Check dependency tools before running tests
[src/xds/xds-server.git] / test / main_test.go
1 /*
2  * Copyright (C) 2017-2018 "IoT.bzh"
3  * Author Clément Bénier <clement.benier@iot.bzh>
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *   http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 package xdsservertest
18
19 import (
20         "fmt"
21         "io"
22         "log"
23         "os"
24         "os/exec"
25         "sync"
26         "testing"
27         "time"
28
29         common "gerrit.automotivelinux.org/gerrit/src/xds/xds-common.git/golib"
30         "gerrit.automotivelinux.org/gerrit/src/xds/xds-server/lib/xsapiv1"
31         socketio_client "github.com/sebd71/go-socket.io-client"
32 )
33
34 // IOSockClient
35 type IOSockClient struct {
36         URL       string
37         Conn      *socketio_client.Client
38         Options   *socketio_client.Options
39         EmitMutex *sync.Mutex
40         Connected bool
41         //ServerDiscoChan chan Disconnection
42         EscapeKeys []byte
43 }
44
45 //global client
46 var HTTPCli *common.HTTPClient
47 var logDir string
48 var sCli *IOSockClient
49
50 // Debug function used to print debug logs
51 func Debug(t *testing.T, args ...interface{}) {
52         if os.Getenv("VERBOSE") != "" {
53                 t.Log(args...)
54         }
55 }
56
57 // Debugf function used to print debug logs
58 func Debugf(t *testing.T, format string, args ...interface{}) {
59         if os.Getenv("VERBOSE") != "" {
60                 t.Logf(format, args...)
61         }
62 }
63
64 // Copy copies from src to dst until either EOF
65 func Copy(src, dst string) error {
66         in, err := os.Open(src)
67         if err != nil {
68                 return err
69         }
70         defer in.Close()
71
72         out, err := os.Create(dst)
73         if err != nil {
74                 return err
75         }
76         defer out.Close()
77
78         _, err = io.Copy(out, in)
79         if err != nil {
80                 return err
81         }
82         return out.Close()
83 }
84
85 // init function will run once before execution of test functions begins.
86 func init() {
87         // Check dependency
88         err := checkTestDep()
89         if err != nil {
90                 log.Fatal(err)
91         }
92 }
93
94 // isCommandAvailable verify if a command/utility is available
95 func isCommandAvailable(name string) bool {
96         cmd := exec.Command("/bin/sh", "-c", "command -v "+name)
97         if err := cmd.Run(); err != nil {
98                 return false
99         }
100         return true
101 }
102
103 // checkTestDep checks if all dependency tools are available to be able to run tests
104 func checkTestDep() error {
105         for _, cmd := range dependency_tools {
106                 if !isCommandAvailable(cmd) {
107                         return fmt.Errorf(cmd + " is not installed and is mandatory to run tests")
108                 }
109         }
110         return nil
111 }
112
113 // initEnv
114 func initEnv(launchProcess bool) {
115         if launchProcess {
116                 /*kill xds-server if needed*/
117                 cmd := exec.Command("pkill", "-9", "xds-server")
118                 if err := cmd.Start(); err != nil {
119                         log.Fatal(err)
120                 }
121                 cmd.Wait()
122         }
123         /*set environment variable*/
124         rootTestLog := "/tmp/xds-server-test"
125         if err := os.Setenv(envRootCfgDir, rootTestLog); err != nil {
126                 log.Fatal(err)
127         }
128         sdkDir := rootTestLog + "/sdks/"
129         if err := os.Setenv(envXdtSdk, sdkDir); err != nil {
130                 log.Fatal(err)
131         }
132         if err := os.Setenv(envXdsServerWorkspaceDir, rootTestLog); err != nil {
133                 log.Fatal(err)
134         }
135         if err := os.Setenv(envXdsServerRootCfgDir, rootTestLog); err != nil {
136                 log.Fatal(err)
137         }
138         if err := os.Setenv("XDS_LOG_SILLY", "1"); err != nil {
139                 log.Fatal(err)
140         }
141         /*remove and recreate working directories*/
142         os.RemoveAll(rootTestLog)
143         os.MkdirAll(rootTestLog, 0755)
144         logDir = rootTestLog + "/logs/"
145         os.MkdirAll(logDir, 0755)
146 }
147
148 /*prepare xds-server process*/
149 func launchXdsServer(proc **os.Process) *os.File {
150         logFile := logDir + logFileXdsServer
151         file, err := os.OpenFile(logFile, os.O_CREATE|os.O_WRONLY, 0644)
152         if err != nil {
153                 log.Fatal(err)
154         }
155         tmpProc, err := os.StartProcess(argsProcess[0], argsProcess, &os.ProcAttr{
156                 Files: []*os.File{os.Stdin, file, file},
157         })
158         if err != nil {
159                 log.Fatal(err)
160         }
161         *proc = tmpProc
162         return file
163 }
164
165 // getHTTPClient
166 func getHTTPClient(lvl int) (*common.HTTPClient, *os.File) {
167         logFile := logDir + logFileClient
168         file, err := os.OpenFile(logFile, os.O_CREATE|os.O_WRONLY, 0644)
169         if err != nil {
170                 log.Fatal(err)
171         }
172         conf := common.HTTPClientConfig{
173                 URLPrefix:           "/api/v1",
174                 HeaderClientKeyName: "Xds-Sid",
175                 CsrfDisable:         true,
176                 LogOut:              file,
177                 LogPrefix:           "XDSSERVERTEST: ",
178                 LogLevel:            lvl,
179         }
180         HTTPcli, err := common.HTTPNewClient(prefixURL, conf)
181         if err != nil {
182                 log.Fatal(err)
183         }
184         log.Printf("HTTP session ID : %v", HTTPcli.GetClientID())
185         var ver xsapiv1.Version
186         err = HTTPcli.Get("/version", &ver)
187         if err != nil {
188                 log.Fatal(err)
189         }
190         return HTTPcli, file
191 }
192
193 func NewIoSocketClient(url, clientID string) (*IOSockClient, error) {
194         var err error
195
196         sCli := &IOSockClient{
197                 URL:       url,
198                 EmitMutex: &sync.Mutex{},
199                 Options: &socketio_client.Options{
200                         Transport: "websocket",
201                         Header:    make(map[string][]string),
202                 },
203         }
204         sCli.Options.Header["XDS-SID"] = []string{clientID}
205
206         sCli.Conn, err = socketio_client.NewClient(url, sCli.Options)
207         if err != nil {
208                 return nil, fmt.Errorf("IO.socket connection error: " + err.Error())
209         }
210
211         sCli.Conn.On("connection", func() {
212                 sCli.Connected = true
213         })
214
215         sCli.Conn.On("disconnection", func(err error) {
216                 if err != nil {
217                         log.Printf("WS disconnection event with err: %v\n", err)
218                 }
219                 sCli.Connected = false
220         })
221
222         log.Printf("Connect websocket with url=%v clientId=%v\n", prefixURL, HTTPCli.GetClientID())
223         return sCli, nil
224 }
225
226 // TestMain is the main entry point of testsuite
227 func TestMain(m *testing.M) {
228
229         /* useful for debugging, preventing from launching xds-server
230          * it can be launch separately */
231         launchProcess := true
232         log.Printf("TestMain: launchProcess is %v, so launching xds-server", launchProcess)
233         initEnv(launchProcess)
234
235         var proc *os.Process
236         var fileXdsServer *os.File
237         if launchProcess {
238                 fileXdsServer = launchXdsServer(&proc)
239                 go func(p *os.Process) {
240                         log.Print("xds-server is launching")
241                         if status, err := p.Wait(); err != nil {
242                                 log.Fatalf("status=%v\n err=%v\n", status, err)
243                         }
244                 }(proc)
245                 defer fileXdsServer.Close()
246         }
247         time.Sleep(1 * time.Second)
248
249         lvl := common.HTTPLogLevelDebug
250         var fileHTTPClient *os.File
251         HTTPCli, fileHTTPClient = getHTTPClient(lvl)
252         defer fileHTTPClient.Close()
253         var err error
254         sCli, err = NewIoSocketClient(prefixURL, HTTPCli.GetClientID())
255         if err != nil {
256                 log.Fatal(err)
257         }
258
259         if HTTPCli == nil {
260                 log.Fatal("HTTPCLi is nil")
261         }
262         res := m.Run()
263         defer os.Exit(res)
264         proc.Kill()
265 }