#pragma once #include #include #include #include "common.hpp" #include "result.hpp" const uint64_t MAX_TESTS = 1024 * 1024; static void (*tests[MAX_TESTS])() = {0}; const char* add_test(void (*fun)(void)) { for (uint64_t i = 0; i < MAX_TESTS; ++i) { if (tests[i] == 0) { tests[i] = fun; break; } } return 0; } bool run_tests() { for (uint64_t i = 0; i < MAX_TESTS; ++i) { if (tests[i] == 0) break; tests[i](); } return true; } #define CONCAT_IMPL(x, y) x##y #define MACRO_CONCAT(x, y) CONCAT_IMPL(x, y) #define TEST_CASE_IMPL(ID, ...) \ static void ID(); \ static const char* MACRO_CONCAT(test_id_, __COUNTER__) [[maybe_unused]] = \ add_test(&ID); \ void ID() #define TEST_CASE(fun_) TEST_CASE_IMPL(MACRO_CONCAT(fun_, _COUNTER_)) template struct Capture { Capture(T& value) : value(value) {} T& value; }; template struct Capture { Capture(T& value) : value(value) {} T& value; }; template struct Capture { Capture(T&& value) : value(value) {} T value; }; Value& to_value(Arena& arena, Value& val) { return val; } template requires std::derived_from Value to_value(Arena& arena, T& val) { return DIEX(val.copy(arena)); } template requires(!std::derived_from) Value to_value(Arena& arena, T& val) { return DIEX(Value::create(arena, val)); } #define ASSERT_EQUALS(lhs, rhs) \ do { \ auto l = Capture(lhs); \ auto r = Capture(rhs); \ auto lv = to_value(arena, l.value); \ auto rv = to_value(arena, r.value); \ short c = DIEX(lv.cmp(arena, rv)); \ if (c != 0) { \ fprintf(stderr, "Values not equal at %s:%d\n", __FILE__, __LINE__); \ debug_print(arena, lv); \ debug_print(arena, rv); \ exit(EXIT_FAILURE); \ } \ } while (0) int main() { return run_tests() ? 0 : 1; }