Testing Guide¶
Comprehensive guide for testing hyprlax functionality.
Running Tests¶
Quick Test¶
# Run all tests
make test
# Run tests with output
make test VERBOSE=1
Specific Tests¶
# Run single test suite
./tests/test_animation
./tests/test_config
./tests/test_compositor
# Run with debugging
gdb ./tests/test_animation
Memory Testing¶
# Run tests with valgrind
make memcheck
# Run specific test with valgrind
valgrind --leak-check=full ./tests/test_config
Coverage Report¶
Coverage targets are not currently provided by the build; use external tools if needed.
Test Structure¶
Tests are simple C programs. Many use the Check framework (linked via pkg-config in the Makefile). The suite covers core modules, renderer, compositor/platform adapters, IPC, and configuration loaders.
Available Test Suites (examples)¶
tests/test_easing– easing values and parsingtests/test_animation– animation state and timingtests/test_config/tests/test_toml_config– config parsingtests/test_ipc– IPC server/client operationstests/test_renderer– renderer scaffolding and shader checkstests/test_platform– platform abstractiontests/test_compositor– compositor detection/capabilitiestests/test_workspace_changes– workspace events
Note: make test builds and runs all present tests/test_*.c binaries.
Test Data¶
Tests create their own data where needed. No image generation scripts are required.
Performance Tests¶
Benchmark Framework¶
// tests/bench_rendering.c
#include <time.h>
static void bench_frame_render(void) {
struct renderer *r = create_test_renderer();
struct layer layers[5];
create_test_layers(layers, 5);
clock_t start = clock();
for (int i = 0; i < 1000; i++) {
renderer_draw_frame(r, layers, 5);
}
clock_t end = clock();
double time_spent = ((double)(end - start)) / CLOCKS_PER_SEC;
printf("1000 frames in %.2f seconds (%.1f FPS)\n",
time_spent, 1000.0 / time_spent);
}
Memory Benchmarks¶
# Profile memory usage
valgrind --tool=massif ./hyprlax test.jpg
ms_print massif.out.*
# Check for leaks
valgrind --leak-check=full --show-leak-kinds=all ./tests/test_config
Environment helpers¶
HYPRLAX_SOCKET_SUFFIXto isolate IPC sockets during testsHYPRLAX_INIT_TRACE=1to trace init and argument/config parsing
Test Utilities¶
Helper Functions¶
// tests/test_utils.c
void create_test_image(const char *path, int width, int height) {
// Create dummy image file for testing
}
struct config *create_test_config(void) {
struct config *cfg = calloc(1, sizeof(*cfg));
cfg->fps = 60;
cfg->duration = 1.0;
cfg->easing = EASING_EXPO;
return cfg;
}
void simulate_workspace_change(int from, int to) {
// Simulate compositor workspace event
}
Continuous Integration¶
GitHub Actions¶
# .github/workflows/test.yml
name: Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y libwayland-dev wayland-protocols
- name: Build
run: make debug
- name: Run tests
run: make test
- name: Memory check
run: make memcheck
# Coverage not provided by Makefile; integrate external tooling if desired
Test Checklist¶
Before Commit¶
- [ ] All tests pass:
make test - [ ] No memory leaks:
make memcheck - [ ] New features have tests
- [ ] Edge cases tested
Test Types to Write¶
- [ ] Happy path tests
- [ ] Error condition tests
- [ ] Boundary tests
- [ ] Configuration tests
- [ ] Platform compatibility tests
- [ ] Performance regression tests
Debugging Failed Tests¶
Using GDB¶
# Debug test failure
gdb ./tests/test_animation
(gdb) run
(gdb) bt # Backtrace on failure
(gdb) print variable_name
Add Debug Output¶
// Temporary debug output in tests
#ifdef DEBUG_TEST
printf("DEBUG: value=%d expected=%d\n", value, expected);
#endif
Common Test Issues¶
Test Hangs¶
- Check for infinite loops
- Verify timeouts are set
- Check for deadlocks
Flaky Tests¶
- Remove timing dependencies
- Use mocks for external dependencies
- Ensure proper cleanup
Platform-Specific Failures¶
- Use conditional compilation
- Mock platform-specific calls
- Document platform requirements
Writing Good Tests¶
Principles¶
- Fast: Tests should run quickly
- Independent: Tests shouldn't depend on each other
- Repeatable: Same result every time
- Self-Validating: Clear pass/fail
- Timely: Write tests with code
Best Practices¶
// Good test
static int test_specific_behavior(void) {
// Single behavior per test
// Clear arrange, act, assert
// Descriptive name
// Minimal setup
}
// Bad test
static int test_everything(void) {
// Tests too many things
// Hard to understand failure
// Complex setup
// Order-dependent
}