eis/eqpalg/test/test_harness.h

85 lines
3.5 KiB
C
Raw Permalink Normal View History

// eqpalg/test/test_harness.h
#pragma once
#include <cmath>
#include <functional>
#include <iostream>
#include <sstream>
#include <stdexcept>
#include <string>
#include <vector>
struct TestRunner {
struct Case {
const char* name;
std::function<void()> fn;
};
inline static std::vector<Case> cases;
static int run() {
int passed = 0, failed = 0;
for (auto& c : cases) {
std::cout << " " << c.name << " ... ";
try {
c.fn();
std::cout << "PASSED\n";
passed++;
} catch (const std::exception& e) {
std::cout << "FAILED\n " << e.what() << "\n";
failed++;
} catch (...) {
std::cout << "FAILED (unknown)\n";
failed++;
}
}
std::cout << "\n" << passed << " passed, " << failed << " failed\n";
return failed ? 1 : 0;
}
};
struct AutoReg {
AutoReg(const char* name, std::function<void()> fn) {
TestRunner::cases.push_back({name, std::move(fn)});
}
};
#define TEST(name) \
static void testfn_##name(); \
static AutoReg autoreg_##name(#name, testfn_##name); \
static void testfn_##name()
#define CHECK(expr) \
do { \
if (!(expr)) \
throw std::runtime_error("CHECK(" #expr ") failed"); \
} while (0)
#define CHECK_EQ(a, b) \
do { \
if ((a) != (b)) { \
std::ostringstream os; \
os << "CHECK_EQ: " << (a) << " != " << (b); \
throw std::runtime_error(os.str()); \
} \
} while (0)
#define CHECK_FLOAT_EQ(a, b, eps) \
do { \
if (std::fabs((a) - (b)) > (eps)) { \
std::ostringstream os; \
os << "CHECK_FLOAT_EQ: |" << (a) << " - " << (b) << "| > " << (eps); \
throw std::runtime_error(os.str()); \
} \
} while (0)
#define CHECK_THROWS(expr) \
do { \
bool caught = false; \
try { \
(void)(expr); \
} catch (...) { \
caught = true; \
} \
if (!caught) \
throw std::runtime_error("CHECK_THROWS(" #expr ") did not throw"); \
} while (0)