Merge remote-tracking branch 'origin/sandbox/benierc/test' 11/16211/1
authorClément Bénier <clement.benier@iot.bzh>
Tue, 21 Aug 2018 16:58:26 +0000 (18:58 +0200)
committerClément Bénier <clement.benier@iot.bzh>
Tue, 21 Aug 2018 16:58:32 +0000 (18:58 +0200)
Change-Id: Idc200f10e217119df9edfebbaf839c5fd45b19a4
Signed-off-by: Clément Bénier <clement.benier@iot.bzh>
18 files changed:
.vscode/launch.json
.vscode/settings.json
Makefile
glide.yaml
test/_test-config.json [new file with mode: 0644]
test/config.go [new file with mode: 0644]
test/config_test.go [new file with mode: 0644]
test/exec_test.go [new file with mode: 0644]
test/fixtures/helloworld/CMakeLists.txt [new file with mode: 0644]
test/fixtures/helloworld/conf.d/cmake/config.cmake [new file with mode: 0644]
test/fixtures/helloworld/helloworld/CMakeLists.txt [new file with mode: 0644]
test/fixtures/helloworld/helloworld/helloworld.c [new file with mode: 0644]
test/fixtures/poky-agl-glibc-x86_64-gcc_crosssdk-native_x86_64-toolchain-1.0.2.sh [new file with mode: 0755]
test/folders_test.go [new file with mode: 0644]
test/main_test.go [new file with mode: 0644]
test/sdks_test.go [new file with mode: 0644]
test/target_test.go [new file with mode: 0644]
test/version_test.go [new file with mode: 0644]

index 7c3d99c..c12c80c 100644 (file)
             "args": ["-log", "debug"],
             "showLog": false
         },
+        {
+            "name": "XDS-Server-Test",
+            "type": "go",
+            "request": "launch",
+            "mode": "test",
+            "program": "${workspaceRoot}/test",
+            "env": {
+                "GOPATH": "${workspaceRoot}/../../../../../..:${env:GOPATH}",
+            },
+            "args": ["-test.v", "-test.run", ".*"],
+            "showLog": false
+        },
         {
             "name": "XDS-Server local dev",
             "type": "go",
index c556d7f..45cbe81 100644 (file)
@@ -21,7 +21,8 @@
         "bin": true,
         "tools": true,
         "webapp/dist": true,
-        "webapp/node_modules": true
+        "webapp/node_modules": true,
+        "**/*~": true
     },
     // Specify paths/files to ignore. (Supports Globs)
     "cSpell.ignorePaths": [
index 705b670..f7f7a9a 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -120,7 +120,11 @@ xds: scripts tools/syncthing/copytobin
        @cd $(ROOT_SRCDIR); $(BUILD_ENV_FLAGS) go build $(VERBOSE_$(V)) -i -o $(LOCAL_BINDIR)/$(TARGET)$(EXT) -ldflags "$(GO_LDFLAGS) -X main.AppVersion=$(VERSION) -X main.AppSubVersion=$(SUB_VERSION)" -gcflags "$(GO_GCFLAGS)" .
 
 test: tools/glide
-       go test --race $(shell $(LOCAL_TOOLSDIR)/glide novendor)
+ifndef name
+       go test --race ./test -v
+else
+       go test --race ./test -v -run $(name)
+endif
 
 vet: tools/glide
        go vet $(shell $(LOCAL_TOOLSDIR)/glide novendor)
index 6aeee9f..69ee318 100644 (file)
@@ -33,3 +33,9 @@ import:
   version: ^1.0.0
 - package: github.com/franciscocpg/reflectme
   version: ^0.1.9
+- package: "github.com/stretchr/testify"
+  version: ^1.2.2
+  subpackages:
+  - assert
+- package: github.com/sebd71/go-socket.io-client
+  version: 46defcb47f
diff --git a/test/_test-config.json b/test/_test-config.json
new file mode 100644 (file)
index 0000000..223b3eb
--- /dev/null
@@ -0,0 +1,8 @@
+{
+    "webAppDir": "${EXEPATH}/../webapp/src",
+    "httpPort": "8000",
+    "sdkScriptsDir": "${EXEPATH}/../sdks",
+    "shareRootDir": "${XDS_SERVER_ROOT_CFG_DIR}/xds-server/projects",
+    "logsDir": "${XDS_SERVER_ROOT_CFG_DIR}/xds-server/logs",
+    "sdkRootDir": "${EXEPATH}/xds-server/sdk"
+}
diff --git a/test/config.go b/test/config.go
new file mode 100644 (file)
index 0000000..4850919
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * 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
+
+var argsProcess = []string{"../bin/xds-server", "-l", "debug", "-c", "_test-config.json"}
+
+const (
+       envRootCfgDir            = "XDS_SERVER_ROOT_CFG_DIR"
+       prefixURL                = "http://localhost:8000"
+       logFileXdsServer         = "xdsserver-test.log"
+       logFileClient            = "client-test.log"
+       envXdtSdk                = "XDT_SDK"
+       envXdsServerWorkspaceDir = "XDS_SERVER_WORKSPACE_DIR"
+       envXdsServerRootCfgDir   = "XDS_SERVER_ROOT_CFG_DIR"
+       sdkFileName              = "poky-agl-glibc-x86_64-gcc_crosssdk-native_x86_64-toolchain-1.0.2.sh"
+       sdkFile                  = "fixtures/" + sdkFileName
+       helloworldFixturesDir    = "fixtures/helloworld"
+)
diff --git a/test/config_test.go b/test/config_test.go
new file mode 100644 (file)
index 0000000..2b95e85
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * 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 (
+       "net"
+       "regexp"
+       "strings"
+       "testing"
+
+       "gerrit.automotivelinux.org/gerrit/src/xds/xds-server/lib/xsapiv1"
+       "github.com/stretchr/testify/assert"
+)
+
+func CheckIP(ipconfig string) bool {
+       ifaces, _ := net.Interfaces()
+       for _, i := range ifaces {
+               addrs, _ := i.Addrs()
+               for _, addr := range addrs {
+                       if strings.HasPrefix(addr.String(), ipconfig) {
+                               return true
+                       }
+               }
+       }
+       return false
+}
+
+func TestConfig(t *testing.T) {
+       var cfg xsapiv1.APIConfig
+       assert.Nil(t, HTTPCli.Get("/config", &cfg))
+       Debugf(t, "Config is %v", cfg)
+
+       re := regexp.MustCompile("^[0-9a-z]+-[0-9a-z]+-[0-9a-z]+-[0-9a-z]+-[0-9a-z]+$")
+       assert.True(t, re.MatchString(cfg.ServerUID)) //ID
+       pathMap, present := cfg.SupportedSharing["PathMap"]
+       assert.True(t, present)
+       assert.True(t, pathMap)
+       assert.True(t, CheckIP(cfg.Builder.IP))
+}
diff --git a/test/exec_test.go b/test/exec_test.go
new file mode 100644 (file)
index 0000000..884ba87
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ * 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 (
+       "bytes"
+       "os"
+       "os/exec"
+       "path"
+       "testing"
+
+       "gerrit.automotivelinux.org/gerrit/src/xds/xds-server/lib/xsapiv1"
+       "github.com/stretchr/testify/assert"
+)
+
+func InitExec(t *testing.T) string {
+       Debugf(t, "Create helloworld directory with app-templates")
+       /*copy helloworld from fixtures to envRootCfgDir*/
+       helloworldDir := path.Join(os.Getenv(envRootCfgDir), "helloworld")
+       cmd := exec.Command("cp", "-r", helloworldFixturesDir, helloworldDir)
+       var out bytes.Buffer
+       cmd.Stdout = &out
+       assert.Nil(t, cmd.Run())
+
+       /*clone submodules app templates into helloworld*/
+       subHelloworldAppTemplateDir := path.Join(helloworldDir, "conf.d", "app-templates")
+       cmd = exec.Command("git", "clone", "https://gerrit.automotivelinux.org/gerrit/p/apps/app-templates.git", subHelloworldAppTemplateDir)
+       assert.Nil(t, cmd.Run())
+       return helloworldDir
+}
+
+func TestExec(t *testing.T) {
+       helloworldDir := InitExec(t)
+       /*channel for SDK events*/
+       chSdks := make(chan xsapiv1.SDK)
+       defer close(chSdks)
+       sdk := xsapiv1.SDKInstallArgs{
+               ID:       "",
+               Filename: sdkFileName,
+               Force:    false,
+       }
+       ConnectSDKStateChange(t, sCli, chSdks)
+       sdkRes := installFakeSdk(t, sdk, chSdks)
+
+       /*check there is no project*/
+       var cfgArray []xsapiv1.FolderConfig
+       assert.Nil(t, HTTPCli.Get("/folders", &cfgArray))
+       assert.Equal(t, len(cfgArray), 0)
+
+       fPrj := xsapiv1.FolderConfig{
+               Label:      "testproject",
+               ClientPath: helloworldDir,
+               Type:       xsapiv1.TypePathMap,
+               ClientData: "clientdatatest",
+               DataPathMap: xsapiv1.PathMapConfig{
+                       ServerPath: helloworldDir,
+               },
+       }
+       /*create project*/
+       var cfg xsapiv1.FolderConfig
+       assert.Nil(t, HTTPCli.Post("/folders", fPrj, &cfg))
+       assert.NotNil(t, cfg)
+
+       /*channel for ExecOutMsg*/
+       chExec := make(chan xsapiv1.ExecExitMsg)
+       defer close(chExec)
+       /*connect to ExecOutEvent*/
+       sCli.Conn.On(xsapiv1.ExecExitEvent, func(ev xsapiv1.ExecExitMsg) {
+               chExec <- ev
+       })
+
+       /*cmake helloworld project with fake sdk*/
+       sdkSourceFile := path.Join(sdkRes.Path, "environment-setup-corei7-64-native-linux")
+       cmd := "source " + sdkSourceFile
+       cmd = cmd + " && "
+       cmd = cmd + "unset SDKTARGETSYSROOT"
+       cmd = cmd + " && "
+       cmd = cmd + "cd " + fPrj.ClientPath
+       cmd = cmd + " && "
+       cmd = cmd + "mkdir -p build"
+       cmd = cmd + " && "
+       cmd = cmd + "cd build"
+       cmd = cmd + " && "
+       cmd = cmd + "cmake .."
+
+       /*post exec cmd cmake*/
+       exec := xsapiv1.ExecArgs{
+               ID:  cfg.ID,
+               Cmd: cmd,
+       }
+       var execRes xsapiv1.ExecArgs
+       Debugf(t, "exec cmake cmd(%v)", cmd)
+       assert.Nil(t, HTTPCli.Post("/exec", exec, &execRes))
+       exitMsg := <-chExec
+       assert.Equal(t, exitMsg.Code, 0)
+
+       /*make helloworld project with fake sdk*/
+       cmd = "source " + sdkSourceFile
+       cmd = cmd + " && "
+       cmd = cmd + "unset SDKTARGETSYSROOT"
+       cmd = cmd + " && "
+       cmd = cmd + "cd " + fPrj.ClientPath
+       cmd = cmd + "&&"
+       cmd = cmd + "cd build"
+       cmd = cmd + "&&"
+       cmd = cmd + "make"
+       exec.Cmd = cmd
+       /*post exec cmd make*/
+       Debugf(t, "exec make cmd(%v)", cmd)
+       assert.Nil(t, HTTPCli.Post("/exec", exec, &execRes))
+       exitMsg = <-chExec
+       assert.Equal(t, exitMsg.Code, 0)
+
+       /*check if helloworld.so exists*/
+       Debug(t, "check that helloworld.so exists")
+       _, err := os.Stat(path.Join(fPrj.ClientPath, "build/helloworld/helloworld.so"))
+       assert.Nil(t, err)
+
+       /*deinit*/
+       assert.Nil(t, HTTPCli.Delete("/folders/"+cfg.ID, &cfg))
+       RemoveSdk(t, sdkRes, chSdks)
+       DisconnectSDKStateChange(t, sCli)
+}
diff --git a/test/fixtures/helloworld/CMakeLists.txt b/test/fixtures/helloworld/CMakeLists.txt
new file mode 100644 (file)
index 0000000..f757721
--- /dev/null
@@ -0,0 +1,3 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 3.3)
+
+include(${CMAKE_CURRENT_SOURCE_DIR}/conf.d/cmake/config.cmake)
diff --git a/test/fixtures/helloworld/conf.d/cmake/config.cmake b/test/fixtures/helloworld/conf.d/cmake/config.cmake
new file mode 100644 (file)
index 0000000..00b4de1
--- /dev/null
@@ -0,0 +1,167 @@
+###########################################################################
+# Copyright 2015, 2016, 2017 IoT.bzh
+#
+# author: Fulup Ar Foll <fulup@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.
+###########################################################################
+
+# Project Info
+# ------------------
+set(PROJECT_NAME helloworld)
+set(PROJECT_VERSION "1.0")
+set(PROJECT_PRETTY_NAME "Helloworld")
+set(PROJECT_DESCRIPTION "Provide an Helloworld program")
+set(PROJECT_AUTHOR "Iot-Team")
+set(PROJECT_AUTHOR_MAIL "secretaria@iot.bzh")
+set(PROJECT_LICENSE "APL2.0")
+set(PROJECT_LANGUAGES,"C")
+
+# Where are stored default templates files from submodule or subtree app-templates in your project tree
+# relative to the root project directory
+set(PROJECT_APP_TEMPLATES_DIR "conf.d/app-templates")
+
+# Where are stored your external libraries for your project. This is 3rd party library that you don't maintain
+# but used and must be built and linked.
+# set(PROJECT_LIBDIR "libs")
+
+# Where are stored data for your application. Pictures, static resources must be placed in that folder.
+# set(PROJECT_RESOURCES "data")
+
+# Which directories inspect to find CMakeLists.txt target files
+# set(PROJECT_SRC_DIR_PATTERN "*")
+
+# Compilation Mode (DEBUG, RELEASE)
+# ----------------------------------
+set(CMAKE_BUILD_TYPE "DEBUG")
+
+# Kernel selection if needed. You can choose between a
+# mandatory version to impose a minimal version.
+# Or check Kernel minimal version and just print a Warning
+# about missing features and define a preprocessor variable
+# to be used as preprocessor condition in code to disable
+# incompatibles features. Preprocessor define is named
+# KERNEL_MINIMAL_VERSION_OK.
+#
+# NOTE*** FOR NOW IT CHECKS KERNEL Yocto environment and
+# Yocto SDK Kernel version.
+# -----------------------------------------------
+#set (kernel_mandatory_version 4.8)
+#set (kernel_minimal_version 4.8)
+
+# Compiler selection if needed. Impose a minimal version.
+# -----------------------------------------------
+set (gcc_minimal_version 4.9)
+
+# PKG_CONFIG required packages
+# -----------------------------
+
+
+# Print a helper message when every thing is finished
+# ----------------------------------------------------
+
+# Customize link option
+# -----------------------------
+#list(APPEND link_libraries -an-option)
+
+# Compilation options definition
+# Use CMake generator expressions to specify only for a specific language
+# Values are prefilled with default options that is currently used.
+# Either separate options with ";", or each options must be quoted separately
+# DO NOT PUT ALL OPTION QUOTED AT ONCE , COMPILATION COULD FAILED !
+# ----------------------------------------------------------------------------
+#set(COMPILE_OPTIONS "-Wall" "-Wextra" "-Wconversion" "-Wno-unused-parameter" "-Wno-sign-compare" "-Wno-sign-conversion" "-Werror=maybe-uninitialized" "-Werror=implicit-function-declaration" "-ffunction-sections" "-fdata-sections" "-fPIC" CACHE STRING "Compilation flags")
+#set(C_COMPILE_OPTIONS "" CACHE STRING "Compilation flags for C language.")
+#set(CXX_COMPILE_OPTIONS "" CACHE STRING "Compilation flags for C++ language.")
+#set(PROFILING_COMPILE_OPTIONS "-g" "-O0" "-pg" "-Wp,-U_FORTIFY_SOURCE" CACHE STRING "Compilation flags for PROFILING build type.")
+#set(DEBUG_COMPILE_OPTIONS "-g" "-ggdb" "-Wp,-U_FORTIFY_SOURCE" CACHE STRING "Compilation flags for DEBUG build type.")
+#set(CCOV_COMPILE_OPTIONS "-g" "-O2" "--coverage" CACHE STRING "Compilation flags for CCOV build type.")
+#set(RELEASE_COMPILE_OPTIONS "-g" "-O2" CACHE STRING "Compilation flags for RELEASE build type.")
+
+# Print a helper message when every thing is finished
+# ----------------------------------------------------
+#set(CLOSING_MESSAGE "")
+#set(PACKAGE_MESSAGE "Install widget file using in the target : afm-util install ${PROJECT_NAME}.wgt")
+
+# (BUG!!!) as PKG_CONFIG_PATH does not work [should be an env variable]
+# ---------------------------------------------------------------------
+set(CMAKE_INSTALL_PREFIX $ENV{HOME}/opt)
+set(CMAKE_PREFIX_PATH ${CMAKE_INSTALL_PREFIX}/lib64/pkgconfig ${CMAKE_INSTALL_PREFIX}/lib/pkgconfig)
+set(LD_LIBRARY_PATH ${CMAKE_INSTALL_PREFIX}/lib64 ${CMAKE_INSTALL_PREFIX}/lib)
+
+
+# Mandatory widget Mimetype specification of the main unit
+# --------------------------------------------------------------------------
+# Choose between :
+#- text/html : HTML application,
+#      content.src designates the home page of the application
+#
+#- application/vnd.agl.native : AGL compatible native,
+#      content.src designates the relative path of the binary.
+#
+# - application/vnd.agl.service: AGL service, content.src is not used.
+#
+#- ***application/x-executable***: Native application,
+#      content.src designates the relative path of the binary.
+#      For such application, only security setup is made.
+#
+set(WIDGET_TYPE application/vnd.agl.service)
+
+# Mandatory Widget entry point file of the main unit
+# --------------------------------------------------------------
+# This is the file that will be executed, loaded,
+# at launch time by the application framework.
+#
+set(WIDGET_ENTRY_POINT config.xml)
+
+# Optional dependencies order
+# ---------------------------
+#set(EXTRA_DEPENDENCIES_ORDER)
+
+# Optional Extra global include path
+# -----------------------------------
+#set(EXTRA_INCLUDE_DIRS)
+
+# Optional extra libraries
+# -------------------------
+#set(EXTRA_LINK_LIBRARIES)
+
+# Optional force binding installation
+# ------------------------------------
+# set(BINDINGS_INSTALL_PREFIX PrefixPath )
+
+# Optional force binding Linking flag
+# ------------------------------------
+# set(BINDINGS_LINK_FLAG LinkOptions )
+
+# Optional force package prefix generation, like widget
+# -----------------------------------------------------
+# set(PKG_PREFIX DestinationPath)
+
+# Optional Application Framework security token
+# and port use for remote debugging.
+#------------------------------------------------------------
+#set(AFB_TOKEN   ""      CACHE PATH "Default AFB_TOKEN")
+#set(AFB_REMPORT "1234" CACHE PATH "Default AFB_TOKEN")
+
+# Optional schema validator about now only XML, LUA and JSON
+# are supported
+#------------------------------------------------------------
+#set(LUA_CHECKER "luac" CACHE STRING "LUA compiler")
+#set(XML_CHECKER "xmllint" CACHE STRING "XML linter")
+#set(JSON_CHECKER "json_verify" CACHE STRING "JSON linter")
+
+# This include is mandatory and MUST happens at the end
+# of this file, else you expose you to unexpected behavior
+# -----------------------------------------------------------
+include(${PROJECT_APP_TEMPLATES_DIR}/cmake/common.cmake)
diff --git a/test/fixtures/helloworld/helloworld/CMakeLists.txt b/test/fixtures/helloworld/helloworld/CMakeLists.txt
new file mode 100644 (file)
index 0000000..373a6f5
--- /dev/null
@@ -0,0 +1,36 @@
+###########################################################################
+# Copyright 2015, 2016, 2017 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.
+###########################################################################
+
+# Add target to project dependency list
+PROJECT_TARGET_ADD(helloworld)
+
+    # Define project Targets
+    file(GLOB sourcelist "*.c")
+
+    # Define project Targets
+    ADD_LIBRARY(${TARGET_NAME} MODULE ${sourcelist})
+
+    # Binder exposes a unique public entry point
+    SET_TARGET_PROPERTIES(${TARGET_NAME} PROPERTIES
+       PREFIX ""
+        LABELS "BINDING"
+       LINK_FLAGS  ${BINDINGS_LINK_FLAG}
+        OUTPUT_NAME ${TARGET_NAME}
+    )
+
+    TARGET_LINK_LIBRARIES(${TARGET_NAME}
+           ${link_libraries}
+    )
diff --git a/test/fixtures/helloworld/helloworld/helloworld.c b/test/fixtures/helloworld/helloworld/helloworld.c
new file mode 100644 (file)
index 0000000..94ebcdc
--- /dev/null
@@ -0,0 +1,6 @@
+#include <stdio.h>
+
+int main() {
+    printf ("Hello, World!\n");
+    return 0;
+}
diff --git a/test/fixtures/poky-agl-glibc-x86_64-gcc_crosssdk-native_x86_64-toolchain-1.0.2.sh b/test/fixtures/poky-agl-glibc-x86_64-gcc_crosssdk-native_x86_64-toolchain-1.0.2.sh
new file mode 100755 (executable)
index 0000000..7781335
Binary files /dev/null and b/test/fixtures/poky-agl-glibc-x86_64-gcc_crosssdk-native_x86_64-toolchain-1.0.2.sh differ
diff --git a/test/folders_test.go b/test/folders_test.go
new file mode 100644 (file)
index 0000000..10f1dc6
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+ * 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 (
+       "io/ioutil"
+       "os"
+       "regexp"
+       "testing"
+
+       "gerrit.automotivelinux.org/gerrit/src/xds/xds-server/lib/xsapiv1"
+       "github.com/stretchr/testify/assert"
+)
+
+func TestFolders(t *testing.T) {
+       /*init: check there is no folder*/
+       Debug(t, "check there is no folder")
+       var cfgArray []xsapiv1.FolderConfig
+       assert.Nil(t, HTTPCli.Get("/folders", &cfgArray))
+       assert.Equal(t, len(cfgArray), 0)
+
+       fPrj := xsapiv1.FolderConfig{
+               Label:      "testproject",
+               ClientPath: logDir + "testproject",
+               Type:       xsapiv1.TypePathMap,
+               ClientData: "clientdatatest",
+               DataPathMap: xsapiv1.PathMapConfig{
+                       ServerPath: logDir + "testserverpath",
+               },
+       }
+       var cfg xsapiv1.FolderConfig
+       Debugf(t, "create folder: \n%v", fPrj)
+       assert.Nil(t, HTTPCli.Post("/folders", fPrj, &cfg))
+       assert.NotNil(t, cfg)
+       Debugf(t, "result folder: \n%v", cfg)
+
+       isCfgPrjMatch := func(fPrj xsapiv1.FolderConfig, cfg xsapiv1.FolderConfig) {
+               re := regexp.MustCompile("^[0-9a-z]+-[0-9a-z]+-[0-9a-z]+-[0-9a-z]+-[0-9a-z]+$")
+               assert.True(t, re.MatchString(cfg.ID)) //ID
+               assert.Equal(t, cfg.Label, fPrj.Label) //Label
+               assert.Equal(t, cfg.ClientPath, fPrj.ClientPath)
+               assert.Equal(t, cfg.Type, fPrj.Type)
+               assert.Equal(t, cfg.Status, "Enable")
+               assert.Equal(t, cfg.IsInSync, true)
+               assert.Equal(t, len(cfg.DefaultSdk), 0)
+               assert.Equal(t, fPrj.ClientData, cfg.ClientData)
+               assert.Equal(t, fPrj.DataPathMap.ServerPath, cfg.DataPathMap.ServerPath)
+       }
+       isCfgPrjMatch(fPrj, cfg)
+       var cfg2 xsapiv1.FolderConfig
+       assert.Nil(t, HTTPCli.Get("/folders/"+cfg.ID, &cfg2))
+       isCfgPrjMatch(fPrj, cfg2)
+
+       assert.Nil(t, HTTPCli.Get("/folders", &cfgArray))
+       assert.Equal(t, len(cfgArray), 1)
+
+       //call with the same uid create error
+       assert.NotNil(t, HTTPCli.Post("/folders", cfg, &cfg))
+
+       /*create/delete folders*/
+       var cfgArrayBis []xsapiv1.FolderConfig
+       assert.Nil(t, HTTPCli.Post("/folders", fPrj, &cfg))
+       Debugf(t, "create folder with id=%v", cfg.ID)
+       assert.Nil(t, HTTPCli.Post("/folders", fPrj, &cfg))
+       Debugf(t, "create folder with id=%v", cfg.ID)
+       assert.Nil(t, HTTPCli.Get("/folders", &cfgArray))
+       assert.Equal(t, len(cfgArray), 3)
+       assert.Nil(t, HTTPCli.Delete("/folders/"+cfgArray[1].ID, &cfg))
+       Debugf(t, "delete folder with id=%v", cfg.ID)
+       assert.Equal(t, cfg, cfgArray[1])
+       assert.Nil(t, HTTPCli.Get("/folders", &cfgArrayBis))
+       assert.Equal(t, len(cfgArrayBis), 2)
+       assert.Nil(t, HTTPCli.Delete("/folders/"+cfgArray[0].ID, &cfg))
+       Debugf(t, "delete folder with id=%v", cfg.ID)
+       assert.Equal(t, cfg, cfgArray[0])
+       assert.Nil(t, HTTPCli.Get("/folders", &cfgArrayBis))
+       assert.Equal(t, len(cfgArrayBis), 1)
+       assert.Nil(t, HTTPCli.Delete("/folders/"+cfgArray[2].ID, &cfg))
+       Debugf(t, "delete folder with id=%v", cfg.ID)
+       assert.Equal(t, cfg, cfgArray[2])
+       assert.Nil(t, HTTPCli.Get("/folders", &cfgArrayBis))
+       assert.Equal(t, len(cfgArrayBis), 0)
+}
+
+func TestFoldersEmptyValues(t *testing.T) {
+       fPrj := xsapiv1.FolderConfig{
+               Label:      "testproject",
+               ClientPath: logDir + "testproject",
+               Type:       xsapiv1.TypePathMap,
+               ClientData: "clientdatatest",
+               DataPathMap: xsapiv1.PathMapConfig{
+                       ServerPath: "",
+               },
+       }
+       var cfg xsapiv1.FolderConfig
+       /*ServerPath is empty*/
+       assert.NotNil(t, HTTPCli.Post("/folders", fPrj, &cfg))
+       Debugf(t, "error while creating folder with empty serverpath \n%v", fPrj)
+
+       fPrj.DataPathMap.ServerPath = logDir + "sameserverpath"
+       fPrj.ClientPath = ""
+       /*ClientPath is Empty*/
+       assert.NotNil(t, HTTPCli.Post("/folders", fPrj, &cfg))
+       Debugf(t, "error while creating folder with empty clientpath \n%v", fPrj)
+
+       fPrj.ClientPath = "logDir"
+       fPrj.Type = ""
+       /*Type is empty*/
+       assert.NotNil(t, HTTPCli.Post("/folders", fPrj, &cfg))
+       Debugf(t, "error while creating folder with empty type \n%v", fPrj)
+
+       var cfgArray []xsapiv1.FolderConfig
+       assert.Nil(t, HTTPCli.Get("/folders", &cfgArray))
+       assert.Equal(t, len(cfgArray), 0)
+}
+
+func TestFoldersPathMapConfig(t *testing.T) {
+       fPrj := xsapiv1.FolderConfig{
+               Label:      "testproject",
+               ClientPath: logDir + "clientpathtest",
+               Type:       xsapiv1.TypePathMap,
+               ClientData: "clientdatatest",
+               DataPathMap: xsapiv1.PathMapConfig{
+                       ServerPath: logDir + "serverpath",
+                       CheckFile:  "checkfile",
+               },
+       }
+       var cfg xsapiv1.FolderConfig
+       /*file not present*/
+       assert.NotNil(t, HTTPCli.Post("/folders", fPrj, &cfg))
+       Debugf(t, "error while creating folder with no checkfile \n%v", fPrj)
+
+       var checkFileClient = fPrj.ClientPath + "/checkfile"
+       var checkFileServer = fPrj.DataPathMap.ServerPath + "/checkfile"
+
+       /*create file*/
+       os.MkdirAll(fPrj.ClientPath, 0755)
+       fPrj.DataPathMap.CheckFile = checkFileClient
+       fPrj.DataPathMap.CheckContent = "CheckContent From Client\n"
+       file, err := os.OpenFile(checkFileClient, os.O_CREATE|os.O_RDWR, 0644)
+       if err != nil {
+               Debug(t, err)
+       }
+       if err := os.Symlink(checkFileClient, checkFileServer); err != nil {
+               Debug(t, err)
+       }
+       /*file content differ*/
+       assert.NotNil(t, HTTPCli.Post("/folders", fPrj, &cfg))
+       Debugf(t, "error while creating folder with different checkfiles \n%v", fPrj)
+
+       /*write same message*/
+       if _, err := file.WriteString(fPrj.DataPathMap.CheckContent); err != nil {
+               Debug(t, err)
+       }
+       assert.Nil(t, HTTPCli.Post("/folders", fPrj, &cfg))
+       Debugf(t, "create folder with same checkfiles \n%v", fPrj)
+
+       /*check server msg: ServerUID needed*/
+       Debugf(t, "check server msg")
+       var APIcfg xsapiv1.APIConfig
+       assert.Nil(t, HTTPCli.Get("/config", &APIcfg))
+       msg := "Pathmap checked message written by xds-server ID: " + APIcfg.ServerUID + "\n"
+       data, err := ioutil.ReadAll(file)
+       if err != nil {
+               Debug(t, err)
+       }
+       assert.Equal(t, msg, string(data))
+
+       assert.Nil(t, HTTPCli.Delete("/folders/"+cfg.ID, &cfg))
+       var cfgArray []xsapiv1.FolderConfig
+       assert.Nil(t, HTTPCli.Get("/folders", &cfgArray))
+       assert.Equal(t, len(cfgArray), 0)
+}
diff --git a/test/main_test.go b/test/main_test.go
new file mode 100644 (file)
index 0000000..68206a9
--- /dev/null
@@ -0,0 +1,227 @@
+/*
+ * 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
+
+func Debug(t *testing.T, args ...interface{}) {
+       if os.Getenv("VERBOSE") != "" {
+               t.Log(args)
+       }
+}
+
+func Debugf(t *testing.T, format string, args ...interface{}) {
+       if os.Getenv("VERBOSE") != "" {
+               t.Logf(format, args)
+       }
+}
+
+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,
+       }
+       cli, err := common.HTTPNewClient(prefixURL, conf)
+       if err != nil {
+               log.Fatal(err)
+       }
+       log.Printf("HTTP session ID : %v", cli.GetClientID())
+       var ver xsapiv1.Version
+       err = cli.Get("/version", &ver)
+       if err != nil {
+               log.Fatal(err)
+       }
+       return cli, 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) {
+               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 separetly */
+       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()
+}
diff --git a/test/sdks_test.go b/test/sdks_test.go
new file mode 100644 (file)
index 0000000..1395b16
--- /dev/null
@@ -0,0 +1,185 @@
+/*
+ * 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 (
+       "log"
+       "os"
+       "path"
+       "regexp"
+       "strings"
+       "testing"
+       "time"
+
+       "gerrit.automotivelinux.org/gerrit/src/xds/xds-server/lib/xsapiv1"
+       "github.com/stretchr/testify/assert"
+)
+
+var cpt int
+
+/*flush channel with timeout*/
+func flushChannelSdk(channel chan xsapiv1.SDK, ms time.Duration) {
+       timeoutB := false
+       for !timeoutB {
+               select {
+               case <-channel:
+               case <-time.After(ms * time.Millisecond):
+                       timeoutB = true
+               }
+       }
+}
+
+func ConnectSDKStateChange(t *testing.T, sCli *IOSockClient, channel chan xsapiv1.SDK) {
+
+       sCli.Conn.On(xsapiv1.EVTSDKStateChange, func(e xsapiv1.EventMsg) {
+               sdk, _ := e.DecodeSDKEvent()
+               channel <- sdk
+       })
+
+       args := xsapiv1.EventRegisterArgs{Name: xsapiv1.EVTSDKStateChange}
+       assert.Nil(t, HTTPCli.Post("/events/register", args, nil))
+}
+
+func DisconnectSDKStateChange(t *testing.T, sCli *IOSockClient) {
+       args := xsapiv1.EventRegisterArgs{Name: xsapiv1.EVTSDKStateChange}
+       assert.Nil(t, HTTPCli.Post("/events/unregister", args, nil))
+}
+
+func InitSdkDir() {
+       /*create sdk dir*/
+       sdkDir := os.Getenv(envXdtSdk)
+       os.MkdirAll(sdkDir, 0755)
+       currentDir, err := os.Getwd()
+       if err != nil {
+               log.Fatal(err)
+       }
+       if err := Copy(path.Join(currentDir, sdkFile), path.Join(sdkDir, sdkFileName)); err != nil {
+               log.Fatal(err)
+       }
+}
+
+func RemoveSdk(t *testing.T, sdk xsapiv1.SDK, chSdks chan xsapiv1.SDK) {
+       Debugf(t, "remove sdk %v", sdk.ID)
+       assert.Nil(t, HTTPCli.Delete("/sdks/"+sdk.ID, &sdk))
+       sdkFromEvt := <-chSdks //waiting for event Uninstalling
+       assert.Equal(t, sdk.ID, sdkFromEvt.ID)
+       assert.Equal(t, sdkFromEvt.Status, "Un-installing")
+       sdkFromEvt = <-chSdks //waiting for event not installed
+       assert.Equal(t, sdkFromEvt.Status, "Not Installed")
+       os.RemoveAll(path.Join(os.Getenv(envXdtSdk), sdk.Profile))
+       os.Remove(strings.Replace(sdk.URL, "file://", "", 1))
+}
+
+func TestSdks(t *testing.T) {
+       InitSdkDir()
+       /*get sdk list from sdk_latest.json*/
+       var sdkArray []xsapiv1.SDK
+       assert.Nil(t, HTTPCli.Get("/sdks", &sdkArray))
+       _, err := os.Stat(path.Join(os.Getenv(envXdtSdk), "sdks_latest.json"))
+       assert.Nil(t, err)
+
+       /*create channel fro SDK event*/
+       chSdks := make(chan xsapiv1.SDK)
+       defer close(chSdks)
+       ConnectSDKStateChange(t, sCli, chSdks)
+
+       /*checking startup installing of SDKs*/
+       for i := 0; i < len(sdkArray); i++ {
+               re := regexp.MustCompile("^[0-9a-z]+-[0-9a-z]+-[0-9a-z]+-[0-9a-z]+-[0-9a-z]+$")
+               assert.True(t, re.MatchString(sdkArray[i].ID))
+               assert.Equal(t, sdkArray[0].Status, "Not Installed")
+
+               var sdk xsapiv1.SDK
+               assert.Nil(t, HTTPCli.Get("/sdks/"+sdkArray[i].ID, &sdk))
+               assert.Equal(t, sdkArray[i], sdk)
+
+               var sdkRes xsapiv1.SDK
+               /*install sdk*/
+               Debugf(t, "install sdk %v", sdk.Name)
+               assert.Nil(t, HTTPCli.Post("/sdks", sdk, &sdkRes))
+               assert.Equal(t, sdkRes.Status, "Installing")
+               sdkFromEvent := <-chSdks //waiting for installing event
+               assert.Equal(t, sdkRes.ID, sdkFromEvent.ID)
+               assert.Equal(t, sdkFromEvent.Status, "Installing")
+
+               /*abort sdk install*/
+               Debugf(t, "abort install sdk %v", sdk.Name)
+               assert.Nil(t, HTTPCli.Post("/sdks/abortinstall", sdk, &sdkRes))
+               assert.Equal(t, sdkRes.Status, "Not Installed")
+               sdkFromEvent = <-chSdks //waiting for not installed status*/
+               assert.Equal(t, sdkRes.ID, sdkFromEvent.ID)
+               assert.Equal(t, sdkRes.Status, sdkFromEvent.Status)
+       }
+}
+
+func installFakeSdk(t *testing.T, sdkInstall xsapiv1.SDKInstallArgs, chSdks chan xsapiv1.SDK) xsapiv1.SDK {
+       InitSdkDir()
+       var sdkRes xsapiv1.SDK
+       assert.Nil(t, HTTPCli.Post("/sdks", sdkInstall, &sdkRes))
+       Debugf(t, "Install fake sdk %v (force=%v)", sdkRes.Name, sdkInstall.Force)
+       assert.Equal(t, sdkRes.Status, "Installing")
+       sdkFromEvent := <-chSdks
+       assert.Equal(t, sdkRes.ID, sdkFromEvent.ID)
+       assert.Equal(t, sdkFromEvent.Status, "Installing")
+       /*waiting for SDKStateChange event from channel*/
+       sdkFromEvent = <-chSdks
+       assert.Equal(t, sdkRes.ID, sdkFromEvent.ID)
+       assert.Equal(t, "Installed", sdkFromEvent.Status)
+       assert.Equal(t, sdkFromEvent.LastError, "")
+       Debugf(t, "Fake sdk %v installed", sdkFromEvent.Name)
+       return sdkFromEvent
+}
+
+func TestInstallFakeSdk(t *testing.T) {
+       sdk := xsapiv1.SDKInstallArgs{
+               ID:       "",
+               Filename: sdkFileName,
+               Force:    false,
+       }
+
+       chSdks := make(chan xsapiv1.SDK)
+       defer close(chSdks)
+       ConnectSDKStateChange(t, sCli, chSdks)
+       installFakeSdk(t, sdk, chSdks)
+
+       /*test force install*/
+       sdk.Force = true
+       sdkRes := installFakeSdk(t, sdk, chSdks)
+       RemoveSdk(t, sdkRes, chSdks)
+       DisconnectSDKStateChange(t, sCli)
+}
+
+func TestSdksError(t *testing.T) {
+       sdk := xsapiv1.SDKInstallArgs{
+               ID:       "",
+               Filename: "",
+               Force:    false,
+       }
+       Debugf(t, "error while installing sdk with no ID and no Filename")
+       var sdkRes xsapiv1.SDK
+       /*error with no ID no filename*/
+       assert.NotNil(t, HTTPCli.Post("/sdks", sdk, &sdkRes))
+       sdk.ID = "42885c24-374e-3ef0-9723-0c8a05191aa"
+       Debugf(t, "error while installing sdk with a fake id=%v", sdk.ID)
+       /*error with fake ID*/
+       assert.NotNil(t, HTTPCli.Post("/sdks", sdk, &sdkRes))
+       sdk.ID = ""
+       sdk.Filename = "fake"
+       Debugf(t, "error while installing sdk with a fake filename=%v", sdk.Filename)
+       /*error with fake filename*/
+       assert.NotNil(t, HTTPCli.Post("/sdks", sdk, &sdkRes))
+}
diff --git a/test/target_test.go b/test/target_test.go
new file mode 100644 (file)
index 0000000..e89011b
--- /dev/null
@@ -0,0 +1,350 @@
+/*
+ * 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 (
+       "strconv"
+       "strings"
+       "testing"
+       "time"
+
+       "gerrit.automotivelinux.org/gerrit/src/xds/xds-server/lib/xsapiv1"
+       "github.com/stretchr/testify/assert"
+)
+
+/*flush channel with timeout*/
+func flushChannelTerm(channel chan xsapiv1.TerminalOutMsg, ms time.Duration) {
+       timeoutB := false
+       for !timeoutB {
+               select {
+               case <-channel:
+               case <-time.After(ms * time.Millisecond):
+                       timeoutB = true
+               }
+       }
+}
+
+func ConnectTargetEvents(t *testing.T, channel chan xsapiv1.TargetConfig) {
+       sCli.Conn.On(xsapiv1.EVTTargetAdd, func(e xsapiv1.EventMsg) {
+               target, _ := e.DecodeTargetEvent()
+               channel <- target
+       })
+
+       args := xsapiv1.EventRegisterArgs{Name: xsapiv1.EVTTargetAdd}
+       assert.Nil(t, HTTPCli.Post("/events/register", args, nil))
+
+       sCli.Conn.On(xsapiv1.EVTTargetRemove, func(e xsapiv1.EventMsg) {
+               target, _ := e.DecodeTargetEvent()
+               channel <- target
+       })
+
+       args = xsapiv1.EventRegisterArgs{Name: xsapiv1.EVTTargetRemove}
+       assert.Nil(t, HTTPCli.Post("/events/register", args, nil))
+}
+
+func DisconnectTargetEvents(t *testing.T) {
+       args := xsapiv1.EventRegisterArgs{Name: xsapiv1.EVTTargetAdd}
+       assert.Nil(t, HTTPCli.Post("/events/unregister", args, nil))
+       args = xsapiv1.EventRegisterArgs{Name: xsapiv1.EVTTargetRemove}
+       assert.Nil(t, HTTPCli.Post("/events/unregister", args, nil))
+}
+
+func ConnectTermEvents(t *testing.T, channel chan xsapiv1.TerminalConfig) {
+       sCli.Conn.On(xsapiv1.EVTTargetTerminalAdd, func(e xsapiv1.EventMsg) {
+               termEvt, _ := e.DecodeTerminalEvent()
+               channel <- termEvt
+       })
+
+       args := xsapiv1.EventRegisterArgs{Name: xsapiv1.EVTTargetTerminalAdd}
+       assert.Nil(t, HTTPCli.Post("/events/register", args, nil))
+
+       sCli.Conn.On(xsapiv1.EVTTargetTerminalStateChange, func(e xsapiv1.EventMsg) {
+               termEvt, _ := e.DecodeTerminalEvent()
+               channel <- termEvt
+       })
+
+       args = xsapiv1.EventRegisterArgs{Name: xsapiv1.EVTTargetTerminalStateChange}
+       assert.Nil(t, HTTPCli.Post("/events/register", args, nil))
+
+       sCli.Conn.On(xsapiv1.EVTTargetTerminalRemove, func(e xsapiv1.EventMsg) {
+               termEvt, _ := e.DecodeTerminalEvent()
+               channel <- termEvt
+       })
+
+       args = xsapiv1.EventRegisterArgs{Name: xsapiv1.EVTTargetTerminalRemove}
+       assert.Nil(t, HTTPCli.Post("/events/register", args, nil))
+}
+
+func DisconnectTermEvents(t *testing.T) {
+       args := xsapiv1.EventRegisterArgs{Name: xsapiv1.EVTTargetTerminalAdd}
+       assert.Nil(t, HTTPCli.Post("/events/unregister", args, nil))
+       args = xsapiv1.EventRegisterArgs{Name: xsapiv1.EVTTargetTerminalStateChange}
+       assert.Nil(t, HTTPCli.Post("/events/unregister", args, nil))
+       args = xsapiv1.EventRegisterArgs{Name: xsapiv1.EVTTargetTerminalRemove}
+       assert.Nil(t, HTTPCli.Post("/events/unregister", args, nil))
+}
+
+func AddTargets(t *testing.T, nbTargets int, chTarget chan xsapiv1.TargetConfig) []string {
+       listID := make([]string, nbTargets)
+       for i := 0; i < nbTargets; i++ {
+               /*target is local*/
+               target := xsapiv1.TargetConfig{
+                       Name: "fakeTarget" + strconv.Itoa(i),
+                       Type: xsapiv1.TypeTgtStandard,
+                       IP:   "127.0.0.1",
+               }
+               /*add target*/
+               assert.Nil(t, HTTPCli.Post("/targets", target, &target))
+               Debugf(t, "add target %v", target.Name)
+               targetEvt := <-chTarget //waiting for event targetAdd
+               assert.Equal(t, target.ID, targetEvt.ID)
+               listID[i] = target.ID
+       }
+       for i := 0; i < nbTargets; i++ {
+               var target xsapiv1.TargetConfig
+               assert.Nil(t, HTTPCli.Get("/targets/"+listID[i], &target))
+               assert.Equal(t, target.Status, "Enable")
+       }
+       return listID
+}
+
+func AddTerms(t *testing.T, nbTerms int, listID []string, chTermEvt chan xsapiv1.TerminalConfig) {
+       for j := 0; j < len(listID); j++ {
+               listTermsID := make([]string, nbTerms)
+               for i := 0; i < nbTerms; i++ {
+                       term := xsapiv1.TerminalConfig{
+                               Name: "terminal" + strconv.Itoa(i),
+                               Type: xsapiv1.TypeTermSSH,
+                       }
+                       /*add terminal on target*/
+                       assert.Nil(t, HTTPCli.Post("/targets/"+listID[j]+"/terminals", term, &term))
+                       Debugf(t, "add terminal %v", term.Name)
+                       termEvt := <-chTermEvt //waiting for event terminalAdd*/
+                       assert.Equal(t, term.ID, termEvt.ID)
+                       listTermsID[i] = term.ID
+               }
+               assert.Equal(t, len(listTermsID), nbTerms)
+               for i := 0; i < nbTerms; i++ {
+                       var term xsapiv1.TerminalConfig
+                       assert.Nil(t, HTTPCli.Get("/targets/"+listID[j]+"/terminals/"+listTermsID[i], &term))
+                       assert.Equal(t, term.Status, "Close")
+               }
+       }
+}
+
+func PostTerms(t *testing.T, post string, chTermEvt chan xsapiv1.TerminalConfig) {
+       var status string
+       switch post {
+       case "open":
+               status = "Open"
+       case "close":
+               status = "Closing"
+       }
+       var targets []xsapiv1.TargetConfig
+       assert.Nil(t, HTTPCli.Get("/targets", &targets))
+       for i := 0; i < len(targets); i++ {
+               var terms []xsapiv1.TerminalConfig
+               assert.Nil(t, HTTPCli.Get("/targets/"+targets[i].ID+"/terminals", &terms))
+               listTermsID := make([]string, len(terms))
+               for j := 0; j < len(terms); j++ {
+                       var term xsapiv1.TerminalConfig
+                       /*post action on term*/
+                       assert.Nil(t, HTTPCli.Post("/targets/"+targets[i].ID+"/terminals/"+terms[j].ID+"/"+post, terms[j], &term))
+                       Debugf(t, "%v terminal %v", post, term.Name)
+                       termEvt := <-chTermEvt //waiting for event terminalStateChange
+                       assert.Equal(t, term.ID, termEvt.ID)
+                       assert.Equal(t, term.Status, status)
+                       assert.Equal(t, termEvt.Status, status)
+                       listTermsID[i] = term.ID
+               }
+               time.Sleep(10 * time.Millisecond)
+               for j := 0; j < len(listTermsID); j++ {
+                       var term xsapiv1.TerminalConfig
+                       assert.Nil(t, HTTPCli.Get("/targets/"+targets[i].ID+"/terminals/"+listTermsID[i], &term))
+                       assert.True(t, strings.EqualFold(term.Status, post))
+                       Debugf(t, "check that term status %v is %v", term.Name, post)
+               }
+       }
+}
+
+func RemoveTermsTargets(t *testing.T, chTarget chan xsapiv1.TargetConfig, chTermEvt chan xsapiv1.TerminalConfig) {
+       var targets []xsapiv1.TargetConfig
+       assert.Nil(t, HTTPCli.Get("/targets", &targets))
+       for i := 0; i < len(targets); i++ {
+               var terms []xsapiv1.TerminalConfig
+               assert.Nil(t, HTTPCli.Get("/targets/"+targets[i].ID+"/terminals", &terms))
+               for j := 0; j < len(terms); j++ {
+                       var term xsapiv1.TerminalConfig
+                       assert.Nil(t, HTTPCli.Delete("/targets/"+targets[i].ID+"/terminals/"+terms[j].ID, &term))
+                       termEvt := <-chTermEvt
+                       assert.Equal(t, term.ID, termEvt.ID)
+                       assert.NotNil(t, HTTPCli.Delete("/targets/"+targets[i].ID+"/terminals/"+terms[j].ID, &term))
+                       Debugf(t, "remove terminal %v", term.Name)
+               }
+               var tgtRes xsapiv1.TargetConfig
+               assert.Nil(t, HTTPCli.Delete("/targets/"+targets[i].ID, &tgtRes))
+               targetEvt := <-chTarget //waiting for remove terminal event
+               assert.Equal(t, tgtRes.ID, targetEvt.ID)
+               assert.Equal(t, targets[i].ID, tgtRes.ID)
+       }
+}
+func TestTarget(t *testing.T) {
+       nbTargets := 3
+       nbTermsByTarget := 3
+       /*channel for target events*/
+       chTarget := make(chan xsapiv1.TargetConfig)
+       defer close(chTarget)
+       ConnectTargetEvents(t, chTarget)
+
+       /*channel for terminal events*/
+       chTermEvt := make(chan xsapiv1.TerminalConfig)
+       defer close(chTermEvt)
+       ConnectTermEvents(t, chTermEvt)
+
+       /*check that targetArray is empty at startup*/
+       var targetArray []xsapiv1.TargetConfig
+       assert.Nil(t, HTTPCli.Get("/targets", &targetArray))
+       assert.Equal(t, len(targetArray), 0)
+
+       listID := AddTargets(t, nbTargets, chTarget)
+       AddTerms(t, nbTermsByTarget, listID, chTermEvt)
+
+       ///*channel for TerminalOutMsg*/
+       //chTerm := make(chan xsapiv1.TerminalOutMsg)
+       //defer close(chTerm)
+
+       ///*connect on terminalOutMsg event*/
+       //sCli.Conn.On(xsapiv1.TerminalOutEvent, func(ev xsapiv1.TerminalOutMsg) {
+       //      chTerm <- ev
+       //})
+
+       ///*just for the first term*/
+       //var terms []xsapiv1.TerminalConfig
+       //var term xsapiv1.TerminalConfig
+       //assert.Nil(t, HTTPCli.Get("/targets/"+listID[0]+"/terminals", &terms))
+       //assert.Nil(t, HTTPCli.Post("/targets/"+listID[0]+"/terminals/"+terms[0].ID+"/open", terms[0], &term))
+       //<-chTermEvt                  //waiting for event terminalStateChange
+       //termOut := <-chTerm          //waiting for terminalOutMsg
+       //flushChannelTerm(chTerm, 50) //flushing all terminalOutMsg
+       //stdoutMsg := string(termOut.Stdout)
+       //if strings.Contains(stdoutMsg, "Connection refused") {
+       //      t.Fatalf("%vYou may have to launch ssh server", stdoutMsg)
+       //} else if strings.Contains(stdoutMsg, "password") {
+       //      t.Fatalf("%vcopy your pub key in authorized_keys\ncat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys", stdoutMsg)
+       //}
+       //assert.True(t, strings.Contains(stdoutMsg, "Last login")) //first terminal msg should be Last Login
+       //assert.Nil(t, HTTPCli.Post("/targets/"+listID[0]+"/terminals/"+terms[0].ID+"/close", terms[0], &term))
+       //<-chTermEvt //waiting for event terminalStateChange
+
+       ///*open terminals*/
+       //PostTerms(t, "open", chTermEvt)
+       //termOut = <-chTerm           //waiting for terminalOutMsg
+       //flushChannelTerm(chTerm, 50) //flushing all terminalOutMsg
+       //stdoutMsg = string(termOut.Stdout)
+       //if strings.Contains(stdoutMsg, "Connection refused") {
+       //      t.Fatalf("%vYou may have to launch ssh server", stdoutMsg)
+       //} else if strings.Contains(stdoutMsg, "password") {
+       //      t.Fatalf("%vcopy your pub key in authorized_keys\ncat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys", stdoutMsg)
+       //}
+       //assert.True(t, strings.Contains(stdoutMsg, "Last login")) //first terminal msg should be Last Login
+
+       ///*create toto file through terminals*/
+       //rootCfgDir := os.Getenv(envRootCfgDir)
+       //totoFile := path.Join(rootCfgDir, "toto")
+
+       ///*test with 2 terminals*/
+       //for i := 0; i < 2; i++ {
+       //      totoFileCurrent := totoFile + strconv.Itoa(i)
+       //      /*send cmd though term*/
+       //      data := []byte("echo helloWorld" + strconv.Itoa(i) + " >> " + totoFileCurrent + "\n")
+       //      Debugf(t, "send following command through terminal: %v", string(data))
+       //      assert.Nil(t, sCli.Conn.Emit(xsapiv1.TerminalInEvent, data))
+       //      flushChannelTerm(chTerm, 50) //waiting for terminal msg
+
+       //      /*check that toto file is created*/
+       //      _, err := os.Stat(totoFileCurrent)
+       //      assert.Nil(t, err)
+
+       //      /*send cmd though term*/
+       //      data = []byte("cat " + totoFileCurrent + "\n")
+       //      Debugf(t, "send following command through terminal: %v", string(data))
+       //      assert.Nil(t, sCli.Conn.Emit(xsapiv1.TerminalInEvent, data))
+
+       //      <-chTerm                     //cmd sent
+       //      termOut = <-chTerm           //result of cat cmd
+       //      flushChannelTerm(chTerm, 50) //flushing what remains
+       //      /*check that terminal msg is what was written before*/
+       //      assert.Equal(t, string(termOut.Stdout), "helloWorld"+strconv.Itoa(i)+"\r\n")
+       //      Debugf(t, "check terminal output msg: %v", string(termOut.Stdout))
+       //}
+
+       //PostTerms(t, "close", chTermEvt)
+
+       /*remove targets and terms*/
+       RemoveTermsTargets(t, chTarget, chTermEvt)
+       DisconnectTargetEvents(t)
+       DisconnectTermEvents(t)
+}
+
+func TestTargetErrors(t *testing.T) {
+       /*cannot create empty target*/
+       target := xsapiv1.TargetConfig{}
+       var targetRes xsapiv1.TargetConfig
+       assert.NotNil(t, HTTPCli.Post("/targets", target, &targetRes))
+       Debugf(t, "error while creating empty target")
+       /*check cannot create target with no IP*/
+       target.Type = xsapiv1.TypeTgtStandard
+       assert.NotNil(t, HTTPCli.Post("/targets", target, &targetRes))
+       Debugf(t, "error while creating target without IP")
+       target.IP = "127.0.0.1"
+       assert.Nil(t, HTTPCli.Post("/targets", target, &targetRes))
+       Debugf(t, "create target %v", targetRes.Name)
+
+       /*cannot create empty terminal*/
+       term := xsapiv1.TerminalConfig{}
+       var termRes xsapiv1.TerminalConfig
+       assert.NotNil(t, HTTPCli.Post("/targets/"+targetRes.ID+"/terminals", term, &termRes))
+       Debugf(t, "error while creating empty terminal")
+       term.Type = xsapiv1.TypeTermSSH
+       assert.NotNil(t, HTTPCli.Post("/targets/"+"1010"+"/terminals", term, &termRes))
+       Debugf(t, "error while creating terminal on an non existing target")
+       assert.Nil(t, HTTPCli.Post("/targets/"+targetRes.ID+"/terminals", term, &termRes))
+       assert.Nil(t, HTTPCli.Post("/targets/"+targetRes.ID+"/terminals", term, &termRes))
+       assert.Nil(t, HTTPCli.Post("/targets/"+targetRes.ID+"/terminals", term, &termRes))
+       assert.Nil(t, HTTPCli.Post("/targets/"+targetRes.ID+"/terminals", term, &termRes))
+       Debugf(t, "create several terminals")
+
+       /*remove targets and terms*/
+       var targetArray []xsapiv1.TargetConfig
+       assert.Nil(t, HTTPCli.Get("/targets", &targetArray))
+       for i := 0; i < len(targetArray); i++ {
+               var termArray []xsapiv1.TerminalConfig
+               assert.Nil(t, HTTPCli.Get("/targets/"+targetArray[i].ID+"/terminals", &termArray))
+               for j := 0; j < len(termArray); j++ {
+                       assert.Nil(t, HTTPCli.Delete("/targets/"+targetArray[i].ID+"/terminals/"+termArray[j].ID, &termRes))
+                       Debugf(t, "delete terminal %v", termRes.Name)
+                       assert.NotNil(t, HTTPCli.Delete("/targets/"+targetArray[i].ID+"/terminals/"+termArray[j].ID, &termRes))
+                       Debugf(t, "error while deleting an already deleted terminal %v", termRes.Name)
+               }
+               var tgtRes xsapiv1.TargetConfig
+               assert.Nil(t, HTTPCli.Delete("/targets/"+targetArray[i].ID, &tgtRes))
+               Debugf(t, "delete target %v", tgtRes.Name)
+               assert.Equal(t, targetArray[i].ID, tgtRes.ID)
+               assert.NotNil(t, HTTPCli.Delete("/targets/"+targetArray[i].ID, &tgtRes))
+               Debugf(t, "error while deleting an already deleted target %v", tgtRes.Name)
+       }
+}
diff --git a/test/version_test.go b/test/version_test.go
new file mode 100644 (file)
index 0000000..5373a15
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * 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 (
+       "regexp"
+       "testing"
+
+       "github.com/stretchr/testify/assert"
+)
+
+func TestVersion(t *testing.T) {
+       var datVersion map[string]interface{}
+       assert.Nil(t, HTTPCli.Get("/version", &datVersion))
+       Debug(t, datVersion)
+
+       ver, present := datVersion["version"]
+       assert.True(t, present)
+       Debugf(t, "version is %s", ver.(string))
+       re := regexp.MustCompile("^v*[0-9]+.[0-9]+.[0-9]+$")
+       assert.True(t, re.MatchString(ver.(string)))
+}