Comprehensive guide for testing hyprlax functionality.
# Run all tests
make test
# Run tests with output
make test VERBOSE=1# Run single test suite
./tests/test_animation
./tests/test_config
./tests/test_compositor
# Run with debugging
gdb ./tests/test_animation# Run tests with valgrind
make memcheck
# Run specific test with valgrind
valgrind --leak-check=full ./tests/test_configCoverage targets are not currently provided by the build; use external tools if needed.
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.
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.
Tests create their own data where needed. No image generation scripts are required.
// 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);
}# 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_configHYPRLAX_SOCKET_SUFFIXto isolate IPC sockets during testsHYPRLAX_INIT_TRACE=1to trace init and argument/config parsing
// 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
}# .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- All tests pass:
make test - No memory leaks:
make memcheck - New features have tests
- Edge cases tested
- Happy path tests
- Error condition tests
- Boundary tests
- Configuration tests
- Platform compatibility tests
- Performance regression tests
# Debug test failure
gdb ./tests/test_animation
(gdb) run
(gdb) bt # Backtrace on failure
(gdb) print variable_name// Temporary debug output in tests
#ifdef DEBUG_TEST
printf("DEBUG: value=%d expected=%d\n", value, expected);
#endif- Check for infinite loops
- Verify timeouts are set
- Check for deadlocks
- Remove timing dependencies
- Use mocks for external dependencies
- Ensure proper cleanup
- Use conditional compilation
- Mock platform-specific calls
- Document platform requirements
- 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
// 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
}