#pragma once #include #include #include namespace pp::tests { class Harness { public: void expect(bool condition, std::string_view expression, std::string_view file, int line) { ++assertions_; if (!condition) { ++failures_; std::cerr << file << ":" << line << ": expectation failed: " << expression << "\n"; } } template void run(std::string_view name, Callback callback) { const auto failures_before = failures_; callback(*this); ++tests_; if (failures_ == failures_before) { std::cout << "[pass] " << name << "\n"; } else { std::cout << "[fail] " << name << "\n"; } } [[nodiscard]] int finish() const { std::cout << "{\"tests\":" << tests_ << ",\"assertions\":" << assertions_ << ",\"failures\":" << failures_ << "}\n"; return failures_ == 0 ? EXIT_SUCCESS : EXIT_FAILURE; } private: int tests_ = 0; int assertions_ = 0; int failures_ = 0; }; } #define PP_EXPECT(harness, expression) \ (harness).expect(static_cast(expression), #expression, __FILE__, __LINE__)