summaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
authorClément Bénier <clement.benier@iot.bzh>2018-08-21 18:58:26 +0200
committerClément Bénier <clement.benier@iot.bzh>2018-08-21 18:58:32 +0200
commitc095e1ea9a9e38f020ce4ae852d97c712be910b6 (patch)
treece085c43116ceb9eda10fd79cfc3d18ecfe6387a /test
parent3c40079d8360c15f0ce52a6c11a2bc2555177463 (diff)
parent2fb2226b666e7a8a21dc8b852188b75c06e2cfc8 (diff)
Merge remote-tracking branch 'origin/sandbox/benierc/test'
Change-Id: Idc200f10e217119df9edfebbaf839c5fd45b19a4 Signed-off-by: Clément Bénier <clement.benier@iot.bzh>
Diffstat (limited to 'test')
-rw-r--r--test/_test-config.json8
-rw-r--r--test/config.go33
-rw-r--r--test/config_test.go53
-rw-r--r--test/exec_test.go137
-rw-r--r--test/fixtures/helloworld/CMakeLists.txt3
-rw-r--r--test/fixtures/helloworld/conf.d/cmake/config.cmake167
-rw-r--r--test/fixtures/helloworld/helloworld/CMakeLists.txt36
-rw-r--r--test/fixtures/helloworld/helloworld/helloworld.c6
-rwxr-xr-xtest/fixtures/poky-agl-glibc-x86_64-gcc_crosssdk-native_x86_64-toolchain-1.0.2.shbin0 -> 2002 bytes
-rw-r--r--test/folders_test.go187
-rw-r--r--test/main_test.go227
-rw-r--r--test/sdks_test.go185
-rw-r--r--test/target_test.go350
-rw-r--r--test/version_test.go36
14 files changed, 1428 insertions, 0 deletions
diff --git a/test/_test-config.json b/test/_test-config.json
new file mode 100644
index 0000000..223b3eb
--- /dev/null
+++ b/test/_test-config.json
@@ -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
index 0000000..4850919
--- /dev/null
+++ b/test/config.go
@@ -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
index 0000000..2b95e85
--- /dev/null
+++ b/test/config_test.go
@@ -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
index 0000000..884ba87
--- /dev/null
+++ b/test/exec_test.go
@@ -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
index 0000000..f757721
--- /dev/null
+++ b/test/fixtures/helloworld/CMakeLists.txt
@@ -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
index 0000000..00b4de1
--- /dev/null
+++ b/test/fixtures/helloworld/conf.d/cmake/config.cmake
@@ -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
index 0000000..373a6f5
--- /dev/null
+++ b/test/fixtures/helloworld/helloworld/CMakeLists.txt
@@ -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
index 0000000..94ebcdc
--- /dev/null
+++ b/test/fixtures/helloworld/helloworld/helloworld.c
@@ -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
index 0000000..7781335
--- /dev/null
+++ b/test/fixtures/poky-agl-glibc-x86_64-gcc_crosssdk-native_x86_64-toolchain-1.0.2.sh
Binary files differ
diff --git a/test/folders_test.go b/test/folders_test.go
new file mode 100644
index 0000000..10f1dc6
--- /dev/null
+++ b/test/folders_test.go
@@ -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
index 0000000..68206a9
--- /dev/null
+++ b/test/main_test.go
@@ -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
index 0000000..1395b16
--- /dev/null
+++ b/test/sdks_test.go
@@ -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
index 0000000..e89011b
--- /dev/null
+++ b/test/target_test.go
@@ -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
index 0000000..5373a15
--- /dev/null
+++ b/test/version_test.go
@@ -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)))
+}