Skip to content

Instantly share code, notes, and snippets.

@sutyum
Created August 12, 2024 19:22
Show Gist options
  • Save sutyum/882d1147de586a7b68be55e13e5eacac to your computer and use it in GitHub Desktop.
Save sutyum/882d1147de586a7b68be55e13e5eacac to your computer and use it in GitHub Desktop.
#ifndef U_TEST_H
#define U_TEST_H
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
// Colored output macros
#define ANSI_COLOR_RED "\x1b[31m"
#define ANSI_COLOR_GREEN "\x1b[32m"
#define ANSI_COLOR_RESET "\x1b[0m"
// Test information structure
typedef struct {
const char* name;
const char* file;
int line;
const char* condition;
bool passed;
} TestInfo;
// Maximum number of tests
#define MAX_TESTS 10000
// Global test information
static TestInfo g_tests[MAX_TESTS];
static size_t g_test_count = 0;
static TestInfo* g_current_test = NULL;
// Assert function
static void test_assert(bool condition, const char* condition_str, const char* file, int line) {
if (g_current_test) {
if (!condition) {
g_current_test->passed = false;
g_current_test->file = file;
g_current_test->line = line;
g_current_test->condition = condition_str;
}
}
}
// Macro for assert
#define assert(condition) test_assert(condition, #condition, __FILE__, __LINE__)
// Test registration function
static void register_test(const char* name, void (*test_func)(void)) {
if (g_test_count < MAX_TESTS) {
g_tests[g_test_count].name = name;
g_tests[g_test_count].passed = true;
g_test_count++;
g_current_test = &g_tests[g_test_count - 1];
test_func();
g_current_test = NULL;
}
}
// Macro for test definition
#define test(name) \
static void test_func_##name(void); \
static void __attribute__((constructor)) register_##name(void) { \
register_test(#name, test_func_##name); \
} \
static void test_func_##name(void)
// Function to print test results
static void print_test_results(void) {
size_t passed = 0, failed = 0;
printf("\nDetailed Test Results:\n");
for (size_t i = 0; i < g_test_count; i++) {
if (g_tests[i].passed) {
passed++;
printf(ANSI_COLOR_GREEN "PASS" ANSI_COLOR_RESET " %s\n", g_tests[i].name);
} else {
failed++;
printf(ANSI_COLOR_RED "FAIL" ANSI_COLOR_RESET " %s\n", g_tests[i].name);
printf(" in %s, line %d: assert(%s)\n",
g_tests[i].file, g_tests[i].line, g_tests[i].condition);
}
}
printf("\nTest Summary:\n");
printf(" Total tests: %zu\n", g_test_count);
printf(" " ANSI_COLOR_GREEN "Passed: %zu" ANSI_COLOR_RESET "\n", passed);
printf(" " ANSI_COLOR_RED "Failed: %zu" ANSI_COLOR_RESET "\n", failed);
}
// Macro for main function
#define U_TEST_MAIN() \
int main(void) { \
print_test_results(); \
return g_test_count > 0 && g_test_count == (size_t)g_tests[g_test_count - 1].passed; \
}
#endif // U_TEST_H
/*
// Usage
// ---
#include "utest.h"
test(simple_addition) {
assert(2 + 2 == 4);
}
test(always_fails) {
assert(1 == 2);
}
U_TEST_MAIN()
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment