#pragma once #include #include #include #include struct TestCase { std::string name; void (*fn)(); }; inline std::vector& tests() { static std::vector t; return t; } inline int register_test(const char* name, void (*fn)()) { tests().push_back({name, fn}); return 0; } #define TEST(name) \ void test_##name(); \ static int reg_##name = register_test(#name, test_##name); \ void test_##name() #define ASSERT_TRUE(expr) \ do { \ if (!(expr)) { \ std::cerr << " FAIL: " << #expr << " (" << __FILE__ << ":" \ << __LINE__ << ")" << std::endl; \ std::exit(1); \ } \ } while (0) #define ASSERT_FALSE(expr) ASSERT_TRUE(!(expr)) #define ASSERT_EQ(a, b) \ do { \ if ((a) != (b)) { \ std::cerr << " FAIL: " << #a << " == " << #b << " (" << __FILE__ \ << ":" << __LINE__ << ")" << std::endl; \ std::exit(1); \ } \ } while (0) #define RUN_ALL_TESTS() \ int main() { \ int passed = 0; \ int failed = 0; \ for (auto& tc : tests()) { \ std::cout << tc.name << "... "; \ try { \ tc.fn(); \ std::cout << "ok" << std::endl; \ passed++; \ } catch (...) { \ std::cout << "FAILED" << std::endl; \ failed++; \ } \ } \ std::cout << passed << " passed, " << failed << " failed" << std::endl;\ return failed > 0 ? 1 : 0; \ }