A multi-threaded stress test for Python's set object, designed to verify the correctness of lock-free __contains__ operations with QSBR-based memory management in free-threaded Python (PEP 703).
No issues were found. The lock-free __contains__ implementation passed all stress tests across multiple test modes, thread configurations, and durations.
This test suite creates multiple reader and writer threads that concurrently access a shared set. It targets specific code paths in the lock-free implementation:
set_lookkey_threadsafe()- Lock-free lookupset_compare_threadsafe()- Entry comparison with_Py_TryIncrefCompareset_table_resize()- Resize with QSBR cleanupset_swap_bodies()- Table swapping for in-place operations
The tests verify that no data races, memory ordering bugs, or crashes occur.
python3 main.py [OPTIONS]--mode MODE: Test mode (default: standard). See Test Modes below.--readers N: Number of reader threads (default: 4)--writers N: Number of writer threads (default: 2)--duration SECONDS: Test duration in seconds (default: 5.0)--small: Use small set mode (< 8 elements, PySet_MINSIZE threshold)--check-frequency N: How often readers perform consistency checks (default: 100)
| Mode | Target | Verification |
|---|---|---|
standard |
Basic concurrent read/write | Contiguous value ranges |
resize |
set_table_resize() + QSBR |
Crash/exception only |
swap |
set_swap_bodies() via __iand__ |
Crash/exception only |
discard |
Dummy entry handling | Crash/exception only |
hash_collision |
Linear probing paths | Crash/exception only |
threshold |
Small/large table transitions | Crash/exception only |
# Basic stress test
python3 main.py --duration 10 --readers 8 --writers 2
# Test resize operations specifically
python3 main.py --mode resize --duration 10 --readers 8
# Test set_swap_bodies (table=NULL race)
python3 main.py --mode swap --readers 8 --duration 5
# Small set test (< 8 elements) - tests smalltable representation
python3 main.py --small --readers 4 --writers 2 --duration 5
# Run all modes
for mode in standard resize swap discard hash_collision threshold; do
python3 main.py --mode $mode --duration 5
done| File | Purpose |
|---|---|
test_mutating_keys.py |
Tests keys that mutate the set in __hash__/__eq__ |
test_resize_race.py |
Targeted resize race condition tests |
run_tests.sh |
Runs all tests |
./run_tests.sh # Run all tests with defaults
./run_tests.sh --quick # Quick test (2s per test)
./run_tests.sh --thorough # Thorough test (30s per test, more threads)The test reports:
- Operations per second for readers and writers
- Consistency checks and failures detected during execution
- Verification results checking for data integrity
- Overall status (SUCCESS or FAILURE)
0: Test passed successfully1: Test failed (verification errors or exceptions occurred)