/* * Copyright (C) 2017-2018 "IoT.bzh" * Author Clément Bénier * * 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 xdsservertest import ( "fmt" "io" "log" "os" "os/exec" "sync" "testing" "time" common "gerrit.automotivelinux.org/gerrit/src/xds/xds-common.git/golib" "gerrit.automotivelinux.org/gerrit/src/xds/xds-server/lib/xsapiv1" socketio_client "github.com/sebd71/go-socket.io-client" ) // IOSockClient type IOSockClient struct { URL string Conn *socketio_client.Client Options *socketio_client.Options EmitMutex *sync.Mutex Connected bool //ServerDiscoChan chan Disconnection EscapeKeys []byte } //global client var HTTPCli *common.HTTPClient var logDir string var sCli *IOSockClient // Debug function used to print debug logs func Debug(t *testing.T, args ...interface{}) { if os.Getenv("VERBOSE") != "" { t.Log(args...) } } // Debugf function used to print debug logs func Debugf(t *testing.T, format string, args ...interface{}) { if os.Getenv("VERBOSE") != "" { t.Logf(format, args...) } } // Copy copies from src to dst until either EOF func Copy(src, dst string) error { in, err := os.Open(src) if err != nil { return err } defer in.Close() out, err := os.Create(dst) if err != nil { return err } defer out.Close() _, err = io.Copy(out, in) if err != nil { return err } return out.Close() } // init function will run once before execution of test functions begins. func init() { // Check dependency err := checkTestDep() if err != nil { log.Fatal(err) } } // isCommandAvailable verify if a command/utility is available func isCommandAvailable(name string) bool { cmd := exec.Command("/bin/sh", "-c", "command -v "+name) if err := cmd.Run(); err != nil { return false } return true } // checkTestDep checks if all dependency tools are available to be able to run tests func checkTestDep() error { for _, cmd := range dependency_tools { if !isCommandAvailable(cmd) { return fmt.Errorf(cmd + " is not installed and is mandatory to run tests") } } return nil } // initEnv func initEnv(launchProcess bool) { if launchProcess { /*kill xds-server if needed*/ cmd := exec.Command("pkill", "-9", "xds-server") if err := cmd.Start(); err != nil { log.Fatal(err) } cmd.Wait() } /*set environment variable*/ rootTestLog := "/tmp/xds-server-test" if err := os.Setenv(envRootCfgDir, rootTestLog); err != nil { log.Fatal(err) } sdkDir := rootTestLog + "/sdks/" if err := os.Setenv(envXdtSdk, sdkDir); err != nil { log.Fatal(err) } if err := os.Setenv(envXdsServerWorkspaceDir, rootTestLog); err != nil { log.Fatal(err) } if err := os.Setenv(envXdsServerRootCfgDir, rootTestLog); err != nil { log.Fatal(err) } if err := os.Setenv("XDS_LOG_SILLY", "1"); err != nil { log.Fatal(err) } /*remove and recreate working directories*/ os.RemoveAll(rootTestLog) os.MkdirAll(rootTestLog, 0755) logDir = rootTestLog + "/logs/" os.MkdirAll(logDir, 0755) } /*prepare xds-server process*/ func launchXdsServer(proc **os.Process) *os.File { logFile := logDir + logFileXdsServer file, err := os.OpenFile(logFile, os.O_CREATE|os.O_WRONLY, 0644) if err != nil { log.Fatal(err) } tmpProc, err := os.StartProcess(argsProcess[0], argsProcess, &os.ProcAttr{ Files: []*os.File{os.Stdin, file, file}, }) if err != nil { log.Fatal(err) } *proc = tmpProc return file } // getHTTPClient func getHTTPClient(lvl int) (*common.HTTPClient, *os.File) { logFile := logDir + logFileClient file, err := os.OpenFile(logFile, os.O_CREATE|os.O_WRONLY, 0644) if err != nil { log.Fatal(err) } conf := common.HTTPClientConfig{ URLPrefix: "/api/v1", HeaderClientKeyName: "Xds-Sid", CsrfDisable: true, LogOut: file, LogPrefix: "XDSSERVERTEST: ", LogLevel: lvl, } HTTPcli, err := common.HTTPNewClient(prefixURL, conf) if err != nil { log.Fatal(err) } log.Printf("HTTP session ID : %v", HTTPcli.GetClientID()) var ver xsapiv1.Version err = HTTPcli.Get("/version", &ver) if err != nil { log.Fatal(err) } return HTTPcli, file } func NewIoSocketClient(url, clientID string) (*IOSockClient, error) { var err error sCli := &IOSockClient{ URL: url, EmitMutex: &sync.Mutex{}, Options: &socketio_client.Options{ Transport: "websocket", Header: make(map[string][]string), }, } sCli.Options.Header["XDS-SID"] = []string{clientID} sCli.Conn, err = socketio_client.NewClient(url, sCli.Options) if err != nil { return nil, fmt.Errorf("IO.socket connection error: " + err.Error()) } sCli.Conn.On("connection", func() { sCli.Connected = true }) sCli.Conn.On("disconnection", func(err error) { if err != nil { log.Printf("WS disconnection event with err: %v\n", err) } sCli.Connected = false }) log.Printf("Connect websocket with url=%v clientId=%v\n", prefixURL, HTTPCli.GetClientID()) return sCli, nil } // TestMain is the main entry point of testsuite func TestMain(m *testing.M) { /* useful for debugging, preventing from launching xds-server * it can be launch separately */ launchProcess := true log.Printf("TestMain: launchProcess is %v, so launching xds-server", launchProcess) initEnv(launchProcess) var proc *os.Process var fileXdsServer *os.File if launchProcess { fileXdsServer = launchXdsServer(&proc) go func(p *os.Process) { log.Print("xds-server is launching") if status, err := p.Wait(); err != nil { log.Fatalf("status=%v\n err=%v\n", status, err) } }(proc) defer fileXdsServer.Close() } time.Sleep(1 * time.Second) lvl := common.HTTPLogLevelDebug var fileHTTPClient *os.File HTTPCli, fileHTTPClient = getHTTPClient(lvl) defer fileHTTPClient.Close() var err error sCli, err = NewIoSocketClient(prefixURL, HTTPCli.GetClientID()) if err != nil { log.Fatal(err) } if HTTPCli == nil { log.Fatal("HTTPCLi is nil") } res := m.Run() defer os.Exit(res) proc.Kill() }