From 9fd2715a333adba6edf5f9ea7ef871401f7b4d1d Mon Sep 17 00:00:00 2001 From: Diogo Behrens Date: Sat, 20 Sep 2025 14:35:11 +0200 Subject: [PATCH] cmake: Add option to measure test coverage Signed-off-by: Diogo Behrens --- CMakeLists.txt | 4 ++++ src/dice/CMakeLists.txt | 9 +++++++++ src/mod/CMakeLists.txt | 7 +++++++ test/pthread_exit_window.c | 8 +++++++- test/traces/trace_lock_unlock.c | 8 ++++++++ test/traces/trace_mutex_2.cpp | 9 ++++----- 6 files changed, 39 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5d866db8..e8a1a61c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -43,6 +43,9 @@ include(GNUInstallDirs) include(CheckSymbolExists) include(cmake/export.cmake) +# Coverage +option(DICE_COVERAGE "Enable test coverage" off) + # TSAN on Clang requires the following flag set(LIBSAN_SHARED) if(CMAKE_C_COMPILER_ID STREQUAL "Clang") @@ -84,6 +87,7 @@ else() endif() option(DICE_TESTS "Enable Dice tests" ${TESTS_DEFAULT}) if(${DICE_TESTS}) + include(CTest) enable_testing() add_subdirectory(test) endif() diff --git a/src/dice/CMakeLists.txt b/src/dice/CMakeLists.txt index d1cc1da4..f204a372 100644 --- a/src/dice/CMakeLists.txt +++ b/src/dice/CMakeLists.txt @@ -84,6 +84,15 @@ add_library(dice SHARED ${SRCS}) target_link_libraries(dice PUBLIC dice.h pthread) install(TARGETS dice DESTINATION lib) +if(${DICE_COVERAGE}) + # do not involve dice-dispatch/dice-box in the coverage metrics + set(TARGETS dice.o dice) + foreach(TARGET ${TARGETS}) + target_compile_options(${TARGET} PRIVATE --coverage) + target_link_options(${TARGET} PUBLIC --coverage) + endforeach() +endif() + if(${ENABLE_SANITIZER}) set(TARGETS rbtree_test dice.o dice) foreach(TARGET ${TARGETS}) diff --git a/src/mod/CMakeLists.txt b/src/mod/CMakeLists.txt index a87b9d70..3de6d2b6 100644 --- a/src/mod/CMakeLists.txt +++ b/src/mod/CMakeLists.txt @@ -39,6 +39,13 @@ foreach(SRC ${SRCS}) PRIVATE -fsanitize=${DICE_SANITIZER}) endif() endif() + + if(${DICE_COVERAGE}) + foreach(ENDING "" ".o" "_testing.o") + target_compile_options(${TARGET}${ENDING} PRIVATE --coverage) + target_link_options(${TARGET}${ENDING} PUBLIC --coverage) + endforeach() + endif() endforeach() target_link_libraries(dice-self PRIVATE pthread) diff --git a/test/pthread_exit_window.c b/test/pthread_exit_window.c index 52ea255f..0e00ac91 100644 --- a/test/pthread_exit_window.c +++ b/test/pthread_exit_window.c @@ -18,6 +18,7 @@ static int exit_called; // TLS key and once guard static pthread_key_t key; static pthread_once_t once; +static void *arg_check; // keep arg in a variable to double check later // A once-initializer to make Alpine Linux happy. This is called in the second // thread and in the main thread but the compilation on Alpine doesn't like it. @@ -36,7 +37,8 @@ run(void *_) { (void)_; pthread_once(&once, tls_init); - if (pthread_setspecific(key, (const void *)malloc(123)) != 0) + arg_check = malloc(123); + if (pthread_setspecific(key, (const void *)arg_check) != 0) abort(); log_printf("1) tid = %p\n", (void *)pthread_self()); return 0; @@ -75,6 +77,10 @@ PS_SUBSCRIBE(CAPTURE_BEFORE, EVENT_FREE, { if (exit_called == 0) return PS_OK; + struct free_event *ev = EVENT_PAYLOAD(ev); + if (ev->ptr != arg_check) + return PS_OK; + log_printf("4) tid = %p\tself = %p\n", (void *)pthread_self(), md); log_printf("Retired thread before free. ID should be 2\n"); log_printf("\tuid = %lu\n", self_id(md)); diff --git a/test/traces/trace_lock_unlock.c b/test/traces/trace_lock_unlock.c index aa4b230f..39ea2b19 100644 --- a/test/traces/trace_lock_unlock.c +++ b/test/traces/trace_lock_unlock.c @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -13,8 +14,15 @@ struct expected_event expected[] = { EXPECTED_EVENT(CAPTURE_EVENT, EVENT_SELF_INIT), + EXPECTED_SUFFIX(CAPTURE_EVENT, EVENT_THREAD_START), EXPECTED_SUFFIX(CAPTURE_BEFORE, EVENT_PTHREAD_MUTEX_LOCK), EXPECTED_EVENT(CAPTURE_AFTER, EVENT_PTHREAD_MUTEX_LOCK), + + // when checking coverage, these are also triggered + EXPECTED_SOME(CAPTURE_EVENT, EVENT_MA_READ, 0, 1), + EXPECTED_SOME(CAPTURE_EVENT, EVENT_MA_WRITE, 0, 1), + // end + EXPECTED_EVENT(CAPTURE_BEFORE, EVENT_PTHREAD_MUTEX_UNLOCK), EXPECTED_EVENT(CAPTURE_AFTER, EVENT_PTHREAD_MUTEX_UNLOCK), EXPECTED_SUFFIX(CAPTURE_EVENT, EVENT_SELF_FINI), diff --git a/test/traces/trace_mutex_2.cpp b/test/traces/trace_mutex_2.cpp index 58641bee..f84b9998 100644 --- a/test/traces/trace_mutex_2.cpp +++ b/test/traces/trace_mutex_2.cpp @@ -82,14 +82,13 @@ struct expected_event expected_1[] = { EXPECTED_EVENT(CAPTURE_BEFORE, EVENT_THREAD_JOIN), EXPECTED_EVENT(CAPTURE_AFTER, EVENT_THREAD_JOIN), -#if defined(__linux__) EXPECTED_EVENT(CAPTURE_EVENT, EVENT_STACKTRACE_EXIT), - EXPECTED_EVENT(CAPTURE_EVENT, EVENT_THREAD_EXIT), - EXPECTED_EVENT(CAPTURE_EVENT, EVENT_SELF_FINI), - EXPECTED_END, -#elif defined(__NetBSD__) EXPECTED_SUFFIX(CAPTURE_EVENT, EVENT_THREAD_EXIT), EXPECTED_SUFFIX(CAPTURE_EVENT, EVENT_SELF_FINI), + +#if defined(__linux__) + EXPECTED_END, +#elif defined(__NetBSD__) EXPECTED_ANY_SUFFIX, #endif };