/*
* Copyright (C) 2017-2018 "IoT.bzh"
* Author Clément Bénier <clement.benier@iot.bzh>
*
* 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()
}
func initEnv(launchProcess bool) {
if launchProcess {
/*kill xds-server if needed*/
cmd := exec.Command("killall", "-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
}
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
}
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()
}