72 lines
2.7 KiB
C++
72 lines
2.7 KiB
C++
#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)
|