Add yaml parser functionality and tests 01/161501/7
authorLeszek Zygo <l.zygo@samsung.com>
Tue, 24 Oct 2017 10:16:44 +0000 (12:16 +0200)
committerLeszek Zygo <l.zygo@samsung.com>
Mon, 4 Dec 2017 13:05:11 +0000 (14:05 +0100)
Change-Id: Iab4513293fbee901798c43f178ded8ee73585c9a
Signed-off-by: Leszek Zygo <l.zygo@samsung.com>
parser/parser.go [new file with mode: 0644]
parser/parser_suite_test.go [new file with mode: 0644]
parser/weles_parser_test.go [new file with mode: 0644]
parser_support.go [new file with mode: 0644]

diff --git a/parser/parser.go b/parser/parser.go
new file mode 100644 (file)
index 0000000..7457f4a
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ *  Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ */
+
+package parser
+
+import (
+       "errors"
+
+       "gopkg.in/yaml.v2"
+
+       "git.tizen.org/tools/weles"
+)
+
+func validatePriority(conf weles.Config) error {
+       switch conf.Priority {
+       case weles.LOW, weles.MEDIUM, weles.HIGH:
+       default:
+               return errors.New("invalid priority")
+       }
+       return nil
+}
+
+// Parser type implements Parser interface.
+type Parser struct{}
+
+// ParseYaml parses yaml content and validates the results.
+// Caller should make sure that input yaml fits to required format (sample_yaml),
+// if not an empty Config and error will be returned.
+func (p *Parser) ParseYaml(in []byte) (*weles.Config, error) {
+       var conf weles.Config
+       err := yaml.Unmarshal(in, &conf)
+       if err != nil {
+               return nil, err
+       }
+
+       err = validatePriority(conf)
+       if err != nil {
+               return nil, err
+       }
+
+       return &conf, nil
+}
diff --git a/parser/parser_suite_test.go b/parser/parser_suite_test.go
new file mode 100644 (file)
index 0000000..d7e702c
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ *  Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ */
+
+package parser_test
+
+import (
+       . "github.com/onsi/ginkgo"
+       . "github.com/onsi/gomega"
+
+       "testing"
+)
+
+func TestParser(t *testing.T) {
+       RegisterFailHandler(Fail)
+       RunSpecs(t, "Parser Suite")
+}
diff --git a/parser/weles_parser_test.go b/parser/weles_parser_test.go
new file mode 100644 (file)
index 0000000..6ee058b
--- /dev/null
@@ -0,0 +1,315 @@
+/*
+ *  Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ */
+
+package parser_test
+
+import (
+       "time"
+
+       . "github.com/onsi/ginkgo"
+       . "github.com/onsi/gomega"
+
+       "git.tizen.org/tools/weles"
+       "git.tizen.org/tools/weles/parser"
+)
+
+var expectedConfig = weles.Config{
+       DeviceType: "qemu",
+       JobName:    "qemu-pipeline",
+       Timeouts: weles.Timeouts{
+               JobTimeout:    weles.ValidPeriod(25 * time.Minute),
+               ActionTimeout: weles.ValidPeriod(5 * time.Minute),
+       },
+       Priority: "medium",
+       Action: weles.Action{
+               Deploy: weles.Deploy{
+                       Timeout: weles.ValidPeriod(20 * time.Minute),
+                       Images: []weles.ImageDefinition{
+                               {
+                                       URI:          "https://images.validation.linaro.org/kvm/standard/stretch-1.img.gz",
+                                       ChecksumURI:  "https://images.validation.linaro.org/kvm/standard/stretch-1.md5",
+                                       ChecksumType: "md5",
+                                       Compression:  "gz",
+                                       Path:         "",
+                                       ChecksumPath: "",
+                               },
+                               {
+                                       URI:          "https://images.validation.linaro.org/kvm/standard/stretch-2.img.zip",
+                                       ChecksumURI:  "https://images.validation.linaro.org/kvm/standard/stretch-2.md5",
+                                       ChecksumType: "md5",
+                                       Compression:  "zip",
+                                       Path:         "",
+                                       ChecksumPath: "",
+                               },
+                       },
+                       PartitionLayout: []weles.PartitionDefinition{
+                               {
+                                       ID:        1,
+                                       ImageName: "image_name1_string",
+                                       Size:      "12345",
+                                       Type:      "fat",
+                               },
+                               {
+                                       ID:        2,
+                                       ImageName: "image_name2_string",
+                                       Size:      "23456",
+                                       Type:      "ext2",
+                               },
+                               {
+                                       ID:        3,
+                                       ImageName: "image_name3_string",
+                                       Size:      "34567",
+                                       Type:      "ext3",
+                               },
+                       },
+               },
+               Boot: weles.Boot{
+                       Login:         "root",
+                       Password:      "tizen",
+                       Prompts:       []string{"linaro-test", "root@debian:~#"},
+                       FailureRetry:  2,
+                       Timeout:       weles.ValidPeriod(20 * time.Minute),
+                       InputSequence: "input_sequence_string",
+                       WaitPattern:   "sample pattern 1 we wait for",
+                       WaitTime:      weles.ValidPeriod(4 * time.Minute),
+               },
+               Test: weles.Test{
+                       FailureRetry: 3,
+                       Name:         "kvm-basic-singlenode",
+                       Timeout:      weles.ValidPeriod(5 * time.Minute),
+                       TestCases: []weles.TestCase{
+                               {
+                                       CaseName: "case_name1_string",
+                                       TestActions: []weles.TestAction{
+                                               weles.Boot{
+                                                       Login:         "root",
+                                                       Password:      "tizen",
+                                                       Prompts:       []string{"linaro-test", "root@debian:~#"},
+                                                       FailureRetry:  2,
+                                                       Timeout:       weles.ValidPeriod(20 * time.Minute),
+                                                       InputSequence: "input_sequence_string",
+                                                       WaitPattern:   "sample pattern 1 we wait for",
+                                                       WaitTime:      weles.ValidPeriod(4 * time.Minute),
+                                               },
+                                               weles.Push{
+                                                       URI:     "uri1_string",
+                                                       Dest:    "path1_string",
+                                                       Alias:   "alias1_string",
+                                                       Timeout: weles.ValidPeriod(6 * time.Minute),
+                                                       Path:    "",
+                                               },
+                                               weles.Run{
+                                                       Name:    "name1_string",
+                                                       Timeout: weles.ValidPeriod(2 * time.Minute),
+                                               },
+                                               weles.Pull{
+                                                       Src:     "path2_string",
+                                                       Alias:   "alias2_string",
+                                                       Timeout: weles.ValidPeriod(1 * time.Minute),
+                                                       Path:    "",
+                                               },
+                                       },
+                               },
+                               {
+                                       CaseName: "case_name2_string",
+                                       TestActions: []weles.TestAction{
+                                               weles.Boot{
+                                                       Login:         "root",
+                                                       Password:      "tizen",
+                                                       Prompts:       []string{"linaro-test", "root@debian:~#"},
+                                                       FailureRetry:  2,
+                                                       Timeout:       weles.ValidPeriod(20 * time.Minute),
+                                                       InputSequence: "input_sequence_string",
+                                                       WaitPattern:   "sample pattern 2 we wait for",
+                                                       WaitTime:      weles.ValidPeriod(3 * time.Minute),
+                                               },
+                                               weles.Push{
+                                                       URI:     "uri1_string",
+                                                       Dest:    "path1_string",
+                                                       Alias:   "alias1_string",
+                                                       Timeout: weles.ValidPeriod(4 * time.Minute),
+                                                       Path:    "",
+                                               },
+                                               weles.Push{
+                                                       URI:     "uri1_string",
+                                                       Dest:    "path1_string",
+                                                       Alias:   "alias1_string",
+                                                       Timeout: weles.ValidPeriod(5 * time.Minute),
+                                                       Path:    "",
+                                               },
+                                               weles.Pull{
+                                                       Src:     "path2_string",
+                                                       Alias:   "alias2_string",
+                                                       Timeout: weles.ValidPeriod(2 * time.Minute),
+                                                       Path:    "",
+                                               },
+                                       },
+                               },
+                               {
+                                       CaseName: "case_name3_string",
+                                       TestActions: []weles.TestAction{
+                                               weles.Pull{
+                                                       Src:     "path2_string",
+                                                       Alias:   "alias2_string",
+                                                       Timeout: weles.ValidPeriod(1 * time.Minute),
+                                                       Path:    "",
+                                               },
+                                       },
+                               },
+                       },
+               },
+       },
+}
+
+var input = []byte(`
+device_type: qemu
+job_name: qemu-pipeline
+timeouts:
+  job:
+    minutes: 25     # timeout for the whole job
+  action:
+    minutes: 5      # default timeout applied for each action; can be overriden in the action itself
+priority: medium
+
+actions:
+
+  - deploy:
+      timeout:
+        minutes: 20
+      images:       # list of images
+         - uri: https://images.validation.linaro.org/kvm/standard/stretch-1.img.gz
+           checksum_uri: https://images.validation.linaro.org/kvm/standard/stretch-1.md5
+           checksum_type: md5
+           compression: gz
+         - uri: https://images.validation.linaro.org/kvm/standard/stretch-2.img.zip
+           checksum_uri: https://images.validation.linaro.org/kvm/standard/stretch-2.md5
+           checksum_type: md5
+           compression: zip
+      partition_layout:     # list of partitions structures
+         - id: 1
+           device_name: device_name1_string
+           image_name: image_name1_string
+           size: 12345
+           type: fat
+         - id: 2
+           device_name: device_name2_string
+           image_name: image_name2_string
+           size: 23456
+           type: ext2
+         - id: 3
+           device_name: device_name3_string
+           image_name: image_name3_string
+           size: 34567
+           type: ext3
+  - boot:
+      login: root
+      password: tizen
+      prompts:
+        - 'linaro-test'
+        - 'root@debian:~#'
+      failure_retry: 2
+      timeout:
+        minutes: 20
+      input_sequence: input_sequence_string
+      wait_pattern: 'sample pattern 1 we wait for'
+      wait_time:
+        minutes: 4
+  - test:
+      failure_retry: 3
+      name: kvm-basic-singlenode
+      timeout:
+        minutes: 5
+      test_cases:
+        - case_name: case_name1_string
+          test_actions:
+            - boot:
+                login: root
+                password: tizen
+                prompts:
+                  - 'linaro-test'
+                  - 'root@debian:~#'
+                failure_retry: 2
+                timeout:
+                  minutes: 20
+                input_sequence: input_sequence_string
+                wait_pattern: 'sample pattern 1 we wait for'
+                wait_time:
+                  minutes: 4
+            - push:
+                uri: uri1_string
+                dest: path1_string
+                alias: alias1_string
+                timeout:
+                  minutes: 6
+            - run:
+                name: name1_string
+                timeout:
+                  minutes: 2
+            - pull:
+                src: path2_string
+                alias: alias2_string
+                timeout:
+                  minutes: 1
+        - case_name: case_name2_string
+          test_actions:
+            - boot:
+                login: root
+                password: tizen
+                prompts:
+                  - 'linaro-test'
+                  - 'root@debian:~#'
+                failure_retry: 2
+                timeout:
+                  minutes: 20
+                input_sequence: input_sequence_string
+                wait_pattern: 'sample pattern 2 we wait for'
+                wait_time:
+                  minutes: 3
+            - push:
+                uri: uri1_string
+                dest: path1_string
+                alias: alias1_string
+                timeout:
+                  minutes: 4
+            - push:
+                uri: uri1_string
+                dest: path1_string
+                alias: alias1_string
+                timeout:
+                  minutes: 5
+            - pull:
+                src: path2_string
+                alias: alias2_string
+                timeout:
+                  minutes: 2
+        - case_name: case_name3_string
+          test_actions:
+             - pull:
+                src: path2_string
+                alias: alias2_string
+                timeout:
+                  minutes: 1
+`)
+
+var _ = Describe("WelesParser", func() {
+       It("should parse input bytes into proper config structure", func() {
+               var p parser.Parser
+               conf, err := p.ParseYaml(input)
+               Expect(err).ToNot(HaveOccurred())
+               Expect(conf).To(Equal(&expectedConfig))
+               expectedConfig = weles.Config{}
+       })
+})
diff --git a/parser_support.go b/parser_support.go
new file mode 100644 (file)
index 0000000..5524e2c
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ *  Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ */
+
+package weles
+
+import (
+       "errors"
+       "reflect"
+       "time"
+)
+
+var validTimeouts = map[string]time.Duration{
+       "seconds": time.Second,
+       "minutes": time.Minute,
+       "hours":   time.Hour,
+       "days":    24 * time.Hour,
+}
+
+// UnmarshalYAML unmarshals ValidPeriod type.
+func (t *ValidPeriod) UnmarshalYAML(unmarshal func(interface{}) error) error {
+       var localTime map[string]int
+       err := unmarshal(&localTime)
+       if err != nil {
+               return err
+       }
+
+       for k, v := range validTimeouts {
+               if _v, ok := localTime[k]; ok {
+                       *t = ValidPeriod(v) * ValidPeriod(_v)
+                       return nil
+               }
+       }
+
+       return errors.New("Invalid timeout")
+}
+
+// LocalTestActionContainer contains fields for all types of test cases.
+type LocalTestActionContainer struct {
+       Boot
+       Push
+       Run
+       Pull
+}
+
+// TestActionTab contains all possible test cases.
+type TestActionTab []LocalTestActionContainer
+
+// UnmarshalYAML is an unmarshalling function for TestActions type.
+func (t *TestActions) UnmarshalYAML(unmarshal func(interface{}) error) error {
+       var testAct TestActionTab
+       err := unmarshal(&testAct)
+       if err != nil {
+               return err
+       }
+
+       for _, e := range testAct {
+               if !reflect.DeepEqual(e.Boot, Boot{}) {
+                       b := e.Boot
+                       *t = append(*t, b)
+               }
+               if e.Push != (Push{}) {
+                       p := e.Push
+                       *t = append(*t, p)
+               }
+               if e.Run != (Run{}) {
+                       r := e.Run
+                       *t = append(*t, r)
+               }
+               if e.Pull != (Pull{}) {
+                       p := e.Pull
+                       *t = append(*t, p)
+               }
+       }
+
+       return nil
+}
+
+// LocalActionContainer contains fields for all types of actions.
+type LocalActionContainer Action
+
+// ActionTab contains all possible actions.
+type ActionTab []LocalActionContainer
+
+// UnmarshalYAML is an unmarshalling function for Action type.
+func (a *Action) UnmarshalYAML(unmarshal func(interface{}) error) error {
+       var act ActionTab
+       err := unmarshal(&act)
+       if err != nil {
+               return err
+       }
+
+       for _, e := range act {
+               if !reflect.DeepEqual(e.Deploy, Deploy{}) {
+                       a.Deploy = e.Deploy
+               }
+               if !reflect.DeepEqual(e.Boot, Boot{}) {
+                       a.Boot = e.Boot
+               }
+               if !reflect.DeepEqual(e.Test, Test{}) {
+                       a.Test = e.Test
+               }
+       }
+
+       return nil
+}