WoWee uses **Catch2 v3** (amalgamated) for unit testing and **clang-tidy** for static analysis. The `test.sh` script is the single entry point for both.
| Command | What it does |
|---|---|
| `./test.sh` | Runs both unit tests (Release) and lint |
| `./test.sh --test` | Runs unit tests only (Release build) |
| `./test.sh --lint` | Runs clang-tidy only |
| `./test.sh --asan` | Runs unit tests under ASAN + UBSan (Debug build) |
The test suite requires the same base toolchain used to build the project. See [BUILD_INSTRUCTIONS.md](BUILD_INSTRUCTIONS.md) for platform-specific dependency installation.
CMake will print: `Test targets: ASAN + UBSan ENABLED` when configured correctly.
---
## Running Tests
### test.sh — the unified entry point
`test.sh` is the recommended way to run tests and/or lint. It handles build-directory discovery, dependency checking, and exit-code aggregation across both steps.
```bash
# Run everything (tests + lint) — default when no flags are given
./test.sh
# Tests only (Release build)
./test.sh --test
# Tests only under ASAN+UBSan (Debug build — requires build_asan/)
./test.sh --asan
# Lint only
./test.sh --lint
# Both tests and lint explicitly
./test.sh --test --lint
# Usage summary
./test.sh --help
```
**Exit codes:**
| Outcome | Exit code |
|---|---|
| All tests passed, lint clean | `0` |
| Any test failed | `1` |
| Any lint diagnostic | `1` |
| Both test failure and lint issues | `1` |
### Running directly with ctest
```bash
# Release build
cd build
ctest --output-on-failure
# ASAN build
cd build_asan
ctest --output-on-failure
# Run one specific test suite by name
ctest --output-on-failure -R srp
# Verbose output (shows every SECTION and REQUIRE)
ctest --output-on-failure -V
```
You can also run a test binary directly for detailed Catch2 output:
```bash
./build/bin/test_srp
./build/bin/test_srp --reporter console
./build/bin/test_srp "[authentication]" # run only tests tagged [authentication]
```
---
## Lint (clang-tidy)
The project uses clang-tidy to enforce C++20 best practices on all first-party sources under `src/`. Third-party code (anything in `extern/`) and generated files are excluded.
### Running lint
```bash
./test.sh --lint
```
Under the hood the script:
1. Locates `clang-tidy` (tries versions 14–18, then `clang-tidy`).
2. Uses `run-clang-tidy` for parallel execution when available; falls back to sequential.
3. Reads `build/compile_commands.json` (generated by CMake) for compiler flags.
4. Feeds GCC stdlib include paths as `-isystem` extras so clang-tidy can resolve `<vector>`, `<string>`, etc. when the compile-commands were generated with GCC.
`compile_commands.json` is regenerated automatically by any CMake configure step. If you only want to update it without rebuilding:
```bash
cmake -B build -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
```
### Applying auto-fixes
Some clang-tidy checks can apply fixes automatically (e.g. `modernize-*`, `readability-*`):
```bash
FIX=1 ./test.sh --lint
```
> **Caution:** Review the diff before committing — automatic fixes occasionally produce non-idiomatic results in complex template code.
### Configuration (.clang-tidy)
The active check set is defined in [.clang-tidy](.clang-tidy) at the repository root.
This means any heap overflow, stack buffer overflow, use-after-free, null dereference, signed integer overflow, or misaligned access detected during a test will abort the process and print a human-readable report to stderr.
### Workflow
```bash
# 1. Configure once (only needs to be re-run when CMakeLists.txt changes)
cmake -B build_asan \
-DCMAKE_BUILD_TYPE=Debug \
-DWOWEE_ENABLE_ASAN=ON \
-DWOWEE_BUILD_TESTS=ON
# 2. Build test binaries (fast incremental after the first build)
cmake --build build_asan --target test_packet test_srp # etc.
# 3. Run
./test.sh --asan
```
### Interpreting ASAN output
A failing ASAN report looks like:
```
==12345==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000000010
READ of size 4 at 0x602000000010 thread T0
#0 0x... in PacketBuffer::read_uint32 src/network/packet.cpp:42
#1 0x... in test_packet tests/test_packet.cpp:88
```
Address the issue in the source file and re-run. Do **not** suppress ASAN reports without a code fix.
---
## Adding New Tests
1.**Create**`tests/test_<name>.cpp` with a standard Catch2 v3 structure:
```cpp
#include "catch_amalgamated.hpp"
TEST_CASE("SomeFeature does X", "[tag]") {
REQUIRE(1 + 1 == 2);
}
```
2.**Register** the test in `tests/CMakeLists.txt` following the existing pattern: