test: add ThreadSanitizer verification for lock-free Channel<T>
Add a contended SPSC stress suite (tests/test_channel_stress.cpp) that actually exercises the ring's memory-ordering pairing and spin/futex/ lost-wakeup logic, plus the CMake and CI plumbing to run it under TSan: - KPN_SANITIZER cache var + kpn_sanitizer_flags() helper (no-op when unset) - kpn_tests_stress executable, labelled "stress" for CTest - reusable tsan.yaml workflow (gcc:14 builder image, already ships libtsan) - ci.yaml gains a tsan job on the same code/dockerfile triggers as test Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+30
-1
@@ -43,6 +43,35 @@ target_link_libraries(kpn_tests PRIVATE
|
||||
GTest::gtest
|
||||
)
|
||||
|
||||
# ── Channel stress suite (separate executable) ────────────────────────────────
|
||||
# Contended SPSC tests for the lock-free Channel<T>. Kept out of kpn_tests
|
||||
# because each case runs many reps / tens of thousands of items and is slow.
|
||||
# Most valuable under -DKPN_SANITIZER=thread, but correct (and run) without it.
|
||||
add_executable(kpn_tests_stress test_channel_stress.cpp)
|
||||
target_link_libraries(kpn_tests_stress PRIVATE kpn Catch2::Catch2WithMain)
|
||||
|
||||
# ── Sanitizer flags ───────────────────────────────────────────────────────────
|
||||
# kpn_sanitizer_flags() is defined in the top-level CMakeLists and is a no-op
|
||||
# unless -DKPN_SANITIZER=... is set. Sanitizer must be on both compile and link.
|
||||
kpn_sanitizer_flags(_kpn_san)
|
||||
if(_kpn_san)
|
||||
foreach(_t kpn_tests kpn_tests_stress)
|
||||
target_compile_options(${_t} PRIVATE ${_kpn_san})
|
||||
target_link_options(${_t} PRIVATE ${_kpn_san})
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
include(CTest)
|
||||
include(Catch)
|
||||
catch_discover_tests(kpn_tests)
|
||||
|
||||
# DISCOVERY_MODE PRE_TEST defers test enumeration to `ctest` run time. The
|
||||
# default (POST_BUILD) runs each test binary during the build to list its
|
||||
# cases — which fails a sanitizer build: a TSan/ASan binary needs a fixed
|
||||
# address-space layout and aborts on startup ("unexpected memory mapping")
|
||||
# under the container's ASLR, breaking the build before any test runs. The
|
||||
# tsan.yaml job invokes the binaries directly (not via ctest), so deferring
|
||||
# discovery costs nothing there and keeps `ctest` working for normal builds.
|
||||
catch_discover_tests(kpn_tests DISCOVERY_MODE PRE_TEST)
|
||||
# Register the stress suite under its own label so CI can run / time it
|
||||
# separately from the fast unit tests.
|
||||
catch_discover_tests(kpn_tests_stress DISCOVERY_MODE PRE_TEST PROPERTIES LABELS "stress")
|
||||
|
||||
Reference in New Issue
Block a user