#ifndef CORE_TEST_HPP #define CORE_TEST_HPP #include "core/data/HashMap.hpp" #include "core/math/Vector.hpp" #include "core/utils/Logger.hpp" namespace Core::Test { namespace Internal { struct Result final { int tests = 0; int successTests = 0; }; using FileName = String32<256>; extern HashMap results; void warn(const char* file, int line, Error e); template bool check(const char* file, int line, const T& wanted, const T& actual, bool c) { file = Logger::getFileName(file); Error e = Error::NONE; FileName fileName; if(checkError(e, fileName.append(file))) { warn(file, line, e); return false; } Result* result = results.search(fileName); if(result == nullptr && checkError(e, results.tryEmplace(result, fileName))) { warn(file, line, e); return false; } result->tests++; if(c) { result->successTests++; return true; } CORE_LOG_ERROR("#:# - expected '#' got '#'", fileName, line, wanted, actual); return false; } template bool checkEqual(const char* file, int line, const T& wanted, const T& actual) { return check(file, line, wanted, actual, wanted == actual); } template bool checkString(const char* file, int line, const A& wanted, const B& actual) { Error e = Error::NONE; String32<2048> a; if(checkError(e, a.append(wanted))) { warn(file, line, e); return false; } String32<2048> b; if(checkError(e, b.append(actual))) { warn(file, line, e); return false; } return checkEqual(file, line, a, b); } bool checkFloat(const char* file, int line, float wanted, float actual, float error); template bool checkVector(const char* file, int line, const Core::Vector& wanted, const Core::Vector& actual, float error) { bool result = true; for(int i = 0; i < N; i++) { result &= checkFloat(file, line, static_cast(wanted[i]), static_cast(actual[i]), error); } return result; } } void finalize(); } #define CORE_TEST_EQUAL(wanted, actual) \ Core::Test::Internal::checkEqual>( \ __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_ERROR(actual) CORE_TEST_EQUAL(Core::Error::NONE, actual) #define CORE_TEST_NULL(actual) CORE_TEST_EQUAL(true, actual == nullptr) // double check to make the null check clear for the compiler #define CORE_TEST_NOT_NULL(actual) \ (CORE_TEST_EQUAL(true, (actual) != nullptr) && (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