#pragma once #include #include #include #include #include #include #include #include #include using plot::f32; using plot::f64; using plot::u32; using plot::u64; namespace plottest { struct Case { const char* name; std::function fn; }; inline std::vector& cases() { static std::vector c; return c; } struct Reg { Reg(const char* n, std::function f) { cases().push_back({n, std::move(f)}); } }; struct Failure { std::string msg; }; inline int run_all() { int failed = 0; for (auto& c : cases()) { try { c.fn(); std::printf("[ ok ] %s\n", c.name); } catch (const Failure& f) { std::printf("[FAIL] %s: %s\n", c.name, f.msg.c_str()); ++failed; } } std::printf("%zu cases, %d failed\n", cases().size(), failed); return failed == 0 ? 0 : 1; } } // namespace plottest #define PLOT_TEST(name) \ static void name(); \ static ::plottest::Reg reg_##name(#name, name); \ static void name() #define PLOT_CHECK(cond) \ do { \ if (!(cond)) \ throw ::plottest::Failure{std::string(__FILE__) + ":" + std::to_string(__LINE__) + \ " CHECK(" #cond ")"}; \ } while (0) #define PLOT_CHECK_NEAR(a, b, eps) \ do { \ const double _a = (a), _b = (b); \ if (!(std::fabs(_a - _b) <= (eps))) \ throw ::plottest::Failure{std::string(__FILE__) + ":" + std::to_string(__LINE__) + \ " CHECK_NEAR(" #a ", " #b ") got " + std::to_string(_a) + \ " vs " + std::to_string(_b)}; \ } while (0)