Rumburak
Rumburak

Reputation: 3571

How to test the static_assert in my library with cmake?

in my library code I have a bunch of static_asserts. I want to test if they fire under the expected conditions.

I would like to write a range of test files and

Does anyone know how to do that with cmake?

AFAICT, try_compile is not the answer, because it is executed while running cmake. I need these checks to be executed during make.

Upvotes: 4

Views: 1783

Answers (3)

nocnokneo
nocnokneo

Reputation: 1967

Add this to your CMakeLists.txt:

include(CTest)

# Test that code is NOT able to compile
function(TestStaticCheck TEST_NAME)
    add_executable(${TEST_NAME} EXCLUDE_FROM_ALL ${TEST_NAME}.cpp)
    target_link_libraries(${TEST_NAME} MyLibrary)
    add_test(NAME ${TEST_NAME}
        COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target ${TEST_NAME}
        )
    set_tests_properties(${TEST_NAME} PROPERTIES WILL_FAIL TRUE)
endfunction()

TestStaticCheck(TestFoo)

Then put this in TestFoo.cpp in the same directory as your CMakeLists.txt:

int main()
{
    // Code that should NOT compile
}

Upvotes: 0

Rumburak
Rumburak

Reputation: 3571

After several more experiments, this is what I am doing now:

add_executable(
  fail_test
  EXCLUDE_FROM_ALL
  fail_test.cpp
  )

add_custom_command(OUTPUT fail_test.out
    COMMAND ${CMAKE_MAKE_PROGRAM} fail_test > ${CMAKE_CURRENT_BINARY_DIR}/fail_test.out 2>&1  || true
    COMMAND grep "int i = row.alpha" ${CMAKE_CURRENT_BINARY_DIR}/fail_test.out > /dev/null
    DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/fail_test.cpp
    COMMENT "fail_test"
    )

add_custom_target(test_constraints DEPENDS fail_test.out COMMAND true)

This is what it does:

  1. Create a target for compiling the code that is supposed to fail at compile time. Exclude this target from the default build so that it does not create a mess.
  2. Add a custom command that calls make for this fail-target, pipes the compiler spew into a file, ignores the result code and then greps for the expected compiler message that indicates that the compilation failed due to the expected reason.
  3. Make the custom command depend on the source file, so that the compilation is tested again when the source file is ended.
  4. Add the custom command as dependency to a custom target.

Of course, for more tests, steps 1, 2 and 4 would go into a function.

So now I can call

make test_constraints

to test if the stuff I want to fail compiling actually does so. And if something does not fail as expected, I can even call

make fail_test

to tune the test or its basis until it fails correctly.

For platform independence, the custom command will probably have to be adjusted. Suggestions welcome.

Upvotes: 1

You could set up a "nested" project for these tests, configure it as part of your CMake run and then build it using cmake --build; something like this:

Your normal CMakeLists.txt:

# ...
execute_process(
  COMMAND ${CMAKE_COMMAND} path/to/test/project
  WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/TestProject
)

add_test(
  NAME StaticAsserts
  WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/TestProject
  COMMAND ${CMAKE_COMMAND} --build .
)
# ...

Of course, the test command could actually be a wrapper script running cmake --build internally and processing its output.

As an alternative, you could move the configuration of the nested project into the test as well, perhaps using CTest to drive the configure & build.

Upvotes: 2

Related Questions