chore: add valgrind and thread sanitizer test profiles [skip ci]

This commit is contained in:
Loric ANDRE 2026-01-29 19:19:03 +01:00
parent b96c65507e
commit 015fd28db6
3 changed files with 113 additions and 1 deletions

View file

@ -1,13 +1,68 @@
experimental = ["setup-scripts"] experimental = ["setup-scripts", "wrapper-scripts"]
[scripts.setup.stop-tmux] [scripts.setup.stop-tmux]
command = "sh -c 'tmux kill-session -t skim_e2e || true'" command = "sh -c 'tmux kill-session -t skim_e2e || true'"
[scripts.setup.start-tmux] [scripts.setup.start-tmux]
command = "tmux new-session -d -s skim_e2e -n skim_e2e" command = "tmux new-session -d -s skim_e2e -n skim_e2e"
# Valgrind wrapper for memory leak detection
[scripts.wrapper.valgrind]
command = [
"valgrind",
"--leak-check=full",
"--show-leak-kinds=all",
"--track-origins=yes",
"--error-exitcode=1",
"--suppressions=.config/valgrind.supp"
]
[profile.default] [profile.default]
fail-fast = false fail-fast = false
retries = 9 retries = 9
[[profile.default.scripts]] [[profile.default.scripts]]
platform = "cfg(unix)" platform = "cfg(unix)"
setup = ["stop-tmux", "start-tmux"] setup = ["stop-tmux", "start-tmux"]
# Valgrind profile for memory leak detection
# Usage: cargo nextest run --profile valgrind --features test-utils
#
# Note: Valgrind can detect memory leaks but does NOT detect dangling threads.
# For thread leak detection, use ThreadSanitizer instead (see below).
[profile.valgrind]
fail-fast = false
retries = 2
test-threads = 1 # Run tests serially to avoid interleaved valgrind output
[[profile.valgrind.scripts]]
platform = "cfg(unix)"
setup = ["stop-tmux", "start-tmux"]
run-wrapper = "valgrind"
# ThreadSanitizer profile for detecting data races and thread issues
# Usage:
# 1. First build with sanitizer (rebuilds stdlib and all deps):
# RUSTFLAGS="-Zsanitizer=thread" cargo +nightly build --tests --features test-utils -Zbuild-std --target x86_64-unknown-linux-gnu
# 2. Then run tests:
# TSAN_OPTIONS="detect_deadlocks=1" cargo +nightly nextest run --profile tsan --features test-utils --target x86_64-unknown-linux-gnu
#
# Note: ThreadSanitizer can detect:
# - Data races (concurrent unsynchronized access to memory)
# - Deadlocks (with TSAN_OPTIONS=detect_deadlocks=1)
# - Thread leaks (threads not joined before program exit)
#
# Requirements:
# - Rust nightly (for -Zsanitizer and -Zbuild-std flags)
# - The -Zbuild-std flag rebuilds the standard library with ThreadSanitizer
# instrumentation to avoid ABI mismatch errors
#
# Important: This takes a long time on first build as it recompiles everything
# including the standard library with ThreadSanitizer instrumentation.
#
# Environment variables:
# TSAN_OPTIONS="detect_deadlocks=1 second_deadlock_stack=1"
[profile.tsan]
fail-fast = false
retries = 3
test-threads = 1 # TSan requires running tests serially
[[profile.tsan.scripts]]
platform = "cfg(unix)"
setup = ["stop-tmux", "start-tmux"]

53
.config/valgrind.supp Normal file
View file

@ -0,0 +1,53 @@
# Valgrind suppressions for skim tests
# This file suppresses known false positives from Rust stdlib and system libraries
# Rust std allocations that are intentionally not freed at program exit
{
rust_std_exit_cleanup
Memcheck:Leak
...
fun:*std*
}
# Thread-local storage cleanup
{
thread_local_cleanup
Memcheck:Leak
...
fun:pthread_create*
}
# Tokio runtime allocations
{
tokio_runtime
Memcheck:Leak
...
fun:*tokio*runtime*
}
# Crossterm/terminal allocations
{
crossterm_terminal
Memcheck:Leak
...
fun:*crossterm*
}
# Libc thread initialization
{
libc_thread_init
Memcheck:Leak
match-leak-kinds: possible
...
fun:calloc
fun:allocate_dtv
}
# DL allocations
{
dl_init
Memcheck:Leak
match-leak-kinds: possible
...
fun:*dl_*
}

View file

@ -6,6 +6,10 @@
- Test (all): `cargo nextest --features test-utils` - Test (all): `cargo nextest --features test-utils`
- Test (single): `cargo nextest test_name --features test-utils` - Test (single): `cargo nextest test_name --features test-utils`
- Integration/E2E tests: `cargo nextest --tests --features test-utils` (will need tmux under the hood) - Integration/E2E tests: `cargo nextest --tests --features test-utils` (will need tmux under the hood)
- Memory leak detection: `cargo nextest run --profile valgrind --features test-utils`
- Thread leak/race detection:
1. Build: `RUSTFLAGS="-Zsanitizer=thread" cargo +nightly build --tests --features test-utils -Zbuild-std --target x86_64-unknown-linux-gnu`
2. Run: `TSAN_OPTIONS="detect_deadlocks=1" cargo +nightly nextest run --profile tsan --features test-utils --target x86_64-unknown-linux-gnu`
- Lint: `cargo clippy` - Lint: `cargo clippy`
- Format: `cargo fmt` (check only: `cargo fmt --check`) - Format: `cargo fmt` (check only: `cargo fmt --check`)