Add Parser implementation with tests 13/162013/8
authorLukasz Wojciechowski <l.wojciechow@partner.samsung.com>
Tue, 14 Nov 2017 10:37:11 +0000 (11:37 +0100)
committerPawel Wieczorek <p.wieczorek2@samsung.com>
Wed, 18 Apr 2018 16:32:31 +0000 (18:32 +0200)
ParserImpl implements parsing phase of Job handling.
It saves yaml file in ArtifactDB, parses it and sets up config.

Change-Id: Icb52b7c1943c29744f82532877aade2bb085c345
Signed-off-by: Lukasz Wojciechowski <l.wojciechow@partner.samsung.com>
controller/parserimpl.go [new file with mode: 0644]
controller/parserimpl_test.go [new file with mode: 0644]

diff --git a/controller/parserimpl.go b/controller/parserimpl.go
new file mode 100644 (file)
index 0000000..613623a
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ *  Copyright (c) 2017-2018 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
+ */
+
+// File controller/parserimpl.go implements Parser.
+
+package controller
+
+import (
+       "fmt"
+       "io/ioutil"
+
+       "git.tizen.org/tools/weles"
+       "git.tizen.org/tools/weles/controller/notifier"
+)
+
+// ParserImpl implements Parser for Controller.
+type ParserImpl struct {
+       // Notifier provides channel for communication with Controller.
+       notifier.Notifier
+       // jobs references Controller's submodule responsible for Jobs management.
+       jobs JobsController
+       // artifacts manages ArtifactsDB.
+       artifacts weles.ArtifactManager
+       // parser creates Job's recipe from yaml.
+       parser weles.Parser
+}
+
+// NewParser creates a new ParserImpl structure setting up references
+// to Weles' modules.
+func NewParser(j JobsController, a weles.ArtifactManager, p weles.Parser) Parser {
+       return &ParserImpl{
+               Notifier:  notifier.NewNotifier(),
+               jobs:      j,
+               artifacts: a,
+               parser:    p,
+       }
+}
+
+// Parse prepares new Job to be processed by saving yaml file in ArtifactDB,
+// parsing yaml and preparing Job's configuration.
+func (h *ParserImpl) Parse(j weles.JobID) {
+       err := h.jobs.SetStatusAndInfo(j, weles.JOB_PARSING, "")
+       if err != nil {
+               h.SendFail(j, fmt.Sprintf("Internal Weles error while changing Job status : %s", err.Error()))
+               return
+       }
+
+       yaml, err := h.jobs.GetYaml(j)
+       if err != nil {
+               h.SendFail(j, fmt.Sprintf("Internal Weles error while getting yaml description : %s", err.Error()))
+               return
+       }
+
+       path, err := h.artifacts.CreateArtifact(weles.ArtifactDescription{
+               JobID: j,
+               Type:  weles.AM_YAMLFILE,
+       })
+       if err != nil {
+               h.SendFail(j, fmt.Sprintf("Internal Weles error while creating file path in ArtifactDB : %s", err.Error()))
+               return
+       }
+
+       err = ioutil.WriteFile(string(path), yaml, 0644)
+       if err != nil {
+               h.SendFail(j, fmt.Sprintf("Internal Weles error while saving file in ArtifactDB : %s", err.Error()))
+               return
+       }
+
+       conf, err := h.parser.ParseYaml(yaml)
+       if err != nil {
+               h.SendFail(j, fmt.Sprintf("Error parsing yaml file : %s", err.Error()))
+               return
+       }
+
+       err = h.jobs.SetConfig(j, *conf)
+       if err != nil {
+               h.SendFail(j, fmt.Sprintf("Internal Weles error while setting config : %s", err.Error()))
+               return
+       }
+
+       h.SendOK(j)
+}
diff --git a/controller/parserimpl_test.go b/controller/parserimpl_test.go
new file mode 100644 (file)
index 0000000..0f48ff3
--- /dev/null
@@ -0,0 +1,178 @@
+/*
+ *  Copyright (c) 2017-2018 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 controller
+
+import (
+       "errors"
+
+       "git.tizen.org/tools/weles"
+       cmock "git.tizen.org/tools/weles/controller/mock"
+       "git.tizen.org/tools/weles/controller/notifier"
+       mock "git.tizen.org/tools/weles/mock"
+       gomock "github.com/golang/mock/gomock"
+       . "github.com/onsi/ginkgo"
+       . "github.com/onsi/gomega"
+)
+
+var _ = Describe("ParserImpl", func() {
+       var r <-chan notifier.Notification
+       var jc *cmock.MockJobsController
+       var am *mock.MockArtifactManager
+       var yp *mock.MockParser
+       var h Parser
+       var ctrl *gomock.Controller
+       j := weles.JobID(0xCAFE)
+       goodpath := weles.ArtifactPath("/tmp/weles_test")
+       badpath := weles.ArtifactPath("/such/path/does/not/exist")
+       config := weles.Config{JobName: "Test name"}
+       yaml := []byte("test yaml")
+       err := errors.New("test error")
+
+       BeforeEach(func() {
+               ctrl = gomock.NewController(GinkgoT())
+
+               jc = cmock.NewMockJobsController(ctrl)
+               am = mock.NewMockArtifactManager(ctrl)
+               yp = mock.NewMockParser(ctrl)
+
+               h = NewParser(jc, am, yp)
+               r = h.Listen()
+       })
+       AfterEach(func() {
+               ctrl.Finish()
+       })
+       Describe("NewParser", func() {
+               It("should create a new object", func() {
+                       Expect(h).NotTo(BeNil())
+                       Expect(h.(*ParserImpl).jobs).To(Equal(jc))
+                       Expect(h.(*ParserImpl).artifacts).To(Equal(am))
+                       Expect(h.(*ParserImpl).parser).To(Equal(yp))
+               })
+       })
+       Describe("Parse", func() {
+               It("should handle job successfully", func() {
+                       gomock.InOrder(
+                               jc.EXPECT().SetStatusAndInfo(j, weles.JOB_PARSING, ""),
+                               jc.EXPECT().GetYaml(j).Return(yaml, nil),
+                               am.EXPECT().CreateArtifact(weles.ArtifactDescription{JobID: j, Type: weles.AM_YAMLFILE}).Return(goodpath, nil),
+                               yp.EXPECT().ParseYaml(yaml).Return(&config, nil),
+                               jc.EXPECT().SetConfig(j, config),
+                       )
+
+                       h.Parse(j)
+
+                       Eventually(r).Should(Receive(Equal(notifier.Notification{
+                               JobID: j,
+                               OK:    true,
+                       })))
+               })
+               It("should fail when unable to set config", func() {
+                       gomock.InOrder(
+                               jc.EXPECT().SetStatusAndInfo(j, weles.JOB_PARSING, ""),
+                               jc.EXPECT().GetYaml(j).Return(yaml, nil),
+                               am.EXPECT().CreateArtifact(weles.ArtifactDescription{JobID: j, Type: weles.AM_YAMLFILE}).Return(goodpath, nil),
+                               yp.EXPECT().ParseYaml(yaml).Return(&config, nil),
+                               jc.EXPECT().SetConfig(j, config).Return(err),
+                       )
+
+                       h.Parse(j)
+
+                       expectedNotification := notifier.Notification{
+                               JobID: j,
+                               OK:    false,
+                               Msg:   "Internal Weles error while setting config : " + err.Error(),
+                       }
+                       Eventually(r).Should(Receive(Equal(expectedNotification)))
+               })
+               It("should fail when unable to parse yaml", func() {
+                       gomock.InOrder(
+                               jc.EXPECT().SetStatusAndInfo(j, weles.JOB_PARSING, ""),
+                               jc.EXPECT().GetYaml(j).Return(yaml, nil),
+                               am.EXPECT().CreateArtifact(weles.ArtifactDescription{JobID: j, Type: weles.AM_YAMLFILE}).Return(goodpath, nil),
+                               yp.EXPECT().ParseYaml(yaml).Return(&weles.Config{}, err),
+                       )
+
+                       h.Parse(j)
+
+                       expectedNotification := notifier.Notification{
+                               JobID: j,
+                               OK:    false,
+                               Msg:   "Error parsing yaml file : " + err.Error(),
+                       }
+                       Eventually(r).Should(Receive(Equal(expectedNotification)))
+               })
+               It("should fail when unable to write yaml file", func() {
+                       gomock.InOrder(
+                               jc.EXPECT().SetStatusAndInfo(j, weles.JOB_PARSING, ""),
+                               jc.EXPECT().GetYaml(j).Return(yaml, nil),
+                               am.EXPECT().CreateArtifact(weles.ArtifactDescription{JobID: j, Type: weles.AM_YAMLFILE}).Return(badpath, nil),
+                       )
+
+                       h.Parse(j)
+
+                       expectedNotification := notifier.Notification{
+                               JobID: j,
+                               OK:    false,
+                               Msg:   "Internal Weles error while saving file in ArtifactDB : " + "open " + string(badpath) + ": no such file or directory",
+                       }
+                       Eventually(r).Should(Receive(Equal(expectedNotification)))
+               })
+               It("should fail when unable to create path in ArtifactDB", func() {
+                       gomock.InOrder(
+                               jc.EXPECT().SetStatusAndInfo(j, weles.JOB_PARSING, ""),
+                               jc.EXPECT().GetYaml(j).Return(yaml, nil),
+                               am.EXPECT().CreateArtifact(weles.ArtifactDescription{JobID: j, Type: weles.AM_YAMLFILE}).Return(weles.ArtifactPath(""), err),
+                       )
+
+                       h.Parse(j)
+
+                       expectedNotification := notifier.Notification{
+                               JobID: j,
+                               OK:    false,
+                               Msg:   "Internal Weles error while creating file path in ArtifactDB : " + err.Error(),
+                       }
+                       Eventually(r).Should(Receive(Equal(expectedNotification)))
+               })
+               It("should fail when unable to get yaml", func() {
+                       gomock.InOrder(
+                               jc.EXPECT().SetStatusAndInfo(j, weles.JOB_PARSING, ""),
+                               jc.EXPECT().GetYaml(j).Return([]byte{}, err),
+                       )
+
+                       h.Parse(j)
+
+                       expectedNotification := notifier.Notification{
+                               JobID: j,
+                               OK:    false,
+                               Msg:   "Internal Weles error while getting yaml description : " + err.Error(),
+                       }
+                       Eventually(r).Should(Receive(Equal(expectedNotification)))
+               })
+               It("should fail when unable to change job status", func() {
+                       jc.EXPECT().SetStatusAndInfo(j, weles.JOB_PARSING, "").Return(err)
+
+                       h.Parse(j)
+
+                       expectedNotification := notifier.Notification{
+                               JobID: j,
+                               OK:    false,
+                               Msg:   "Internal Weles error while changing Job status : " + err.Error(),
+                       }
+                       Eventually(r).Should(Receive(Equal(expectedNotification)))
+               })
+       })
+})