Calling Unittest++ from cmake created makefile - cmake

I recently started learning cmake, and have run into a small issue. I got both my executable and the unit tests to compile from the generated makefile without issue. If I run ./test in the build directory, the tests created in UnitTest++ run and complete as expected, printing the results. Is there any way to get make test to simply run the test executable rather than running it inside ctest framework or should I go about this a different way?
Here is a minimal working example of my code:
src/main/main.c is a simple empty main function
src/test/testMain.cpp:
#include <UnitTest++/UnitTest++.h>
TEST(FailSpect)
{
CHECK(false);
}
int main()
{
UnitTest::RunAllTests();
}
CMakeLists.txt:
cmake_minimum_required( VERSION 2.6 )
project( myProject)
enable_testing()
set( myProjectMain
src/main/main.c
)
set( myProjectSrc
)
set( myProjectTestSrc
src/test/testMain.cpp
)
add_executable( myExecutable ${myProjectMain} ${myProjectSrc} )
add_executable( testSuite ${myProjectTestSrc} ${myProjectSrc} )
target_link_libraries( testSuite UnitTest++ )
add_test( testExe testSuite )
make test output:
Running tests...
Start processing tests
Test project /myProjectDir/build
1/ 1 Testing testExe Passed
100% tests passed, 0 tests failed out of 1
./testSuite output:
/myProjectDir/src/test/testMain.cpp:5: error: Failure in FailSpect: false
FAILURE: 1 out of 1 tests failed (1 failures).
Test time: 0.00 seconds.

I have sorted out how to do this. First remove the lines:
enable_testing()
and
add_test(testExe testSuite)
and replace them by the line:
add_custom_target(test ./testExe
DEPENDS ./testExe)
at the end of the CMakeLists.txt file. Now make (all) builds both the tests and the main program. If everything is built already, then make test will just check that the tests are built and run them, producing:
[100%] Built target testExe
/myProjectDir/src/test/testMain.cpp:5: error: Failure in FailSpect: false
FAILURE: 1 out of 1 tests failed (1 failures).
Test time: 0.00 seconds.
[100%] Built target test
If the tests are out of date (after a make clean for instance), then make test will produce:
[100%] Building CXX object CMakeFiles/testExe.dir/src/test/testMain.cpp.o
Linking CXX executable testExe
[100%] Built target testExe
/myProjectDir/src/test/testMain.cpp:5: error: Failure in FailSpect: false
FAILURE: 1 out of 1 tests failed (1 failures).
Test time: 0.00 seconds.
[100%] Built target test

Related

libssl.so needed by target, missing and no known rule to make it

I am trying to make a Yocto recipe for an application (application_1.0.0.bb). Here is a (simplified) CMake for that application:
cmake_minimum_required(VERSION 3.14)
project(
server
VERSION 0.1.0
DESCRIPTION "Main application"
HOMEPAGE_URL "https://gitlab.123.com/software/projects/server"
LANGUAGES CXX
)
message(STATUS "CMAKE_CURRENT_BINARY_DIR: ${CMAKE_CURRENT_BINARY_DIR}")
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
# ---- Poco::Util ----
find_package(Poco REQUIRED COMPONENTS Util)
find_package(unofficial-libmariadb CONFIG REQUIRED)
find_package(Poco REQUIRED COMPONENTS Data DataMySQL)
# ---- Declare executable ----
add_executable(server_exe
src/main.cpp
)
add_executable(server::exe ALIAS server_exe)
set_property(TARGET server_exe PROPERTY OUTPUT_NAME server)
target_compile_features(server_exe PRIVATE cxx_std_17)
target_link_libraries(server_exe
PRIVATE
Poco::Util
Poco::DataMySQL
)
Both poco and mariadb are in the DEPENDS of application.bb recipe. The important parts of their CMake process (a bit patched from the original projects) are:
Poco::DataMySQL has target_link_libraries(DataMySQL PUBLIC Poco::Data ${MYSQL_LIBRARIES}) with set(MYSQL_LIBRARIES unofficial::libmariadb) and a find_package(unofficial-libmariadb CONFIG REQUIRED) called right before. Oh, and the Poco library is built the -DBUILD_SHARED_LIBS=OFF (so it builds static libraries)
libmariadb has a TARGET_LINK_LIBRARIES(libmariadb LINK_PRIVATE ${SYSTEM_LIBS}) with SYSTEM_LIBS withSET(SSL_LIBRARIES ${OPENSSL_SSL_LIBRARY} ${OPENSSL_CRYPTO_LIBRARY}) (Both OPENSSL_SSL_LIBRARY and OPENSSL_CRYPTO_LIBRARY being variables coming out FIND_PACKAGE(OPENSSL)). It is exported as unofficial::libmariadb.
Configuration step is successful but at the start of the compile step, bitbake gives me this error:
ERROR: application-1.0+gitAUTOINC+ebcaa0785-r0 do_compile: ExecutionError('/home/buildbot/oe-core/build/cortexa53-tdx-linux/application/1.0+gitAUTOINC+ebcaa0785-r0/temp/run.do_compile.368082', 1, None, None)
ERROR: Logfile of failure stored in: ...
Log data follows:
| DEBUG: Executing shell function do_compile
| NOTE: VERBOSE=1 cmake --build /home/buildbot/oe-core/build/tmp/work/cortexa53-tdx-linux/application/1.0+gitAUTOINC+ebcaa0785-r0/build --target all --
| ninja: error: '/home/buildbot/oe-core/build/tmp/work/cortexa53-tdx-linux/mariadb/10.7.4-r0/recipe-sysroot/usr/lib/libssl.so' needed by 'application', missing and no known rule to make it
| WARNING: exit code 1 from a shell command.
ERROR: Task (/home/.../application_1.0.0.bb:do_compile) failed with exit code '1'
The error say libssl.so is needed but missing. You need to add in your .bbappend file a build dependency (and maybe runtime dependency?)
DEPENDS += "openssl"
RDEPENDS += "openssl"

CLion: run tests before build

I made a project in CLion (C++ + CMake) where I have a shared library project with 2 configurations Debug | Release. I have also implemented google tests for unit testing.
When the configuration is Release I would like to run some tests (or all) before the build. When the tests fail the library should not be build.
Is this possible? If so how?
I have found the answer with add_custom_command().
In my main CMakeLists.txt I have
if(${CMAKE_BUILD_TYPE} STREQUAL "Release")
#Rebuild the tests just in case some tests has changed and the executable was not rebuild
add_custom_command(TARGET ${PROJECT_NAME} PRE_BUILD
COMMAND ${CMAKE_COMMAND} --build "${CMAKE_BINARY_DIR}" --target tests --
)
if(${WIN32})
set(TESTS_BIN tests.exe)
else()
set(TESTS_BIN tests)
endif()
#Run the tests executable
add_custom_command(TARGET ${PROJECT_NAME} PRE_BUILD
COMMAND "${CMAKE_BINARY_DIR}/${TESTS_BIN}"
)
endif()
The add_custom_command() is smart therefore when the tests executable doesn't return 0 (all test have passed successfully) the build will fail and the library will not be build.

how to use CTest with Node js command, for testing JS file compiled from C++ using emscripten, and use Catch2?

I am try to use Catch2 library for testing and compile it with emscripten and run the test. The directory structure of my project look like this
|- CMakeLists.txt
|- build
|   |- ...
|   |- try-test.js
|   |- try-test.wasm
|   |- try-test.wast
|- test
|   |- main.cpp
|- third_party
|- Catch2
|- ...
when I am move to build directory and run node try-test.js, it success. but when i am run ctest, it fail. Below is the output message.
Test project /Users/janucaria/Projects/junk/em-cpp-unit-test/build
Start 1: trytest
Could not find executable node /Users/janucaria/Projects/junk/em-cpp-unit-test/build/try-test.js
Looked in the following places:
node /Users/janucaria/Projects/junk/em-cpp-unit-test/build/try-test.js
node /Users/janucaria/Projects/junk/em-cpp-unit-test/build/try-test.js
node /Users/janucaria/Projects/junk/em-cpp-unit-test/build/Release/try-test.js
node /Users/janucaria/Projects/junk/em-cpp-unit-test/build/Release/try-test.js
node /Users/janucaria/Projects/junk/em-cpp-unit-test/build/Debug/try-test.js
node /Users/janucaria/Projects/junk/em-cpp-unit-test/build/Debug/try-test.js
node /Users/janucaria/Projects/junk/em-cpp-unit-test/build/MinSizeRel/try-test.js
node /Users/janucaria/Projects/junk/em-cpp-unit-test/build/MinSizeRel/try-test.js
node /Users/janucaria/Projects/junk/em-cpp-unit-test/build/RelWithDebInfo/try-test.js
node /Users/janucaria/Projects/junk/em-cpp-unit-test/build/RelWithDebInfo/try-test.js
node /Users/janucaria/Projects/junk/em-cpp-unit-test/build/Deployment/try-test.js
node /Users/janucaria/Projects/junk/em-cpp-unit-test/build/Deployment/try-test.js
node /Users/janucaria/Projects/junk/em-cpp-unit-test/build/Development/try-test.js
node /Users/janucaria/Projects/junk/em-cpp-unit-test/build/Development/try-test.js
Unable to find executable: node /Users/janucaria/Projects/junk/em-cpp-unit-test/build/try-test.js
1/1 Test #1: trytest ..........................***Not Run 0.00 sec
0% tests passed, 1 tests failed out of 1
Total Test time (real) = 0.01 sec
The following tests FAILED:
1 - trytest (Not Run)
Errors while running CTest
Am I missing something here?
here is my test/main.cpp
#define CATCH_CONFIG_MAIN
#include <catch2/catch.hpp>
TEST_CASE("Try test")
{
int foo = 1;
REQUIRE(foo == 1);
}
and here the CMakeLists.txt
cmake_minimum_required(VERSION 3.11)
project(trytest)
enable_testing()
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
add_executable(try-test "test/main.cpp")
target_include_directories(try-test
PRIVATE
"${PROJECT_SOURCE_DIR}/third_party/Catch2/single_include"
)
target_compile_options(try-test PRIVATE "-Wall" "-Wpedantic" "-stdlib=libc++")
add_test(
NAME trytest
COMMAND "node ${CMAKE_CURRENT_BINARY_DIR}/try-test.js")
I would be grateful for any help you are able to provide.
I figure it out. I am use add_test wrong. It should be
add_test(
NAME trytest
COMMAND node "${CMAKE_CURRENT_BINARY_DIR}/try-test.js")
so the ctest will run command node with arguments ${CMAKE_CURRENT_BINARY_DIR}/try-test.js

When using CMake + CTest + CDash can I have an optional test fixture?

I am using CMake FIXTURES_SETUP/FIXTURES_REQUIRED to only run tests if an external resource is available. However, the external resource is optional (available on some test machines, but not others) so when the fixture that checks for the resource fails I do not want to consider the tests suite to have failed, I simply do not want to run any tests that require the fixture. Is there a way to mark a test fixture as 'allowed to fail'. I know there is WILL_FAIL but this inverts the sense of the test so that it would be marked as failure when it passes.
No. When you add a test that means you expect that test to pass. When a prerequisite of that test fails, CMake skips that test (does not actually run it) and counts it as failed because it did not succeed.
e.g.
# CMakeLists.txt
cmake_minimum_required(VERSION 3.3)
project(example)
enable_testing()
add_test(NAME failIfUnavail COMMAND false)
add_test(NAME dependentTest1 COMMAND true)
add_test(NAME dependentTest2 COMMAND true)
add_test(NAME cleaner COMMAND true)
set_tests_properties(failIfUnavail PROPERTIES FIXTURES_SETUP example_case)
set_tests_properties(dependentTest1 dependentTest2 PROPERTIES FIXTURES_REQUIRED example_case)
set_tests_properties(cleaner PROPERTIES FIXTURES_CLEANUP example_case)
$ cmake -H. -Bbuild
-- The C compiler identification is GNU 8.2.0
-- The CXX compiler identification is GNU 8.2.0
-- Check for working C compiler: /bin/gcc
-- Check for working C compiler: /bin/gcc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /bin/g++
-- Check for working CXX compiler: /bin/g++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /build
$ cmake --build build/ --target test
Running tests...
Test project /home/pamini/cmake_test1/build
Start 1: failIfUnavail
1/4 Test #1: failIfUnavail ....................***Failed 0.00 sec
Start 2: dependentTest1
Failed test dependencies: failIfUnavail
2/4 Test #2: dependentTest1 ...................***Not Run 0.00 sec
Start 3: dependentTest2
Failed test dependencies: failIfUnavail
3/4 Test #3: dependentTest2 ...................***Not Run 0.00 sec
Start 4: cleaner
4/4 Test #4: cleaner .......................... Passed 0.00 sec
25% tests passed, 3 tests failed out of 4
Total Test time (real) = 0.02 sec
The following tests FAILED:
1 - failIfUnavail (Failed)
2 - dependentTest1 (Not Run)
3 - dependentTest2 (Not Run)
Errors while running CTest
gmake: *** [test] Error 8
What you can do is:
If the resource's availability is known at configuration time then check and only add the tests when you expect them to pass.
If the resource's availability is not known at configuration time then modify the tests themselves to account for this uncertainty. For example, unit tests avoid this issue by using mock objects that imitate the behavior of the resources they depend on.

How to force cmake to write test output after make test

I'm building fortran project with cmake and I can't find solution to print to console FRUIT test results, they look something like these:
Test module initialized
. : successful assert, F : failed assert
7.00000000000000 -3.60000000000000 7.00000000000000
FFF
Start of FRUIT summary:
Some tests failed!
-- Failed assertion messages:
[_not_set_]:Expected [7.00000000000000], Got [1.00000000000000]
[_not_set_]:Expected [-3.60000000000000], Got [2.00000000000000]
[_not_set_]:Expected [7.00000000000000], Got [6.00000000000000]
-- end of failed assertion messages.
Total asserts : 3
Successful : 0
Failed : 3
Successful rate: 0.00%
Successful asserts / total asserts : [ 0 / 3 ]
Successful cases / total cases : [ 0 / 0 ]
-- end of FRUIT summary
The output I'm getting with make test looks like:
make test
Running tests...
Test project /home/konrad/Desktop/fortran
Start 1: unit_tests
1/1 Test #1: unit_tests ....................... Passed 0.01 sec
100% tests passed, 0 tests failed out of 1
Total Test time (real) = 0.01 sec
And since passing cmake tests doesn't mean passing FRUIT ones, I want to print FRUIT file everytime I run tests (just for the sake of making it work). I've tried adding printing commands at the end of test command (like this less), adding
-P ${CMAKE_TEST_DIR}/unit_tests.txt
at the end of add_test, building custom after build commands (which I can't make to run after make test so if you knew how to do that would solve it as well, seems like make test or test is not really a target)
Last part of my cmake file with all the testing code:
add_executable(task ${TASK_SOURCES})
add_executable(tests ${TEST_SOURCES})
enable_testing()
set(run_command "${CMAKE_BINARY_DIR}/tests")
set(UNIT_TEST_NAME "unit_tests.txt")
file(MAKE_DIRECTORY ${CMAKE_TEST_DIR})
add_test( NAME unit_tests
COMMAND sh -c
"rm -f ${CMAKE_TEST_DIR}/${UNIT_TEST_NAME} \
&& ${run_command} \
>> ${CMAKE_TEST_DIR}/${UNIT_TEST_NAME} \
&& less ${CMAKE_TEST_DIR}/${UNIT_TEST_NAME}"
)
I have solved a lack of tests output with custom CMake target that will invoke ctest in verbose mode etc.
e.g.
enable_testing()
add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND}
--force-new-ctest-process
--verbose
--output-on-failure
)
The output of cmake tests is captured to a file (Testing/Temporary/LastTest.log in my current project).
cmake tests rely on the return code of the test program, with one test program per test.
If you wish to run a program that is a "driver" for your tests, I recommend to use add_custom_target. This commands will add a target that runs a command of your choice.
For instance:
add_custom_target(Name unit_tests tests)
add_dependencies(unit_tests tests)
I am not sure whether the add_dependencies line is needed in this case though (as tests is a target managed by cmake).
Then, you can run
make unit_tests
and it will run your test driver.