Add DeviceCommunicationProvider implementation 47/162647/16
authorAdam Malinowski <a.malinowsk2@partner.samsung.com>
Mon, 27 Nov 2017 05:01:15 +0000 (06:01 +0100)
committerAleksander Mistewicz <a.mistewicz@samsung.com>
Fri, 15 Jun 2018 10:51:19 +0000 (12:51 +0200)
Change-Id: I0b98831d3ee53de05831caf7564363fdf289fcf8
Signed-off-by: Adam Malinowski <a.malinowsk2@partner.samsung.com>
Signed-off-by: Aleksander Mistewicz <a.mistewicz@samsung.com>
manager/dryad/device_communication_provider.go
manager/dryad/device_communication_provider_test.go [new file with mode: 0644]

index f870f14..2fa09a6 100644 (file)
 
 package dryad
 
-// NewDeviceCommunicationProvider is a stub.
+import (
+       "path/filepath"
+       "strings"
+       "time"
+)
+
+// deviceCommunicationProvider implements DeviceCommunicationProvider interface.
+type deviceCommunicationProvider struct {
+       DeviceCommunicationProvider
+       credentials     Credentials
+       sessionProvider SessionProvider
+}
+
+// NewDeviceCommunicationProvider returns new instance of DeviceCommunicationProvider.
 func NewDeviceCommunicationProvider(session SessionProvider) DeviceCommunicationProvider {
+       return &deviceCommunicationProvider{
+               sessionProvider: session,
+       }
+}
+
+// Login is a part of DeviceCommunicationProvider interface.
+func (d *deviceCommunicationProvider) Login(credentials Credentials) error {
+       d.credentials = credentials
+       _, _, err := d.sessionProvider.Exec([]string{"dut_login.sh", d.credentials.Username, d.credentials.Password})
+       return err
+}
+
+// CopyFilesTo function is a part of DeviceCommunicationProvider interface.
+// It uses tmpfs of MuxPi so caller must take into consideration size of all files that are to be copied.
+func (d *deviceCommunicationProvider) CopyFilesTo(src []string, dest string) error {
+       if !strings.HasSuffix(dest, "/") {
+               dest += "/"
+       }
+
+       for _, path := range src {
+               fileName := filepath.Base(path)
+               tmpDst := "/tmp/weles_cft_" + fileName
+
+               err := d.sessionProvider.SendFile(path, tmpDst)
+               if err != nil {
+                       return err
+               }
+
+               _, _, err = d.sessionProvider.Exec([]string{"dut_copyto.sh", tmpDst, dest + fileName})
+               if err != nil {
+                       return err
+               }
+       }
        return nil
 }
+
+// CopyFilesFrom function is a part of DeviceCommunicationProvider interface.
+// It uses tmpfs of MuxPi so caller must take into consideration size of all files that are to be copied.
+func (d *deviceCommunicationProvider) CopyFilesFrom(src []string, dest string) error {
+       for _, path := range src {
+               fileName := filepath.Base(path)
+               tmpDst := "/tmp/weles_cff_" + fileName
+
+               _, _, err := d.sessionProvider.Exec([]string{"dut_copyfrom.sh", path, tmpDst})
+               if err != nil {
+                       return err
+               }
+
+               err = d.sessionProvider.ReceiveFile(tmpDst, dest+fileName)
+               if err != nil {
+                       return err
+               }
+       }
+       return nil
+}
+
+// Exec function is a part of DeviceCommunicationProvider interface.
+func (d *deviceCommunicationProvider) Exec(cmd []string, timeout time.Duration) (stdout, stderr []byte, err error) {
+       return d.sessionProvider.Exec(append([]string{"dut_exec.sh"}, cmd...))
+}
+
+// Close function is a part of DeviceCommunicationProvider interface.
+func (d *deviceCommunicationProvider) Close() error {
+       return nil // Nothing to do for the time.
+}
diff --git a/manager/dryad/device_communication_provider_test.go b/manager/dryad/device_communication_provider_test.go
new file mode 100644 (file)
index 0000000..134a4a3
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ *  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 dryad
+
+import (
+       "io/ioutil"
+       "strconv"
+       "time"
+
+       "os"
+       "path/filepath"
+
+       . "github.com/onsi/ginkgo"
+       . "github.com/onsi/gomega"
+)
+
+var _ = Describe("DeviceCommunicationProvider", func() {
+       var dcp DeviceCommunicationProvider
+       timeout := time.Second * 30
+       onelineCows := `Cows called Daisy Are often lazy. But cows called Brian They be flyin Up in the air And out into space Because of the grass And the gasses it makes!`
+
+       var testFiles []string
+       for i := 1; i < 6; i++ {
+               buff := make([]byte, i*1024*1024)
+               fileName := "/tmp/weles_test_file_" + strconv.FormatUint(uint64(i), 10) + ".bin"
+               ioutil.WriteFile(fileName, buff, 0644)
+               testFiles = append(testFiles, fileName)
+       }
+
+       BeforeEach(func() {
+               if !accessInfoGiven {
+                       Skip("No valid access info to Dryad")
+               }
+               sp := NewSessionProvider(dryadInfo)
+               dcp = NewDeviceCommunicationProvider(sp)
+               sp.DUT()
+               time.Sleep(2 * time.Second)
+               for t := 0; t < 3; t++ { // Try to boot DUT 3 times. For some reason Odroid U3 won't boot every time.
+                       sp.PowerTick()
+                       for i := 0; i < 10; i++ {
+                               time.Sleep(10 * time.Second)
+                               if dcp.Login(Credentials{"", ""}) == nil {
+                                       return
+                               }
+                       }
+               }
+
+               Skip("Target device (DUT) not available.")
+       })
+
+       AfterEach(func() {
+               dcp.Close()
+       })
+
+       It("should 'login' to DUT", func() {
+               err := dcp.Login(Credentials{"", ""})
+               Expect(err).ToNot(HaveOccurred())
+       })
+
+       It("should list / dir", func() {
+               stdout, stderr, err := dcp.Exec([]string{"ls", "-al", "/"}, timeout)
+               Expect(err).ToNot(HaveOccurred())
+               Expect(stdout).ToNot(BeEmpty())
+               Expect(stderr).To(BeEmpty())
+       })
+
+       It("should write and read poem from a file", func() {
+               By("Writing poem to a file")
+               stdout, stderr, err := dcp.Exec([]string{"echo", onelineCows, " \">\" ", flyingCowsPath}, timeout)
+               Expect(err).ToNot(HaveOccurred())
+               Expect(stdout).To(BeEmpty())
+               Expect(stderr).To(BeEmpty())
+
+               By("Reading poem from a file")
+               stdout, stderr, err = dcp.Exec([]string{"cat", flyingCowsPath}, timeout)
+               Expect(err).ToNot(HaveOccurred())
+               Expect(string(stdout[:len(stdout)-2])).To(BeIdenticalTo(onelineCows))
+               Expect(stderr).To(BeEmpty())
+       })
+
+       It("should not read poem from nonexistent file", func() {
+               stdout, stderr, err := dcp.Exec([]string{"cat", flyingCowsPath + ".txt"}, timeout)
+               Expect(err).ToNot(HaveOccurred())                   // When sdb is used no error is returned.
+               Expect(stdout).To(ContainSubstring("No such file")) // And stderr are redirected to stdout.
+               Expect(stderr).To(BeEmpty())
+       })
+
+       It("should transfer files to and from DUT", func() {
+               os.Mkdir("/tmp/dl", 0755)
+
+               By("Sending files to DUT")
+               err := dcp.CopyFilesTo(testFiles, "/tmp/")
+               Expect(err).ToNot(HaveOccurred())
+
+               By("Receiving files from DUT")
+               err = dcp.CopyFilesFrom(testFiles, "/tmp/dl/")
+               Expect(err).ToNot(HaveOccurred())
+               for _, path := range testFiles {
+                       fl, _ := os.Open(path)
+                       ls, _ := fl.Stat()
+                       fr, _ := os.Open("/tmp/dl/" + filepath.Base(path))
+                       rs, _ := fr.Stat()
+                       Expect(ls.Size()).To(BeIdenticalTo(rs.Size()))
+                       fl.Close()
+                       fr.Close()
+               }
+       })
+
+       It("should not transfer files to Dryad's nonexistent directory", func() {
+               err := dcp.CopyFilesTo(testFiles, "/nonexistent_dir/")
+               Expect(err).To(HaveOccurred())
+       })
+
+       It("should not transfer nonexistent file from Dryad's", func() {
+               err := dcp.CopyFilesFrom([]string{"/nonexistent_dir/nonexistent_file"}, "/tmp/dl/")
+               Expect(err).To(HaveOccurred())
+       })
+})