/** * test_framework.h - Simple unit testing framework for GlaMaC * * Copyright (C) 2025 https://optics-design.com * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. */ #ifndef TEST_FRAMEWORK_H #define TEST_FRAMEWORK_H #include #include #include #include // Test statistics static int tests_run = 0; static int tests_passed = 0; static int tests_failed = 0; // ANSI color codes for output #define RESET "\033[0m" #define RED "\033[31m" #define GREEN "\033[32m" #define YELLOW "\033[33m" #define BLUE "\033[34m" #define MAGENTA "\033[35m" #define CYAN "\033[36m" // Test macros #define TEST_START(name) \ printf(CYAN "Running test: %s" RESET "\n", name); \ tests_run++; #define TEST_ASSERT(condition, message) \ if (condition) { \ printf(GREEN " ✓ PASS: %s" RESET "\n", message); \ } else { \ printf(RED " ✗ FAIL: %s" RESET "\n", message); \ tests_failed++; \ return 0; \ } #define TEST_ASSERT_EQ(expected, actual, message) \ if ((expected) == (actual)) { \ printf(GREEN " ✓ PASS: %s (expected: %d, actual: %d)" RESET "\n", message, expected, actual); \ } else { \ printf(RED " ✗ FAIL: %s (expected: %d, actual: %d)" RESET "\n", message, expected, actual); \ tests_failed++; \ return 0; \ } #define TEST_ASSERT_STR_EQ(expected, actual, message) \ if (strcmp(expected, actual) == 0) { \ printf(GREEN " ✓ PASS: %s" RESET "\n", message); \ } else { \ printf(RED " ✗ FAIL: %s (expected: '%s', actual: '%s')" RESET "\n", message, expected, actual); \ tests_failed++; \ return 0; \ } #define TEST_ASSERT_FLOAT_EQ(expected, actual, tolerance, message) \ if (fabs((expected) - (actual)) < (tolerance)) { \ printf(GREEN " ✓ PASS: %s" RESET "\n", message); \ } else { \ printf(RED " ✗ FAIL: %s (expected: %.6f, actual: %.6f, diff: %.6f)" RESET "\n", \ message, expected, actual, fabs((expected) - (actual))); \ tests_failed++; \ return 0; \ } #define TEST_ASSERT_NULL(ptr, message) \ if ((ptr) == NULL) { \ printf(GREEN " ✓ PASS: %s" RESET "\n", message); \ } else { \ printf(RED " ✗ FAIL: %s (expected NULL, got non-NULL)" RESET "\n", message); \ tests_failed++; \ return 0; \ } #define TEST_ASSERT_NOT_NULL(ptr, message) \ if ((ptr) != NULL) { \ printf(GREEN " ✓ PASS: %s" RESET "\n", message); \ } else { \ printf(RED " ✗ FAIL: %s (expected non-NULL, got NULL)" RESET "\n", message); \ tests_failed++; \ return 0; \ } #define TEST_END() \ tests_passed++; \ printf(GREEN "Test completed successfully" RESET "\n\n"); \ return 1; // Test runner helpers #define RUN_TEST(test_func) \ if (test_func()) { \ /* Test passed */ \ } else { \ /* Test failed - already handled in macros */ \ } #define TEST_SUMMARY() \ printf(MAGENTA "=== Test Summary ===" RESET "\n"); \ printf("Total tests run: %d\n", tests_run); \ printf(GREEN "Passed: %d" RESET "\n", tests_passed); \ if (tests_failed > 0) { \ printf(RED "Failed: %d" RESET "\n", tests_failed); \ } else { \ printf("Failed: 0\n"); \ } \ printf("Success rate: %.1f%%\n", tests_run > 0 ? (100.0 * tests_passed / tests_run) : 0.0); \ printf(MAGENTA "===================" RESET "\n"); \ return tests_failed == 0 ? 0 : 1; #endif /* TEST_FRAMEWORK_H */