From cac4a8dd2ac6670c5db8d2370cdd12451f9f50cf Mon Sep 17 00:00:00 2001 From: Claudius Holeksa Date: Tue, 9 May 2023 17:24:41 +0200 Subject: Added readme and moved src files --- src/keltest/test.cpp | 139 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 src/keltest/test.cpp (limited to 'src/keltest/test.cpp') diff --git a/src/keltest/test.cpp b/src/keltest/test.cpp new file mode 100644 index 0000000..1178b20 --- /dev/null +++ b/src/keltest/test.cpp @@ -0,0 +1,139 @@ +#include "test.h" + +#include +#include +#include + +namespace keltest { + +template +constexpr bool always_false = false; + +test_case* test_case_head = nullptr; +test_case** test_case_tail = &test_case_head; + +test_case::test_case(std::string file_, uint32_t line_, std::string& description_): + file{std::move(file_)}, + line{line_}, + description{std::move(description_)}, + next{nullptr}, + prev{test_case_tail} +{ + /** + * Since I always forget how this works. + */ + /** + * If the list is empty, then this command sets the head to this + * If the list is not empty it sets the previous test_case "next" to this location + */ + *prev = this; + /** + * The tail is set this->next location which is used in a later test_case's constructor + */ + test_case_tail = &next; +} + +test_case::~test_case(){ + *prev = next; + if( next == nullptr ){ + test_case_tail = prev; + }else { + next->prev = prev; + } +} + +namespace colour { +struct red {}; +struct green {}; +struct blue {}; +struct white {}; + +using variant = std::variant; +} + + +class test_runner { +private: + void write(const colour::variant& col, const std::string& front, const std::string& message){ + std::string_view start_col, end_col; + start_col = std::visit([](auto& col) -> std::string_view { + using T = std::decay_t; + + if constexpr ( std::is_same_v ){ + return "\033[0;1;31m"; + } + else if constexpr ( std::is_same_v ){ + return "\033[0;1;32m"; + } + else if constexpr ( std::is_same_v ){ + return "\033[0;1;34m"; + } + else if constexpr ( std::is_same_v ){ + return "\033[0m"; + } + else { + static_assert(always_false, "Case exhausted"); + } + return "\033[0m"; + }, col); + end_col = "\033[0m"; + + std::cout<next){ + std::string name = test->fil + std::string{":"} + std::to_string(test->line) + std::string{":"} + test->description; + write(colour::blue, "[ TEST ] ", name); + bool failed = true; + + std::string fail_message; + auto start_clock = std::chrono::steady_clock::now(); + + try { + test->run(); + failed = false; + }catch(std::exception& e){ + fail_message = e.what(); + failed = true; + } + auto stop_clock = std::chrono::steady_clock::now(); + + auto runtime_duration_intern = stop_clock - start_clock; + + auto runtime_duration = std::chrono::duration_cast(runtime_duration_intern); + + std::string message = name + std::string{" ("} + std::to_string(runtime_duration.count()) + std::string{" µs) "}; + + if( failed ){ + write(colour::red, "[ FAIL ] ", message + std::string{" "} + fail_message); + ++failed_count; + }else{ + write(colour::green, "[ PASS ] ", message); + ++passed_count; + } + } + + if( passed_count > 0 ) write(colour::green, std::to_string(passed_count) + std::string{" test(s) passed"}, ""); + + if( failed_count > 0 ) write(colour::red, std::to_string(failed_count) + std::string{" test(s) failed"}, ""); + + return failed_count > 0 ? -1 : 0; + } +}; +} + +#if KELTEST_COMPILE_TEST_BINARY + +int main() { + ::keltest::test_runner runner; + int rv = runner.run(); + + return rv != 0 ? -1 : 0; +} + +#endif -- cgit v1.2.3