mirror of
https://github.com/JBuildr/nubix.git
synced 2026-10-17 16:01:41 +02:00
80 lines
3.5 KiB
C++
80 lines
3.5 KiB
C++
// Nubix — tiny self-contained unit test framework (host only).
|
|
//
|
|
// XC_TEST(suite, name) { XC_CHECK(cond); XC_CHECK_EQ(a, b); XC_REQUIRE(cond); }
|
|
//
|
|
// Run: xc-tests [suite ...] (no args = all suites). Exit code = number of failed tests.
|
|
// Copyright (C) 2026 Nubix contributors
|
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
#pragma once
|
|
|
|
#include <cstdio>
|
|
#include <functional>
|
|
#include <sstream>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
namespace xctest {
|
|
|
|
struct Failure {}; // thrown by XC_REQUIRE to abort the current test
|
|
|
|
struct TestCase {
|
|
const char* suite;
|
|
const char* name;
|
|
std::function<void()> fn;
|
|
};
|
|
|
|
std::vector<TestCase>& registry();
|
|
// Record a failed check for the currently running test.
|
|
void fail(const char* file, int line, const std::string& msg);
|
|
|
|
struct Registrar {
|
|
Registrar(const char* suite, const char* name, std::function<void()> fn) {
|
|
registry().push_back({suite, name, std::move(fn)});
|
|
}
|
|
};
|
|
|
|
template <typename T>
|
|
std::string show(const T& v) {
|
|
std::ostringstream os;
|
|
os << v;
|
|
return os.str();
|
|
}
|
|
inline std::string show(const std::string& v) { return "\"" + v + "\""; }
|
|
inline std::string show(const char* v) { return v ? "\"" + std::string(v) + "\"" : "(null)"; }
|
|
inline std::string show(unsigned char v) { return std::to_string(static_cast<unsigned>(v)); }
|
|
inline std::string show(signed char v) { return std::to_string(static_cast<int>(v)); }
|
|
inline std::string show(bool v) { return v ? "true" : "false"; }
|
|
|
|
} // namespace xctest
|
|
|
|
#define XC_CAT2(a, b) a##b
|
|
#define XC_CAT(a, b) XC_CAT2(a, b)
|
|
|
|
#define XC_TEST(suite, name) \
|
|
static void XC_CAT(xc_test_##suite##_, name)(); \
|
|
static ::xctest::Registrar XC_CAT(xc_reg_##suite##_, name)(#suite, #name, \
|
|
&XC_CAT(xc_test_##suite##_, name)); \
|
|
static void XC_CAT(xc_test_##suite##_, name)()
|
|
|
|
#define XC_CHECK(cond) \
|
|
do { \
|
|
if (!(cond)) ::xctest::fail(__FILE__, __LINE__, "CHECK(" #cond ")"); \
|
|
} while (0)
|
|
|
|
#define XC_REQUIRE(cond) \
|
|
do { \
|
|
if (!(cond)) { \
|
|
::xctest::fail(__FILE__, __LINE__, "REQUIRE(" #cond ")"); \
|
|
throw ::xctest::Failure{}; \
|
|
} \
|
|
} while (0)
|
|
|
|
#define XC_CHECK_EQ(a, b) \
|
|
do { \
|
|
const auto& xc_a_ = (a); \
|
|
const auto& xc_b_ = (b); \
|
|
if (!(xc_a_ == xc_b_)) \
|
|
::xctest::fail(__FILE__, __LINE__, \
|
|
"CHECK_EQ(" #a ", " #b "): " + ::xctest::show(xc_a_) + " != " + ::xctest::show(xc_b_)); \
|
|
} while (0)
|