I run unit tests by building with ninja
and then running ninja test
from my build tree:
cmake -G Ninja /source/tree ninja ninja test
However, to run valgrind I need to run it manually:
valgrind rel/path/to/test
I'd like valgrind
to run automatically when I run ninja test
. According to the cmake documentation "setting up [valgrind tests] is extremely easy", but when I run
ctest -D NightlyMemoryCheck
I just get this error:
Cannot find file: /home/arman/tinman/deb/DartConfiguration.tcl Site: Build name: (empty) WARNING: No nightly start time found please set in CTestConfig.cmake or DartConfig.cmake Problem initializing the dashboard.
I get a similar error when I follow the instructions from this SO question:
How do I make ctest run a program with valgrind without dart?
I don't know what dart
is, but according the website it's some kind of online testing doodad.
Clearly extremely easy is not easy enough for me. Does anyone know of a solution that is so supremely easy that you'd have to be some kind of IT warlock to make it not work?
To add testing to a CMake-based project, simply include(CTest) and use the add_test command.
Run the tests in parallel using the given number of jobs. This option tells CTest to run the tests in parallel using given number of jobs. This option can also be set by setting the CTEST_PARALLEL_LEVEL environment variable. This option can be used with the PROCESSORS test property.
Here is a self contained example that shows how to add valgrind tests to a CMake project. The example consists of a single C++ source file main.cpp
:
#include <iostream> int main() { double* leak = new double[10]; std::cout << "Hello!" << std::endl; }
The code contains an intentional leak which should be picked up by valgrind. We also need a CMakeLists.txt
file which requires CMake >= 2.8:
cmake_minimum_required(VERSION 2.8) project (ValgrindExample) include (CTest) add_executable(example main.cpp) add_test(example_test example)
Here it is important to include the CTest module with include
instead of just enabling tests with enable_testing()
. The CTest module takes care of setting up the machinery for being able to run memory checks with tests (e.g., it locates the valgrind executable).
Now we can open a shell session in the project folder and create a Ninja build tree:
$ mkdir build; cd build $ cmake -G Ninja -DCMAKE_BUILD_TYPE=Debug ..
We can build and run tests without valgrind in the regular way:
$ ninja [2/2] Linking CXX executable example $ ninja test [0/1] Running tests... ... 100% tests passed, 0 tests failed out of 1 Total Test time (real) = 0.01 sec
To run tests with valgrind we have to use CMake's ctest executable with the test action memcheck
:
$ ctest -T memcheck ... 1/1 MemCheck #1: example_test ..................... Passed 0.77 sec 100% tests passed, 0 tests failed out of 1 Total Test time (real) = 0.77 sec -- Processing memory checking output: Memory checking results: Memory Leak - 2
ctest prints a summary of the memory checking results. The detailed output of valgrind is located in a temporary directory in the build tree:
$ cat ./Testing/Temporary/MemoryChecker.*.log ==4565== 80 bytes in 1 blocks are definitely lost in loss record 37 of 64 ==4565== at 0x10000B681: malloc (in /usr/local/Cellar/valgrind/3.12.0/lib/valgrind/vgpreload_memcheck-amd64-darwin.so) ==4565== by 0x1000507DD: operator new(unsigned long) (in /usr/lib/libc++.1.dylib) ==4565== by 0x100000F93: main (main.cpp:5) ...
It is not possible to automatically run valgrind when you run ninja test
because CMake's built-in test target cannot be modified and always runs tests in the regular way. We can however add a custom CMake target which invokes ctest with the -T memcheck
option and then prints the detailed valgrind report:
add_custom_target(test_memcheck COMMAND ${CMAKE_CTEST_COMMAND} --force-new-ctest-process --test-action memcheck COMMAND cat "${CMAKE_BINARY_DIR}/Testing/Temporary/MemoryChecker.*.log" WORKING_DIRECTORY "${CMAKE_BINARY_DIR}")
--test-action
is the verbose version of the switch -T
.
We then can invoke valgrind testing from Ninja with
$ ninja test_memcheck
and get the results as if we ran valgrind manually.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With