-
Notifications
You must be signed in to change notification settings - Fork 0
Test Infrastructure
The project uses a comprehensive testing approach with regression tests, unit tests, and CI integration tests.
The main test runner is run_test.py (repository root), a Python script that:
- Discovers test fixture files
- Runs the analyzer on each fixture
- Validates output against expected diagnostics from source comments
- Supports parallel execution and caching
# Run all tests
python3 run_test.py --analyzer ./build/stack_usage_analyzer
# Run a specific test directory
python3 run_test.py --analyzer ./build/stack_usage_analyzer test/bound-storage/
# Run a single test file
python3 run_test.py --analyzer ./build/stack_usage_analyzer test/bound-storage/bound-storage.c
# Parallel execution
python3 run_test.py --analyzer ./build/stack_usage_analyzer --jobs 4Test fixtures are C/C++ source files with expected diagnostic annotations in comments:
// at line 12, column 14
// [ !!Warn ] potential stack buffer overflow on variable 'test' (size 10)
// ... alias path: test
// ... constant index 11 is out of bounds (0..9)
// ... (this is a write access)
int main(void)
{
char test[10];
test[11] = 'a'; // line 12
return 0;
}Warning-level diagnostic:
// [ !!Warn ] <message prefix>Error-level diagnostic:
// [!!Error] <message prefix>Info-level diagnostic:
// [!Info] <message prefix>Location annotation (must precede the diagnostic):
// at line <N>, column <N>Per-file model selection:
// resource-model: models/resource-lifetime/generic.txt
// escape-model: models/stack-escape/generic.txt| Directory | What it tests |
|---|---|
test/alloca/ |
Dynamic alloca, VLA, user-controlled sizes, oversized |
test/bound-storage/ |
Buffer overflow, alias chains, struct arrays, reachability |
test/cpy-buffer/ |
memcpy/memset overflow detection |
test/diagnostics/ |
Duplicate if-else conditions |
test/escape-stack/ |
Stack pointer escape (store, callback, return) |
test/false-positive-repro/ |
Regression tests for known false positives |
test/local-storage/ |
Stack frame size, callee propagation |
test/multiple-storage/ |
Multiple stores to same buffer |
test/no-error/ |
Files that should produce no diagnostics |
test/offset_of-container_of/ |
container_of macro, pointer arithmetic |
test/pointer_reference-const_correctness/ |
Const parameter detection |
test/resource-lifetime/ |
Resource lifecycle (missing/double release, cross-TU) |
test/size-arg/ |
Size-minus-one patterns |
test/uninitialized-variable/ |
Uninitialized local variable reads |
test/vla/ |
Variable-length array detection |
Fine-grained unit tests for core analyzer modules.
cmake -S . -B build -DBUILD_ANALYZER_UNIT_TESTS=ON ...
cmake --build build# Via CTest
cd build && ctest -R analyzer_module_unit_tests
# Direct execution (pass source dir as argument)
./build/stack_usage_analyzer_unit_tests /path/to/coretrace-stack-analyzer-
LocationResolver-- debug info to source location conversion -
Reachability-- unreachable code filtering heuristics -
ModulePreparationService-- stack size computation, call graph building
test/unit/analyzer_module_unit_tests.cpp
The test runner also invokes unit tests automatically via check_analyzer_module_unit_tests().
fixtures/ contains CI integration test fixtures:
- CMake projects with
compile_commands.jsongeneration - Tests the full pipeline: build + analyze + validate
| Workflow | Purpose |
|---|---|
.github/workflows/ci.yml |
Main CI: build + test on Ubuntu |
.github/workflows/clang-format.yml |
Code format compliance check |
.github/workflows/commit-check.yml |
Commit message validation |
.github/workflows/publish-docker.yml |
Docker image build and push |
.github/workflows/test-ci-integration.yml |
End-to-end CI integration tests |
- Create a directory under
test/matching your check name - Add one or more
.c/.cppfiles with annotated expectations - Include both positive (triggering) and negative (clean) cases
- Add a false-positive regression test if needed under
test/false-positive-repro/
-
basic-case.c-- simple triggering case -
no-error.cor*-ok.c-- clean code, no diagnostics expected -
*-interproc*.c-- cross-function or cross-TU tests -
*-nested*.c-- nested construct variations
For tests that require multiple files (resource or uninitialized cross-TU), use matching prefixes:
test/resource-lifetime/cross-tu-wrapper-def.c # defines the wrapper
test/resource-lifetime/cross-tu-wrapper-use.c # uses the wrapper
test/uninitialized-variable/cross-tu-uninitialized-wrapper-def.c
test/uninitialized-variable/cross-tu-uninitialized-wrapper-use.c
run_test.py supports caching to avoid re-running unchanged tests. Cache is invalidated when:
- The analyzer binary changes
- The test file changes
- The expected annotations change