#ifndef _test_common_n_
#define _test_common_n_

#pragma once
#include <iostream>
#include <stdexcept>
#include <string>
#include <vector>

struct TestFailure : public std::runtime_error {
    using std::runtime_error::runtime_error;
};


#define CHECK(cond, msg) do { if (!(cond)) throw TestFailure(msg); } while (0)
#define CHECK_EQ(a,b,msg) do { if (!((a)==(b))) { throw TestFailure(std::string(msg) + " (" #a " != " #b ")"); } } while (0)

#define TEST_CASE(name) \
    static void name(); \
    struct name##_registrar { name##_registrar(){ TestRegistry::add(#name, &name);} } name##_registrar_instance; \
    static void name()

struct TestRegistry {
    using Fn = void(*)();
    static std::vector<std::pair<std::string, Fn>>& list() {
        static std::vector<std::pair<std::string, Fn>> v; return v;
    }
    static void add(const std::string& name, Fn fn) { list().push_back({name, fn}); }
};

// Default test runner main()
#ifdef TEST_MAIN
int main() {
    int fails = 0;
    for (auto& t : TestRegistry::list()) {
        try {
            t.second();
            //std::cout << "[PASS] " << t.first << "\n";
        } catch (const TestFailure& e) {
            std::cerr << "[FAIL] " << t.first << " -> " << e.what() << "\n";
            ++fails;
        } catch (const std::exception& e) {
            std::cerr << "[ERROR] " << t.first << " -> " << e.what() << "\n";
            ++fails;
        }
    }
    std::cout << (fails ? "Some tests failed ❌\n" : "All tests passed ✅\n");
    return fails ? 1 : 0;
}
#endif

#endif // _test_common_n_