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>
70 lines
2.8 KiB
CMake
70 lines
2.8 KiB
CMake
cmake_minimum_required(VERSION 3.21)
|
|
|
|
# ── Catch2 ────────────────────────────────────────────────────────────────────
|
|
find_package(Catch2 3 QUIET)
|
|
if(NOT Catch2_FOUND)
|
|
include(FetchContent)
|
|
FetchContent_Declare(
|
|
Catch2
|
|
GIT_REPOSITORY https://github.com/catchorg/Catch2.git
|
|
GIT_TAG v3.5.3
|
|
)
|
|
FetchContent_MakeAvailable(Catch2)
|
|
endif()
|
|
|
|
# ── Google Test ───────────────────────────────────────────────────────────────
|
|
find_package(GTest QUIET)
|
|
if(NOT GTest_FOUND)
|
|
include(FetchContent)
|
|
FetchContent_Declare(
|
|
googletest
|
|
GIT_REPOSITORY https://github.com/google/googletest.git
|
|
GIT_TAG v1.14.0
|
|
)
|
|
FetchContent_MakeAvailable(googletest)
|
|
endif()
|
|
|
|
# ── Test executable ───────────────────────────────────────────────────────────
|
|
add_executable(kpn_tests
|
|
test_fixed_string.cpp
|
|
test_traits.cpp
|
|
test_channel.cpp
|
|
test_node.cpp
|
|
test_network.cpp
|
|
test_static_network.cpp
|
|
test_shared_resource.cpp
|
|
test_pool_node.cpp
|
|
test_scheduler.cpp
|
|
)
|
|
|
|
target_link_libraries(kpn_tests PRIVATE
|
|
kpn
|
|
Catch2::Catch2WithMain
|
|
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)
|
|
# 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 PROPERTIES LABELS "stress")
|