// // Created by Patrick Maschek on 08/04/2024. // #ifndef CONST_CONTAINER_TEST_DEFINE_TEST_HPP_ #define CONST_CONTAINER_TEST_DEFINE_TEST_HPP_ #include #include #include #include "test_ret_val.h" template struct test_def_base { using FuncType = Func; const char *name; Func func; constexpr test_def_base(const char * name, Func func) : name(name), func(func) {} virtual constexpr std::invoke_result_t operator()() { return std::apply(func, std::make_tuple()); } }; template struct test_definition : public test_def_base { using base = test_def_base; static constexpr std::size_t ARG_SIZE = sizeof...(Args); std::tuple args; constexpr test_definition(const char *name, Func func, Args ...args) : test_def_base(name, func), args(std::make_tuple(args...)) {} constexpr std::invoke_result_t operator()() override { return std::apply(base::func, args); } }; struct test_suite_base { const char *name; }; template requires (sizeof...(TestDefs) == 0 || (std::derived_from> && ...)) struct test_suite : public test_suite_base { static constexpr std::size_t TEST_NR = sizeof...(TestDefs); std::tuple tests; constexpr test_suite(const char *name, std::tuple tests) : test_suite_base(name), tests(tests) {} constexpr ret_val run() { std::vector v; std::apply([&v](auto&& ...args) { ((v.push_back(args())), ...); }, tests); ret_val ret = { name }; std::ranges::move(v, ret.vals.begin()); return ret; } }; template struct quick_test_def { Suite current; template constexpr auto operator()(const char *name, Func func, Args... args) { auto test = test_definition(name, func, args...); auto new_suite = test_suite(current.name, std::tuple_cat(current.tests, std::make_tuple(test))); return quick_test_def { new_suite }; } constexpr operator Suite() { return current; } }; template test_suite(quick_test_def>) -> test_suite; constexpr auto define_tests(const char *name) { return quick_test_def { test_suite<>{ name, std::make_tuple() } }; } #endif //CONST_CONTAINER_TEST_DEFINE_TEST_HPP_