#ifndef CORE_TEST_H #define CORE_TEST_H #include "data/HashMap.h" #include "math/Vector.h" #include "utils/Logger.h" namespace Core::Test { namespace Internal { struct Result final { int tests = 0; int successTests = 0; }; using FileName = ArrayString<256>; extern HashMap<FileName, Result> results; template<typename T> bool checkEqual(const char* file, int line, const T& wanted, const T& actual) { FileName fileName; if(fileName.append(file)) { CORE_LOG_WARNING("cannot append file name: #", file); return false; } Result* result = results.search(fileName); if(result == nullptr) { result = results.tryEmplace(fileName); if(result == nullptr) { CORE_LOG_WARNING("cannot add test result for #", file); return false; } } result->tests++; if(wanted == actual) { result->successTests++; return true; } CORE_LOG_ERROR("#:# - expected '#' got '#'", fileName, line, wanted, actual) return false; } template<typename A, typename B> bool checkString(const char* file, int line, const A& wanted, const B& actual) { ArrayString<2048> a; if(a.append(wanted)) { CORE_LOG_WARNING("too small buffer"); return false; } ArrayString<2048> b; if(b.append(actual)) { CORE_LOG_WARNING("too small buffer"); return false; } return checkEqual(file, line, a, b); } bool checkFloat(const char* file, int line, float wanted, float actual, float error); template<int N, typename T> bool checkVector(const char* file, int line, const Core::Vector<N, T>& wanted, const Core::Vector<N, T>& actual, float error) { bool result = true; for(int i = 0; i < N; i++) { result = checkFloat(file, line, static_cast<float>(wanted[i]), static_cast<float>(actual[i]), error) && result; } return result; } } void finalize(); } #define CORE_TEST_EQUAL(wanted, actual) \ Core::Test::Internal::checkEqual<Core::RemoveReference<decltype(actual)>>( \ __FILE__, __LINE__, wanted, actual) #define CORE_TEST_STRING(wanted, actual) \ Core::Test::Internal::checkString(__FILE__, __LINE__, wanted, actual); #define CORE_TEST_FALSE(actual) CORE_TEST_EQUAL(false, actual); #define CORE_TEST_TRUE(actual) CORE_TEST_EQUAL(true, actual); #define CORE_TEST_NULL(actual) CORE_TEST_EQUAL(true, actual == nullptr); #define CORE_TEST_NOT_NULL(actual) CORE_TEST_EQUAL(true, actual != nullptr); #define CORE_TEST_FLOAT(wanted, actual, error) \ Core::Test::Internal::checkFloat(__FILE__, __LINE__, wanted, actual, error); #define CORE_TEST_VECTOR(wanted, actual) \ Core::Test::Internal::checkVector(__FILE__, __LINE__, wanted, actual, \ 0.0001f); #endif