PokemonScriptTester/src/Tester/TestRunner.hpp

123 lines
5.0 KiB
C++

#ifndef POKEMONSCRIPTTESTER_TESTRUNNER_HPP
#define POKEMONSCRIPTTESTER_TESTRUNNER_HPP
#include <PkmnLib/ScriptResolving/AngelScript/AngelScriptMetadata.hpp>
#include <PkmnLib/ScriptResolving/AngelScript/ContextPool.hpp>
#include <chrono>
#include <thread>
#include "../../extern/termcolor.hpp"
#include "Test.hpp"
class TestRunner {
AngelScriptResolver* _scriptResolver;
ArbUt::Dictionary<std::string, std::unique_ptr<Test>> _tests;
public:
TestRunner(AngelScriptResolver* scriptResolver) : _scriptResolver(scriptResolver) {
const auto* module = scriptResolver->GetMainModule();
auto builder = scriptResolver->GetBuilder();
for (u32 i = 0; i < module->GetFunctionCount(); ++i) {
auto* func = module->GetFunctionByIndex(i);
auto metaData = builder.GetMetadataForFunc(func);
for (const auto& m : metaData) {
auto meta = AngelscriptMetadata(m);
if (meta.GetIdentifier() == "Test"_cnc) {
auto name = meta.GetParameter("name"_cnc);
if (_tests.Has(name)) {
std::cout << termcolor::red << "Duplicate test name: '" << name << "'." << termcolor::reset
<< std::endl;
continue;
}
_tests.GetStdMap().insert({name, std::make_unique<Test>(name, func)});
}
}
}
}
i32 RunAll([[maybe_unused]]bool waitForDebugger) {
auto ctx = _scriptResolver->GetContextPool()->RequestContext();
ctx->SetUserData(_scriptResolver->GetUserdata());
#if ANGELSCRIPT_DEBUGGER
_scriptResolver->SetDebugger(new AngelscriptDebugger());
auto& debugger = *_scriptResolver->GetDebugger().GetValue();
debugger.Run(8684);
debugger.RegisterContext(ctx);
if (waitForDebugger) {
std::cout << "Waiting for debugger" << std::endl;
while (!debugger.HasDebuggerAttached()) {
continue;
}
std::this_thread::sleep_for(std::chrono::milliseconds(500));
}
#endif
for (auto& test : _tests) {
test.second->Run(ctx);
}
ctx->Release();
size_t notRunTests = 0;
size_t successfulTests = 0;
size_t failedTests = 0;
size_t totalRequirements = 0;
size_t failedRequirements = 0;
for (auto& test : _tests) {
auto result = test.second->GetResult();
switch (result) {
case TestResult::NotRan: notRunTests += 1; break;
case TestResult::Success: successfulTests += 1; break;
case TestResult::Failed: {
std::cout << termcolor::red << "Test '" << termcolor::yellow << test.first << termcolor::red
<< "' failed with message: " << termcolor::reset << std::endl;
std::cout << test.second->GetErrorMessage() << std::endl << std::endl;
failedTests += 1;
break;
}
}
totalRequirements += test.second->GetTotalRequirements();
failedRequirements += test.second->GetFailedRequirements();
}
auto totalTests = successfulTests + failedTests;
auto digitWidth = std::log10(std::max(totalTests, totalRequirements)) + 2;
std::cout << "Running tests in library folder: " << std::filesystem::current_path().stem() << std::endl;
std::cout << termcolor::blue << "=====================================================================";
for (int i = 0; i < digitWidth; ++i) {
std::cout << "===";
}
std::cout << termcolor::reset << std::endl;
ReportResults("Test cases", digitWidth, totalTests, successfulTests, failedTests, notRunTests);
ReportResults("Requirements", digitWidth, totalRequirements, totalRequirements - failedRequirements,
failedRequirements, {});
if (failedTests > 0) {
return 1;
}
return 0;
}
static void ReportResults(const std::string& label, double digitWidth, size_t total, size_t passed, size_t failed,
std::optional<size_t> skipped) {
std::cout << std::left // Left align
<< std::setw(16) << label + ":" << std::setw(digitWidth) << total << std::setw(3) << "|";
if (passed > 0) {
std::cout << termcolor::green;
}
std::cout << std::left << std::setw(14) << "Passed:" << std::setw(digitWidth) << passed << termcolor::reset
<< std::setw(3) << "|";
if (failed > 0) {
std::cout << termcolor::red;
}
std::cout << std::setw(14) << "Failed:" << std::setw(digitWidth) << failed << termcolor::reset;
std::cout << std::setw(3) << "|";
if (skipped.has_value()) {
std::cout << std::setw(14) << "Skipped:" << std::setw(digitWidth) << skipped.value();
}
std::cout << std::endl;
}
};
#endif // POKEMONSCRIPTTESTER_TESTRUNNER_HPP