#ifndef TEST_UTILS_H #define TEST_UTILS_H #include #include #include #include // Detect if running under valgrind by checking /proc/self/maps for vgpreload. // This is used to skip fork-based tests that are incompatible with valgrind // (the instrumented parent runs too slowly, causing pipe timeouts). static inline bool is_running_under_valgrind(void) { FILE* f = fopen("/proc/self/maps", "r"); if (!f) return false; char buf[4096]; size_t n = fread(buf, 1, sizeof(buf) - 1, f); fclose(f); buf[n] = '\0'; return strstr(buf, "vgpreload") != NULL; } // Global test suite status extern int tests_run; extern int tests_failed; extern bool current_test_failed; // Helper to run a test function #define RUN_TEST(test_func) \ do { \ printf("Running %s...\n", #test_func); \ tests_run++; \ current_test_failed = false; \ test_func(); \ if (current_test_failed) { \ tests_failed++; \ printf(" \033[1;31m[FAILED]\033[0m %s\n", #test_func); \ } else { \ printf(" \033[1;32m[PASSED]\033[0m %s\n", #test_func); \ } \ } while (0) // Assertion macros #define EXPECT_TRUE(condition) \ do { \ if (!(condition)) { \ printf(" \033[1;31m[FAIL]\033[0m %s:%d: Assertion failed: %s is false\n", __FILE__, \ __LINE__, #condition); \ current_test_failed = true; \ return; \ } \ } while (0) #define EXPECT_FALSE(condition) \ do { \ if (condition) { \ printf(" \033[1;31m[FAIL]\033[0m %s:%d: Assertion failed: %s is true\n", __FILE__, \ __LINE__, #condition); \ current_test_failed = true; \ return; \ } \ } while (0) #define EXPECT_EQ_INT(actual, expected) \ do { \ int act = (actual); \ int exp = (expected); \ if (act != exp) { \ printf(" \033[1;31m[FAIL]\033[0m %s:%d: Expected %d, got %d\n", __FILE__, __LINE__, exp, \ act); \ current_test_failed = true; \ return; \ } \ } while (0) #define EXPECT_EQ_STR(actual, expected) \ do { \ const char* act = (actual); \ const char* exp = (expected); \ if (act == NULL || exp == NULL) { \ if (act != exp) { \ printf(" \033[1;31m[FAIL]\033[0m %s:%d: Expected %s, got %s\n", __FILE__, __LINE__, \ exp ? exp : "NULL", act ? act : "NULL"); \ current_test_failed = true; \ return; \ } \ } else if (strcmp(act, exp) != 0) { \ printf(" \033[1;31m[FAIL]\033[0m %s:%d: Expected \"%s\", got \"%s\"\n", __FILE__, \ __LINE__, exp, act); \ current_test_failed = true; \ return; \ } \ } while (0) #define EXPECT_NOT_NULL(ptr) \ do { \ if ((ptr) == NULL) { \ printf(" \033[1;31m[FAIL]\033[0m %s:%d: Expected non-null pointer, got NULL\n", __FILE__, \ __LINE__); \ current_test_failed = true; \ return; \ } \ } while (0) #define EXPECT_NULL(ptr) \ do { \ if ((ptr) != NULL) { \ printf(" \033[1;31m[FAIL]\033[0m %s:%d: Expected NULL, got %p\n", __FILE__, __LINE__, \ (void*)(ptr)); \ current_test_failed = true; \ return; \ } \ } while (0) #endif