// // 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 #include #include "test_ret_val.h" template struct quick_test_def; enum class EvalFlag { RUNTIME, CONSTEVAL, RUNTIME_CONSTEVAL }; struct test_def_base {}; template struct test_def_func_base : public test_def_base { using FuncType = Func; const char *name; Func func; EvalFlag evalFlag = EvalFlag::RUNTIME; constexpr test_def_func_base(const char * name, Func func) : name(name), func(func) {} constexpr test_def_func_base(const char * name, Func func, EvalFlag evalFlag) : name(name), func(func), evalFlag(evalFlag) {} virtual constexpr std::invoke_result_t operator()() { return std::apply(func, std::make_tuple()); } consteval auto run_consteval() { return operator()(); } }; template struct test_definition : public test_def_func_base { using base = test_def_func_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_func_base(name, func), args(std::make_tuple(args...)) {} constexpr test_definition(const char *name, Func func, EvalFlag evalFlag, Args ...args) : test_def_func_base(name, func, evalFlag), 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> && ...)) class test_suite : public test_suite_base { public: static constexpr std::size_t TEST_NR = sizeof...(TestDefs); constexpr test_suite(const char *name, std::tuple tests) : test_suite_base(name), tests(tests) {} ret_val run() const { constexpr auto is = std::make_index_sequence(); std::cout << "--------------\n"; constexpr auto test_arr = expand_tuple(tests, is); constexpr auto const_test_arr = test_arr | std::views::enumerate | std::views::filter([](auto e) consteval { return noexcept(e.run_consteval()); }); for (auto [i, test_ref] : std::ranges::views::enumerate(test_arr)) { auto test = test_ref.get(); std::cout << "Running Test: \"" << test.name << "\"\n"; if (test.evalFlag == EvalFlag::RUNTIME || test.evalFlag == EvalFlag::RUNTIME_CONSTEVAL) { ret_val_s ret = test(); std::cout << "Result of Runtime Evaluation of Test \"" << ret.test_name << "\" (number: " << i << "): " << (ret.val == ReturnCode::PASSED ? "PASSED" : "FAILED") << "\n" << "\t" << ret.msg << "\n"; } std::optional cret; if (test.evalFlag == EvalFlag::CONSTEVAL || test.evalFlag == EvalFlag::RUNTIME_CONSTEVAL) { //cret = run_consteval_test<>(); } if (cret.has_value()) { auto ret = cret.value(); std::cout << "Result of Consteval Evaluation of Test \"" << ret.test_name << "\" (number: " << i << "): " << (ret.val == ReturnCode::PASSED ? "PASSED" : "FAILED") << "\n" << "\t" << ret.msg << "\n"; } } ret_val ret = { name }; //std::ranges::move(v, ret.vals.begin()); return ret; } private: static constexpr std::tuple...> tests; template static constexpr auto expand_tuple(const auto &tests, std::index_sequence) { return std::array { (std::reference_wrapper(std::get(tests)), ...) }; } template requires (std::derived_from>) static consteval ret_val_s run_consteval_test() { return Test(); } friend class quick_test_def>; }; template struct quick_test_def { Suite current; template constexpr auto operator()(const char *name, Func func, Args... args) { return operator()(name, func, EvalFlag::RUNTIME, std::forward(args)...); } template constexpr auto operator()(const char *name, Func func, EvalFlag evalFlag, Args... args) { auto test = test_definition(name, func, evalFlag, 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_