112 lines
3.6 KiB
Markdown
112 lines
3.6 KiB
Markdown
# Tests and Assertions
|
|
|
|
## Test infrastructure
|
|
|
|
Tests live in `test/` and mirror the `src/dusk/` directory structure.
|
|
Enable with `-DDUSK_BUILD_TESTS=ON`. The test runner is **cmocka**.
|
|
|
|
### Entry point
|
|
|
|
Every test file includes `dusktest.h`, which pulls in `dusk.h` and
|
|
`assert/assert.h`. When `DUSK_TEST_ASSERT` is defined, `assert.h`
|
|
includes `cmocka.h` and redirects assertion failures through
|
|
`mock_assert()` instead of calling `abort()`.
|
|
|
|
### Test function signature
|
|
|
|
```c
|
|
static void test_something(void **state) {
|
|
// ... setup ...
|
|
// ... exercise ...
|
|
// ... assert ...
|
|
assert_int_equal(memoryGetAllocatedCount(), 0); // leak check
|
|
}
|
|
```
|
|
|
|
### Registering and running tests
|
|
|
|
```c
|
|
int main(void) {
|
|
const struct CMUnitTest tests[] = {
|
|
cmocka_unit_test(test_errorThrow),
|
|
cmocka_unit_test(test_errorOk),
|
|
};
|
|
return cmocka_run_group_tests(tests, NULL, NULL);
|
|
}
|
|
```
|
|
|
|
Use `cmocka_unit_test_setup_teardown()` when a test needs per-test
|
|
setup or teardown callbacks.
|
|
|
|
### Assertion mix
|
|
|
|
Tests use **two** sets of assertion macros:
|
|
|
|
| Origin | When to use |
|
|
|--------|-------------|
|
|
| cmocka: `assert_int_equal()`, `assert_non_null()` etc. | Validate results inside test functions |
|
|
| Dusk: `assertTrue()`, `assertNotNull()` etc. | Exercise the code under test (these may fire and need catching) |
|
|
|
|
To assert that a Dusk assertion fires, use cmocka's mock system:
|
|
|
|
```c
|
|
expect_assert_failure(assertTrueImpl(__FILE__, __LINE__, false, "msg"));
|
|
```
|
|
|
|
### Memory leak discipline
|
|
|
|
Every test function must end by asserting:
|
|
|
|
```c
|
|
assert_int_equal(memoryGetAllocatedCount(), 0);
|
|
```
|
|
|
|
This ensures all allocations from the code under test were freed.
|
|
|
|
---
|
|
|
|
## Assertion system
|
|
|
|
Source: `src/dusk/assert/`
|
|
|
|
### Runtime vs test mode
|
|
|
|
| Mode | Trigger | Effect on failure |
|
|
|------|---------|-------------------|
|
|
| Runtime (default) | Release / non-test builds | Logs the message + backtrace, then calls `abort()` |
|
|
| Test (`DUSK_TEST_ASSERT`) | `-DDUSK_TEST_ASSERT` build flag | Routes through cmocka `mock_assert()` for controlled catching |
|
|
| Faked (`DUSK_ASSERTIONS_FAKED`) | Defined by platform or test | All macros become no-ops (`((void)0)`) |
|
|
|
|
### Available macros
|
|
|
|
| Macro | Description |
|
|
|-------|-------------|
|
|
| `assertTrue(x, msg)` | Fails if `x` is false |
|
|
| `assertFalse(x, msg)` | Fails if `x` is true |
|
|
| `assertNotNull(ptr, msg)` | Fails if `ptr` is NULL |
|
|
| `assertNull(ptr, msg)` | Fails if `ptr` is not NULL |
|
|
| `assertUnreachable(msg)` | Unconditional failure; marks unreachable code |
|
|
| `assertDeprecated(msg)` | Marks a code path as deprecated |
|
|
| `assertStringEqual(a, b, msg)` | Fails if strings differ |
|
|
| `assertStrLenMax(str, len, msg)` | Fails if `strlen(str) >= len` |
|
|
| `assertStrLenMin(str, len, msg)` | Fails if `strlen(str) < len` |
|
|
| `assertIsMainThread(msg)` | Fails if called from a non-main thread |
|
|
| `assertNotMainThread(msg)` | Fails if called from the main thread |
|
|
| `assertStructSize(type, size)` | Compile-time size check via `_Static_assert` |
|
|
|
|
### Thread tracking
|
|
|
|
`assertInit()` records the main thread ID (pthreads). The main-thread
|
|
assertions compare against this stored ID. Call `assertInit()` once at
|
|
startup before spawning any threads.
|
|
|
|
### Usage guidelines
|
|
|
|
- Prefer the specific macro over a bare `assertTrue` for clarity
|
|
(e.g. use `assertNotNull` instead of `assertTrue(ptr != NULL, ...)`).
|
|
- Use `assertUnreachable` in `default:` cases of exhaustive switches.
|
|
- Use `assertStructSize` to guard struct layouts that must match
|
|
a known binary format or a platform ABI.
|
|
- Do not use asserts for expected error paths -- use `errorThrow`
|
|
instead. Asserts are for programmer mistakes, not runtime errors.
|