129 lines
3.7 KiB
C++
129 lines
3.7 KiB
C++
#include "test_harness.h"
|
|
#include <nlohmann/json.hpp>
|
|
#include <fstream>
|
|
#include <iomanip>
|
|
#include <ctime>
|
|
|
|
void TestHarness::AddTest(const std::string& name, std::function<bool(std::string&)> func) {
|
|
m_tests.push_back({name, func});
|
|
}
|
|
|
|
std::vector<TestResult> TestHarness::Run(const std::string& filter) {
|
|
std::vector<TestResult> results;
|
|
|
|
for (const auto& test : m_tests) {
|
|
// Filter check
|
|
if (!filter.empty() && test.name.find(filter) == std::string::npos) {
|
|
continue;
|
|
}
|
|
|
|
TestResult result;
|
|
result.name = test.name;
|
|
|
|
std::cout << "Running: " << test.name << "... " << std::flush;
|
|
|
|
auto start = std::chrono::steady_clock::now();
|
|
|
|
try {
|
|
std::string error;
|
|
result.passed = test.func(error);
|
|
result.error_message = error;
|
|
} catch (const std::exception& e) {
|
|
result.passed = false;
|
|
result.error_message = std::string("Exception: ") + e.what();
|
|
} catch (...) {
|
|
result.passed = false;
|
|
result.error_message = "Unknown exception";
|
|
}
|
|
|
|
auto end = std::chrono::steady_clock::now();
|
|
result.duration_ms = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
|
|
|
|
if (result.passed) {
|
|
std::cout << "PASSED (" << result.duration_ms << "ms)\n";
|
|
} else {
|
|
std::cout << "FAILED\n";
|
|
std::cout << " Error: " << result.error_message << "\n";
|
|
}
|
|
|
|
results.push_back(result);
|
|
}
|
|
|
|
return results;
|
|
}
|
|
|
|
void TestHarness::WriteJsonReport(const std::vector<TestResult>& results, const std::string& path) {
|
|
nlohmann::json report;
|
|
|
|
// Get timestamp
|
|
auto now = std::chrono::system_clock::now();
|
|
auto time = std::chrono::system_clock::to_time_t(now);
|
|
std::stringstream ss;
|
|
ss << std::put_time(std::gmtime(&time), "%Y-%m-%dT%H:%M:%SZ");
|
|
|
|
report["name"] = "Lua Sandbox Security Tests";
|
|
report["timestamp"] = ss.str();
|
|
|
|
int passed = 0, failed = 0;
|
|
for (const auto& r : results) {
|
|
if (r.passed) passed++;
|
|
else failed++;
|
|
}
|
|
|
|
report["summary"]["passed"] = passed;
|
|
report["summary"]["failed"] = failed;
|
|
report["summary"]["total"] = static_cast<int>(results.size());
|
|
|
|
nlohmann::json tests = nlohmann::json::array();
|
|
for (const auto& r : results) {
|
|
nlohmann::json t;
|
|
t["name"] = r.name;
|
|
t["status"] = r.passed ? "passed" : "failed";
|
|
t["duration_ms"] = r.duration_ms;
|
|
if (!r.passed && !r.error_message.empty()) {
|
|
t["error"] = r.error_message;
|
|
}
|
|
tests.push_back(t);
|
|
}
|
|
report["tests"] = tests;
|
|
|
|
std::ofstream f(path);
|
|
f << report.dump(2);
|
|
}
|
|
|
|
void TestHarness::PrintResults(const std::vector<TestResult>& results) {
|
|
std::cout << "\n";
|
|
std::cout << "========================================\n";
|
|
std::cout << " TEST RESULTS\n";
|
|
std::cout << "========================================\n\n";
|
|
|
|
int passed = 0, failed = 0;
|
|
for (const auto& r : results) {
|
|
if (r.passed) passed++;
|
|
else failed++;
|
|
}
|
|
|
|
std::cout << "Total: " << results.size() << "\n";
|
|
std::cout << "Passed: " << passed << "\n";
|
|
std::cout << "Failed: " << failed << "\n\n";
|
|
|
|
if (failed > 0) {
|
|
std::cout << "FAILED TESTS:\n";
|
|
for (const auto& r : results) {
|
|
if (!r.passed) {
|
|
std::cout << " - " << r.name << "\n";
|
|
std::cout << " " << r.error_message << "\n";
|
|
}
|
|
}
|
|
std::cout << "\n";
|
|
}
|
|
|
|
if (failed == 0) {
|
|
std::cout << "ALL TESTS PASSED!\n";
|
|
} else {
|
|
std::cout << "SOME TESTS FAILED!\n";
|
|
}
|
|
|
|
std::cout << "========================================\n";
|
|
}
|