diff --git a/delphyne-gui/cmake/TestUtils.cmake b/delphyne-gui/cmake/TestUtils.cmake index aeb485ff..bf043070 100644 --- a/delphyne-gui/cmake/TestUtils.cmake +++ b/delphyne-gui/cmake/TestUtils.cmake @@ -1,10 +1,7 @@ ################################################## -# Hack: to just build the files but not add them into the testsuite -# (like auxiliary apps using gtest files called from other tests) -# set the delphyne_SKIP_IN_TESTSUITE variable to true. The variable will -# be set to false at the end of the function. -macro (delphyne_build_tests) +find_package(ament_cmake_gtest REQUIRED) +macro (delphyne_build_tests) # Find the Python interpreter for running the # check_test_ran.py script find_package(PythonInterp QUIET) @@ -13,141 +10,26 @@ macro (delphyne_build_tests) foreach(GTEST_SOURCE_file ${ARGN}) string(REGEX REPLACE ".cc" "" BINARY_NAME ${GTEST_SOURCE_file}) set(BINARY_NAME ${TEST_TYPE}_${BINARY_NAME}) - if(USE_LOW_MEMORY_TESTS) - add_definitions(-DUSE_LOW_MEMORY_TESTS=1) - endif(USE_LOW_MEMORY_TESTS) - add_executable(${BINARY_NAME} - ${GTEST_SOURCE_file} - ) - - add_dependencies(${BINARY_NAME} - gtest gtest_main - ) + ament_add_gtest(${BINARY_NAME} ${GTEST_SOURCE_file} TIMEOUT 240) - target_link_libraries(${BINARY_NAME} - ${IGNITION-COMMON_LIBRARIES} - ${global_attributes} - libgtest.a - pthread - ) - - if (UNIX) - target_link_libraries(${BINARY_NAME} - libgtest.a - libgtest_main.a + # Kind of an ugly catch-all bucket + target_link_libraries( + ${BINARY_NAME} + ${IGNITION-COMMON_LIBRARIES} + ${global_attributes} pthread - ) - elseif(WIN32) - target_link_libraries(${BINARY_NAME} - gtest - gtest_main - ) - endif() - - if (NOT DEFINED delphyne_SKIP_IN_TESTSUITE) - set(delphyne_SKIP_IN_TESTSUITE False) - endif() - - if (NOT delphyne_SKIP_IN_TESTSUITE) - add_test(${BINARY_NAME} ${CMAKE_CURRENT_BINARY_DIR}/${BINARY_NAME} - --gtest_output=xml:${CMAKE_BINARY_DIR}/test_results/${BINARY_NAME}.xml) - - set_tests_properties(${BINARY_NAME} PROPERTIES TIMEOUT 240) - - if (PYTHONINTERP_FOUND) - # Check that the test produced a result and create a failure if - # it didn't. Guards against crashed and timed out tests. - add_test(check_${BINARY_NAME} python - ${PROJECT_SOURCE_DIR}/test/utils/check_test_ran.py - ${CMAKE_BINARY_DIR}/test_results/${BINARY_NAME}.xml) - endif() - endif() - endforeach() - - # If delphyne_SKIP_IN_TESTSUITE was set to True, back to default. This way - # we request for explicit definition before calling the macro - if (delphyne_SKIP_IN_TESTSUITE) - set(delphyne_SKIP_IN_TESTSUITE False) - endif() -endmacro() - -################################################## -# Hack: to just build the files but not add them into the testsuite -# (like auxiliary apps using gtest files called from other tests) -# set the delphyne_SKIP_IN_TESTSUITE variable to true. The variable will -# be set to false at the end of the function. -macro (delphyne_build_test) - - # Find the Python interpreter for running the - # check_test_ran.py script - find_package(PythonInterp QUIET) - - # Build the test - set(GTEST_SOURCE_file ${ARGV0}) - string(REGEX REPLACE ".cc" "" BINARY_NAME ${GTEST_SOURCE_file}) - set(BINARY_NAME ${TEST_TYPE}_${BINARY_NAME}) - if(USE_LOW_MEMORY_TESTS) - add_definitions(-DUSE_LOW_MEMORY_TESTS=1) - endif(USE_LOW_MEMORY_TESTS) - - add_executable(${BINARY_NAME} - ${GTEST_SOURCE_file} - ${ARGN} - ) - - add_dependencies(${BINARY_NAME} - gtest gtest_main - ) - - target_link_libraries(${BINARY_NAME} - ${IGNITION-COMMON_LIBRARIES} - ${IGNITION-GUI_LIBRARIES} - ${IGNITION-MATH_LIBRARIES} - ${IGNITION-MSGS_LIBRARIES} - ${IGNITION-RENDERING_LIBRARIES} - ${IGNITION-TRANSPORT_LIBRARIES} - ${Qt5Core_LIBRARIES} - ${Qt5Widgets_LIBRARIES} - ${lcm_LIBRARIES} - ${global_attributes} - ) - - if (UNIX) - target_link_libraries(${BINARY_NAME} - libgtest.a - libgtest_main.a - pthread - ) - elseif(WIN32) - target_link_libraries(${BINARY_NAME} - gtest - gtest_main ) - endif() - if (NOT DEFINED delphyne_SKIP_IN_TESTSUITE) - set(delphyne_SKIP_IN_TESTSUITE False) - endif() - - if (NOT delphyne_SKIP_IN_TESTSUITE) - add_test(${BINARY_NAME} ${CMAKE_CURRENT_BINARY_DIR}/${BINARY_NAME} - --gtest_output=xml:${CMAKE_BINARY_DIR}/test_results/${BINARY_NAME}.xml) - - set_tests_properties(${BINARY_NAME} PROPERTIES TIMEOUT 240) + # Remove a warning in GTest. + target_compile_options(${BINARY_NAME} PRIVATE "-Wno-sign-compare") if (PYTHONINTERP_FOUND) # Check that the test produced a result and create a failure if # it didn't. Guards against crashed and timed out tests. add_test(check_${BINARY_NAME} python - ${PROJECT_SOURCE_DIR}/tools/check_test_ran.py + ${PROJECT_SOURCE_DIR}/test/utils/check_test_ran.py ${CMAKE_BINARY_DIR}/test_results/${BINARY_NAME}.xml) endif() - endif() - - # If delphyne_SKIP_IN_TESTSUITE was set to True, back to default. This way - # we request for explicit definition before calling the macro - if (delphyne_SKIP_IN_TESTSUITE) - set(delphyne_SKIP_IN_TESTSUITE False) - endif() + endforeach() endmacro() diff --git a/delphyne-gui/cmake/Utils.cmake b/delphyne-gui/cmake/Utils.cmake index d430799d..6b071874 100644 --- a/delphyne-gui/cmake/Utils.cmake +++ b/delphyne-gui/cmake/Utils.cmake @@ -108,7 +108,6 @@ endmacro() # This should be migrated to more fine control solution based on set_property APPEND # directories. It's present on cmake 2.8.8 while precise version is 2.8.7 link_directories(${PROJECT_BINARY_DIR}/test) -include_directories("${PROJECT_SOURCE_DIR}/test/gtest/include") ################################################# # Enable tests compilation by default diff --git a/delphyne-gui/package.xml b/delphyne-gui/package.xml index 69d9d3e4..85d6264e 100644 --- a/delphyne-gui/package.xml +++ b/delphyne-gui/package.xml @@ -34,6 +34,7 @@ ament_cmake ament_cmake_clang_format + ament_cmake_gtest ament_cmake diff --git a/delphyne-gui/test/CMakeLists.txt b/delphyne-gui/test/CMakeLists.txt index bd7d3a72..e69de29b 100644 --- a/delphyne-gui/test/CMakeLists.txt +++ b/delphyne-gui/test/CMakeLists.txt @@ -1,23 +0,0 @@ -include_directories ( - ${PROJECT_SOURCE_DIR}/test/gtest/include - ${PROJECT_SOURCE_DIR}/test/gtest - ${PROJECT_SOURCE_DIR}/test - ${PROJECT_BINARY_DIR} -) - -configure_file (test_config.h.in ${PROJECT_BINARY_DIR}/include/delphyne/test_config.h) - -# Build gtest -add_library(gtest STATIC gtest/src/gtest-all.cc) -add_library(gtest_main STATIC gtest/src/gtest_main.cc) -target_link_libraries(gtest_main gtest) -set(GTEST_LIBRARY "${PROJECT_BINARY_DIR}/test/libgtest.a") -set(GTEST_MAIN_LIBRARY "${PROJECT_BINARY_DIR}/test/libgtest_main.a") - -execute_process(COMMAND cmake -E remove_directory ${CMAKE_BINARY_DIR}/test_results) -execute_process(COMMAND cmake -E make_directory ${CMAKE_BINARY_DIR}/test_results) -include_directories(${GTEST_INCLUDE_DIRS}) - -add_subdirectory(integration) -add_subdirectory(performance) -add_subdirectory(regression) diff --git a/delphyne-gui/test/integration/CMakeLists.txt b/delphyne-gui/test/integration/CMakeLists.txt deleted file mode 100644 index a43c9f1f..00000000 --- a/delphyne-gui/test/integration/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -set(TEST_TYPE "INTEGRATION") - -set(tests - -) - -include_directories(SYSTEM ${CMAKE_BINARY_DIR}/test/) -link_directories(${PROJECT_BINARY_DIR}/test) - -delphyne_build_tests(${tests}) diff --git a/delphyne-gui/test/performance/CMakeLists.txt b/delphyne-gui/test/performance/CMakeLists.txt deleted file mode 100644 index 690ada28..00000000 --- a/delphyne-gui/test/performance/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -set(TEST_TYPE "PERFORMANCE") - -set(tests -) - -link_directories(${PROJECT_BINARY_DIR}/test) - -delphyne_build_tests(${tests}) diff --git a/delphyne-gui/test/regression/CMakeLists.txt b/delphyne-gui/test/regression/CMakeLists.txt deleted file mode 100644 index 30ae9867..00000000 --- a/delphyne-gui/test/regression/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -set(TEST_TYPE "REGRESSION") - -set(tests -) - -link_directories(${PROJECT_BINARY_DIR}/test) - -delphyne_build_tests(${tests}) diff --git a/delphyne-gui/test/test_config.h.in b/delphyne-gui/test/test_config.h.in deleted file mode 100644 index 9f67a877..00000000 --- a/delphyne-gui/test/test_config.h.in +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Copyright (C) 2017 Open Source Robotics Foundation - * - * 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. - * -*/ - -#ifndef DELPHYNE_TEST_CONFIG_HH_ -#define DELPHYNE_TEST_CONFIG_HH_ - -#define PROJECT_SOURCE_PATH "${PROJECT_SOURCE_DIR}" -#define PROJECT_BINARY_PATH "${PROJECT_BINARY_DIR}" -#define DELPHYNE_LIBRARY_PATH "${PROJECT_BINARY_DIR}/src" -#define DELPHYNE_VERSION_FULL "@PROJECT_VERSION_FULL@" - -#include -#include -#include -#include -#include -#include - -#ifdef _WIN32 - #include - #include -#else - #include - #include - #include - #include -#endif - -#include "gtest/gtest.h" -#include "delphyne/Helpers.hh" - -#if (_MSC_VER >= 1400) // Visual Studio 2005 - #include - - /// \brief setenv/unstenv are not present in Windows. Define them to make - /// the code portable. - /// \param[in] _name Variable name. - /// \param[in] _value Value. - /// \param[in] _rewrite If 'name' does exist in the environment, then its - /// value is changed to 'value' if 'rewrite' is nonzero. If overwrite is - /// zero, then the value of 'name' is not changed. - /// /return 0 on success or -1 on error. - int setenv(const char *_name, const char *_value, int /*_rewrite*/) - { - std::stringstream sstr; - std::string name = _name; - std::string value = _value; - sstr << name << '=' << value; - return _putenv(sstr.str().c_str()); - } - - /// \brief Deletes an environment variable. - /// \param[in] _name Variable name. - void unsetenv(const char *_name) - { - std::stringstream sstr; - std::string name = _name; - sstr << name << '='; - _putenv(sstr.str().c_str()); - } -#endif - -namespace testing -{ - /// \brief Join str1 and str2 considering both as storing system paths. - /// \param[in] str1 string containing a path. - /// \param[in] str2 string containing a path. - /// \return The string representation of the union of two paths. - std::string portablePathUnion(const std::string str1, const std::string str2) - { -#ifdef _WIN32 - std::tr2::sys::path base_path(str1); - return base_path /= str2; -#else - // Ugly as hell but trying to avoid boost::filesystem - return str1 + "/" + str2; -#endif - } - -#ifdef _WIN32 - using forkHandlerType = PROCESS_INFORMATION; -#else - using forkHandlerType = pid_t; -#endif - - /// \brief create a new process and run command on it. This function is - /// implementing the creation of a new process on both Linux (fork) and - /// Windows (CreateProcess) and the execution of the command provided. - /// \param[in] command The full system path to the binary to run into the - /// new process. - /// \return On success, the PID of the child process is returned in the - /// parent, an 0 is returned in the child. On failure, -1 is returned in the - /// parent and no child process is created. - forkHandlerType forkAndRun(const char *_command, const char *_partition) - { -#ifdef _WIN32 - STARTUPINFO info= {sizeof(info)}; - PROCESS_INFORMATION processInfo; - - char cmd[500]; - delphyne_strcpy(cmd, _command); - delphyne_strcat(cmd, " "); - delphyne_strcat(cmd, _partition); - - if (!CreateProcess(NULL, const_cast(cmd), NULL, NULL, - TRUE, 0, NULL, NULL, &info, &processInfo)) - { - std::cerr << "CreateProcess call failed" << std::endl; - } - - return processInfo; -#else - pid_t pid = fork(); - - if (pid == 0) - { - if (execl(_command, _command, _partition, - reinterpret_cast(0)) == -1) - { - std::cerr << "Error running execl call: " << _command << std::endl; - } - } - - return pid; -#endif - } - - /// \brief Wait for the end of a process and handle the termination - /// \param[in] pi Process handler of the process to wait for - /// (PROCESS_INFORMATION in windows or forkHandlerType in UNIX). - void waitAndCleanupFork(const forkHandlerType pi) - { -#ifdef _WIN32 - // Wait until child process exits. - WaitForSingleObject(pi.hProcess, INFINITE); - - // Close process and thread handler. - CloseHandle(pi.hProcess); - CloseHandle(pi.hThread); -#else - // Wait for the child process to return. - int status; - waitpid(pi, &status, 0); - if (status == -1) - std::cerr << "Error while running waitpid" << std::endl; -#endif - } - - /// \brief Send a termination signal to the process handled by pi. - /// \param[in] pi Process handler of the process to stop - /// (PROCESS_INFORMATION in windows or forkHandlerType in UNIX). - void killFork(const forkHandlerType pi) - { -#ifdef _WIN32 - // TerminateProcess return 0 on error - if (TerminateProcess(pi.hProcess, 0) == 0) - std::cerr << "Error running TerminateProcess: " << GetLastError(); -#else - kill(pi, SIGTERM); -#endif - } - - /// \brief Get a random number based on an integer converted to string. - /// \return A random integer converted to string. - std::string getRandomNumber() - { - // Initialize random number generator. - uint32_t seed = std::random_device {}(); - std::mt19937 randGenerator(seed); - - // Create a random number based on an integer converted to string. - std::uniform_int_distribution d(0, INT_MAX); - - return std::to_string(d(randGenerator)); - } - - // The fixture for testing classes. - class FileParserUtils : public ::testing::Test - { - /// \brief Code here will be called immediately after the constructor - /// (right before each test). - virtual void SetUp() - { - this->fileName = getRandomNumber() + ".txt"; - } - - /// \brief Code here will be called immediately after each test - /// (right before the destructor). - virtual void TearDown() - { - if (this->testFile.is_open()) - this->testFile.close(); - std::remove(this->fileName.c_str()); - } - - /// \brief Populate the temporary file. - /// \param[in] _content File content. - protected: void PopulateFile(const std::string &_content) - { - if (this->testFile.is_open()) - this->testFile.close(); - - this->testFile.open(this->fileName); - this->testFile << _content << std::endl; - } - - /// \brief The name of the test file created. - protected: std::string fileName; - - /// \brief If file content is not empty, its value will be used to populate - /// a text file and check some parser functions. - protected: std::string fileContent = ""; - - /// \brief A test file. - protected: std::ofstream testFile; - }; -} - -#endif // header guard