Integrate ROM-dependent testing framework into YAZE

- Added a new RomDependentTestSuite to facilitate testing functionalities that rely on the currently loaded ROM, enhancing test coverage.
- Updated EditorManager to register the new test suite and manage the current ROM for dependent tests.
- Enhanced the IntegratedTestSuite to first check for a loaded ROM before proceeding with tests, improving robustness.
- Improved the TestManager UI to indicate ROM loading status and provide feedback for running ROM-dependent tests.
- Updated CMake configuration to include the new test suite header, ensuring proper integration into the build system.
This commit is contained in:
scawful
2025-09-25 13:44:03 -04:00
parent 8ab30dd5ad
commit c943577aff
6 changed files with 494 additions and 95 deletions

View File

@@ -26,5 +26,6 @@ set(
app/editor/system/popup_manager.cc app/editor/system/popup_manager.cc
app/test/test_manager.cc app/test/test_manager.cc
app/test/integrated_test_suite.h app/test/integrated_test_suite.h
app/test/rom_dependent_test_suite.h
app/test/unit_test_suite.h app/test/unit_test_suite.h
) )

View File

@@ -22,6 +22,7 @@
#include "app/rom.h" #include "app/rom.h"
#include "app/test/test_manager.h" #include "app/test/test_manager.h"
#include "app/test/integrated_test_suite.h" #include "app/test/integrated_test_suite.h"
#include "app/test/rom_dependent_test_suite.h"
#ifdef YAZE_ENABLE_GTEST #ifdef YAZE_ENABLE_GTEST
#include "app/test/unit_test_suite.h" #include "app/test/unit_test_suite.h"
#endif #endif
@@ -118,6 +119,7 @@ void EditorManager::InitializeTestSuites() {
test_manager.RegisterTestSuite(std::make_unique<test::PerformanceTestSuite>()); test_manager.RegisterTestSuite(std::make_unique<test::PerformanceTestSuite>());
test_manager.RegisterTestSuite(std::make_unique<test::UITestSuite>()); test_manager.RegisterTestSuite(std::make_unique<test::UITestSuite>());
test_manager.RegisterTestSuite(std::make_unique<test::ArenaTestSuite>()); test_manager.RegisterTestSuite(std::make_unique<test::ArenaTestSuite>());
test_manager.RegisterTestSuite(std::make_unique<test::RomDependentTestSuite>());
// Register Google Test suite if available // Register Google Test suite if available
#ifdef YAZE_ENABLE_GTEST #ifdef YAZE_ENABLE_GTEST
@@ -834,6 +836,9 @@ absl::Status EditorManager::LoadRom() {
current_rom_ = &session.rom; current_rom_ = &session.rom;
current_editor_set_ = &session.editors; current_editor_set_ = &session.editors;
// Update test manager with current ROM for ROM-dependent tests
test::TestManager::Get().SetCurrentRom(current_rom_);
static RecentFilesManager manager("recent_files.txt"); static RecentFilesManager manager("recent_files.txt");
manager.Load(); manager.Load();
manager.AddFile(file_name); manager.AddFile(file_name);
@@ -956,6 +961,10 @@ absl::Status EditorManager::SetCurrentRom(Rom *rom) {
if (&session.rom == rom) { if (&session.rom == rom) {
current_rom_ = &session.rom; current_rom_ = &session.rom;
current_editor_set_ = &session.editors; current_editor_set_ = &session.editors;
// Update test manager with current ROM for ROM-dependent tests
test::TestManager::Get().SetCurrentRom(current_rom_);
return absl::OkStatus(); return absl::OkStatus();
} }
} }

View File

@@ -151,10 +151,18 @@ class IntegratedTestSuite : public TestSuite {
result.error_message = "ROM testing disabled in configuration"; result.error_message = "ROM testing disabled in configuration";
} else { } else {
try { try {
// Test ROM class instantiation // First try to use currently loaded ROM from editor
Rom test_rom; Rom* current_rom = TestManager::Get().GetCurrentRom();
// Test with actual ROM file if available if (current_rom && current_rom->is_loaded()) {
// Test with currently loaded ROM
result.status = TestStatus::kPassed;
result.error_message = absl::StrFormat(
"Current ROM validated: %s (%zu bytes)",
current_rom->title().c_str(), current_rom->size());
} else {
// Fallback to loading ROM file
Rom test_rom;
std::string rom_path = test_rom_path_; std::string rom_path = test_rom_path_;
if (rom_path.empty()) { if (rom_path.empty()) {
rom_path = "zelda3.sfc"; rom_path = "zelda3.sfc";
@@ -165,7 +173,7 @@ class IntegratedTestSuite : public TestSuite {
if (status.ok()) { if (status.ok()) {
result.status = TestStatus::kPassed; result.status = TestStatus::kPassed;
result.error_message = absl::StrFormat( result.error_message = absl::StrFormat(
"ROM loaded successfully: %s (%zu bytes)", "ROM loaded from file: %s (%zu bytes)",
test_rom.title().c_str(), test_rom.size()); test_rom.title().c_str(), test_rom.size());
} else { } else {
result.status = TestStatus::kFailed; result.status = TestStatus::kFailed;
@@ -173,10 +181,11 @@ class IntegratedTestSuite : public TestSuite {
} }
} else if (skip_missing_rom_) { } else if (skip_missing_rom_) {
result.status = TestStatus::kSkipped; result.status = TestStatus::kSkipped;
result.error_message = "ROM file not found: " + rom_path; result.error_message = "No current ROM and file not found: " + rom_path;
} else { } else {
result.status = TestStatus::kFailed; result.status = TestStatus::kFailed;
result.error_message = "Required ROM file not found: " + rom_path; result.error_message = "No current ROM and required file not found: " + rom_path;
}
} }
} catch (const std::exception& e) { } catch (const std::exception& e) {

View File

@@ -0,0 +1,343 @@
#ifndef YAZE_APP_TEST_ROM_DEPENDENT_TEST_SUITE_H
#define YAZE_APP_TEST_ROM_DEPENDENT_TEST_SUITE_H
#include <chrono>
#include <memory>
#include <vector>
#include "absl/strings/str_format.h"
#include "app/test/test_manager.h"
#include "app/gfx/arena.h"
#include "app/rom.h"
#include "app/zelda3/overworld/overworld.h"
#include "app/gui/icons.h"
namespace yaze {
namespace test {
// ROM-dependent test suite that works with the currently loaded ROM
class RomDependentTestSuite : public TestSuite {
public:
RomDependentTestSuite() = default;
~RomDependentTestSuite() override = default;
std::string GetName() const override { return "ROM-Dependent Tests"; }
TestCategory GetCategory() const override { return TestCategory::kIntegration; }
absl::Status RunTests(TestResults& results) override {
Rom* current_rom = TestManager::Get().GetCurrentRom();
if (!current_rom || !current_rom->is_loaded()) {
// Add a skipped test indicating no ROM is loaded
TestResult result;
result.name = "ROM_Available_Check";
result.suite_name = GetName();
result.category = GetCategory();
result.status = TestStatus::kSkipped;
result.error_message = "No ROM currently loaded in editor";
result.duration = std::chrono::milliseconds{0};
result.timestamp = std::chrono::steady_clock::now();
results.AddResult(result);
return absl::OkStatus();
}
// Run ROM-dependent tests
RunRomHeaderValidationTest(results, current_rom);
RunRomDataAccessTest(results, current_rom);
RunRomGraphicsExtractionTest(results, current_rom);
RunRomOverworldLoadingTest(results, current_rom);
if (test_advanced_features_) {
RunRomSpriteDataTest(results, current_rom);
RunRomMusicDataTest(results, current_rom);
}
return absl::OkStatus();
}
void DrawConfiguration() override {
Rom* current_rom = TestManager::Get().GetCurrentRom();
ImGui::Text("%s ROM-Dependent Test Configuration", ICON_MD_STORAGE);
if (current_rom && current_rom->is_loaded()) {
ImGui::TextColored(ImVec4(0.0f, 1.0f, 0.0f, 1.0f),
"%s Current ROM: %s", ICON_MD_CHECK_CIRCLE, current_rom->title().c_str());
ImGui::Text("Size: %zu bytes", current_rom->size());
ImGui::Text("File: %s", current_rom->filename().c_str());
} else {
ImGui::TextColored(ImVec4(1.0f, 0.5f, 0.0f, 1.0f),
"%s No ROM currently loaded", ICON_MD_WARNING);
ImGui::Text("Load a ROM in the editor to enable ROM-dependent tests");
}
ImGui::Separator();
ImGui::Checkbox("Test ROM header validation", &test_header_validation_);
ImGui::Checkbox("Test ROM data access", &test_data_access_);
ImGui::Checkbox("Test graphics extraction", &test_graphics_extraction_);
ImGui::Checkbox("Test overworld loading", &test_overworld_loading_);
ImGui::Checkbox("Test advanced features", &test_advanced_features_);
if (test_advanced_features_) {
ImGui::Indent();
ImGui::Checkbox("Test sprite data", &test_sprite_data_);
ImGui::Checkbox("Test music data", &test_music_data_);
ImGui::Unindent();
}
}
private:
void RunRomHeaderValidationTest(TestResults& results, Rom* rom) {
auto start_time = std::chrono::steady_clock::now();
TestResult result;
result.name = "ROM_Header_Validation_Test";
result.suite_name = GetName();
result.category = GetCategory();
result.timestamp = start_time;
if (!test_header_validation_) {
result.status = TestStatus::kSkipped;
result.error_message = "Header validation disabled in configuration";
} else {
try {
std::string title = rom->title();
size_t size = rom->size();
// Basic validation
bool valid_title = !title.empty() && title != "ZELDA3" && title.length() <= 21;
bool valid_size = size >= 1024*1024 && size <= 8*1024*1024; // 1MB to 8MB
if (valid_title && valid_size) {
result.status = TestStatus::kPassed;
result.error_message = absl::StrFormat(
"ROM header valid: '%s' (%zu bytes)", title.c_str(), size);
} else {
result.status = TestStatus::kFailed;
result.error_message = absl::StrFormat(
"ROM header validation failed: title='%s' size=%zu", title.c_str(), size);
}
} catch (const std::exception& e) {
result.status = TestStatus::kFailed;
result.error_message = "Header validation failed: " + std::string(e.what());
}
}
auto end_time = std::chrono::steady_clock::now();
result.duration = std::chrono::duration_cast<std::chrono::milliseconds>(
end_time - start_time);
results.AddResult(result);
}
void RunRomDataAccessTest(TestResults& results, Rom* rom) {
auto start_time = std::chrono::steady_clock::now();
TestResult result;
result.name = "ROM_Data_Access_Test";
result.suite_name = GetName();
result.category = GetCategory();
result.timestamp = start_time;
if (!test_data_access_) {
result.status = TestStatus::kSkipped;
result.error_message = "Data access testing disabled in configuration";
} else {
try {
// Test basic ROM data access patterns
size_t bytes_tested = 0;
bool access_success = true;
// Test reading from various ROM regions
try {
[[maybe_unused]] auto header_byte = rom->ReadByte(0x7FC0);
bytes_tested++;
[[maybe_unused]] auto code_byte = rom->ReadByte(0x8000);
bytes_tested++;
[[maybe_unused]] auto data_word = rom->ReadWord(0x8002);
bytes_tested++;
} catch (...) {
access_success = false;
}
if (access_success && bytes_tested >= 3) {
result.status = TestStatus::kPassed;
result.error_message = absl::StrFormat(
"ROM data access verified: %zu operations", bytes_tested);
} else {
result.status = TestStatus::kFailed;
result.error_message = "ROM data access failed";
}
} catch (const std::exception& e) {
result.status = TestStatus::kFailed;
result.error_message = "Data access test failed: " + std::string(e.what());
}
}
auto end_time = std::chrono::steady_clock::now();
result.duration = std::chrono::duration_cast<std::chrono::milliseconds>(
end_time - start_time);
results.AddResult(result);
}
void RunRomGraphicsExtractionTest(TestResults& results, Rom* rom) {
auto start_time = std::chrono::steady_clock::now();
TestResult result;
result.name = "ROM_Graphics_Extraction_Test";
result.suite_name = GetName();
result.category = GetCategory();
result.timestamp = start_time;
if (!test_graphics_extraction_) {
result.status = TestStatus::kSkipped;
result.error_message = "Graphics extraction testing disabled in configuration";
} else {
try {
auto graphics_result = LoadAllGraphicsData(*rom);
if (graphics_result.ok()) {
auto& sheets = graphics_result.value();
size_t loaded_sheets = 0;
for (const auto& sheet : sheets) {
if (sheet.is_active()) {
loaded_sheets++;
}
}
result.status = TestStatus::kPassed;
result.error_message = absl::StrFormat(
"Graphics extraction successful: %zu/%zu sheets loaded",
loaded_sheets, sheets.size());
} else {
result.status = TestStatus::kFailed;
result.error_message = "Graphics extraction failed: " +
std::string(graphics_result.status().message());
}
} catch (const std::exception& e) {
result.status = TestStatus::kFailed;
result.error_message = "Graphics extraction test failed: " + std::string(e.what());
}
}
auto end_time = std::chrono::steady_clock::now();
result.duration = std::chrono::duration_cast<std::chrono::milliseconds>(
end_time - start_time);
results.AddResult(result);
}
void RunRomOverworldLoadingTest(TestResults& results, Rom* rom) {
auto start_time = std::chrono::steady_clock::now();
TestResult result;
result.name = "ROM_Overworld_Loading_Test";
result.suite_name = GetName();
result.category = GetCategory();
result.timestamp = start_time;
if (!test_overworld_loading_) {
result.status = TestStatus::kSkipped;
result.error_message = "Overworld loading testing disabled in configuration";
} else {
try {
zelda3::Overworld overworld(rom);
auto ow_status = overworld.Load(rom);
if (ow_status.ok()) {
result.status = TestStatus::kPassed;
result.error_message = "Overworld loading successful from current ROM";
} else {
result.status = TestStatus::kFailed;
result.error_message = "Overworld loading failed: " + std::string(ow_status.message());
}
} catch (const std::exception& e) {
result.status = TestStatus::kFailed;
result.error_message = "Overworld loading test failed: " + std::string(e.what());
}
}
auto end_time = std::chrono::steady_clock::now();
result.duration = std::chrono::duration_cast<std::chrono::milliseconds>(
end_time - start_time);
results.AddResult(result);
}
void RunRomSpriteDataTest(TestResults& results, Rom* rom) {
auto start_time = std::chrono::steady_clock::now();
TestResult result;
result.name = "ROM_Sprite_Data_Test";
result.suite_name = GetName();
result.category = GetCategory();
result.timestamp = start_time;
if (!test_sprite_data_) {
result.status = TestStatus::kSkipped;
result.error_message = "Sprite data testing disabled in configuration";
} else {
try {
// Basic sprite data validation (simplified for now)
// In a full implementation, this would test sprite loading
result.status = TestStatus::kSkipped;
result.error_message = "Sprite data testing not yet implemented";
} catch (const std::exception& e) {
result.status = TestStatus::kFailed;
result.error_message = "Sprite data test failed: " + std::string(e.what());
}
}
auto end_time = std::chrono::steady_clock::now();
result.duration = std::chrono::duration_cast<std::chrono::milliseconds>(
end_time - start_time);
results.AddResult(result);
}
void RunRomMusicDataTest(TestResults& results, Rom* rom) {
auto start_time = std::chrono::steady_clock::now();
TestResult result;
result.name = "ROM_Music_Data_Test";
result.suite_name = GetName();
result.category = GetCategory();
result.timestamp = start_time;
if (!test_music_data_) {
result.status = TestStatus::kSkipped;
result.error_message = "Music data testing disabled in configuration";
} else {
try {
// Basic music data validation (simplified for now)
// In a full implementation, this would test music loading
result.status = TestStatus::kSkipped;
result.error_message = "Music data testing not yet implemented";
} catch (const std::exception& e) {
result.status = TestStatus::kFailed;
result.error_message = "Music data test failed: " + std::string(e.what());
}
}
auto end_time = std::chrono::steady_clock::now();
result.duration = std::chrono::duration_cast<std::chrono::milliseconds>(
end_time - start_time);
results.AddResult(result);
}
// Configuration
bool test_header_validation_ = true;
bool test_data_access_ = true;
bool test_graphics_extraction_ = true;
bool test_overworld_loading_ = true;
bool test_advanced_features_ = false;
bool test_sprite_data_ = false;
bool test_music_data_ = false;
};
} // namespace test
} // namespace yaze
#endif // YAZE_APP_TEST_ROM_DEPENDENT_TEST_SUITE_H

View File

@@ -1,7 +1,9 @@
#include "app/test/test_manager.h" #include "app/test/test_manager.h"
#include "absl/strings/str_format.h" #include "absl/strings/str_format.h"
#include "absl/strings/str_cat.h"
#include "app/gfx/arena.h" #include "app/gfx/arena.h"
#include "app/gui/icons.h"
#include "imgui/imgui.h" #include "imgui/imgui.h"
#ifdef YAZE_ENABLE_IMGUI_TEST_ENGINE #ifdef YAZE_ENABLE_IMGUI_TEST_ENGINE
@@ -274,6 +276,17 @@ void TestManager::DrawTestDashboard() {
ImGui::Begin("Test Dashboard", &show_dashboard_, ImGuiWindowFlags_MenuBar); ImGui::Begin("Test Dashboard", &show_dashboard_, ImGuiWindowFlags_MenuBar);
// ROM status indicator
bool has_rom = current_rom_ && current_rom_->is_loaded();
if (has_rom) {
ImGui::TextColored(ImVec4(0.0f, 1.0f, 0.0f, 1.0f),
"%s ROM Loaded: %s", ICON_MD_CHECK_CIRCLE, current_rom_->title().c_str());
} else {
ImGui::TextColored(ImVec4(1.0f, 0.5f, 0.0f, 1.0f),
"%s No ROM loaded - ROM-dependent tests will be skipped", ICON_MD_WARNING);
}
ImGui::Separator();
// Menu bar // Menu bar
if (ImGui::BeginMenuBar()) { if (ImGui::BeginMenuBar()) {
if (ImGui::BeginMenu("Run")) { if (ImGui::BeginMenu("Run")) {
@@ -321,25 +334,46 @@ void TestManager::DrawTestDashboard() {
// Enhanced test execution status // Enhanced test execution status
if (is_running_) { if (is_running_) {
ImGui::PushStyleColor(ImGuiCol_Text, GetTestStatusColor(TestStatus::kRunning)); ImGui::PushStyleColor(ImGuiCol_Text, GetTestStatusColor(TestStatus::kRunning));
ImGui::Text(" Running: %s", current_test_name_.c_str()); ImGui::Text("%s Running: %s", ICON_MD_PLAY_CIRCLE_FILLED, current_test_name_.c_str());
ImGui::PopStyleColor(); ImGui::PopStyleColor();
ImGui::ProgressBar(progress_, ImVec2(-1, 0), ImGui::ProgressBar(progress_, ImVec2(-1, 0),
absl::StrFormat("%.0f%%", progress_ * 100.0f).c_str()); absl::StrFormat("%.0f%%", progress_ * 100.0f).c_str());
} else { } else {
// Enhanced control buttons // Enhanced control buttons
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.2f, 0.7f, 0.2f, 1.0f)); ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.2f, 0.7f, 0.2f, 1.0f));
if (ImGui::Button("🚀 Run All Tests", ImVec2(140, 0))) { if (ImGui::Button(absl::StrCat(ICON_MD_PLAY_ARROW, " Run All Tests").c_str(), ImVec2(140, 0))) {
[[maybe_unused]] auto status = RunAllTests(); [[maybe_unused]] auto status = RunAllTests();
} }
ImGui::PopStyleColor(); ImGui::PopStyleColor();
ImGui::SameLine(); ImGui::SameLine();
if (ImGui::Button("🧪 Quick Test", ImVec2(100, 0))) { if (ImGui::Button(absl::StrCat(ICON_MD_SPEED, " Quick Test").c_str(), ImVec2(100, 0))) {
[[maybe_unused]] auto status = RunTestsByCategory(TestCategory::kMemory); [[maybe_unused]] auto status = RunTestsByCategory(TestCategory::kMemory);
} }
ImGui::SameLine(); ImGui::SameLine();
if (ImGui::Button("🗑️ Clear", ImVec2(80, 0))) { bool has_rom = current_rom_ && current_rom_->is_loaded();
if (has_rom) {
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.2f, 0.5f, 0.8f, 1.0f));
}
if (ImGui::Button(absl::StrCat(ICON_MD_STORAGE, " ROM Tests").c_str(), ImVec2(100, 0))) {
if (has_rom) {
[[maybe_unused]] auto status = RunTestsByCategory(TestCategory::kIntegration);
}
}
if (has_rom) {
ImGui::PopStyleColor();
}
if (ImGui::IsItemHovered()) {
if (has_rom) {
ImGui::SetTooltip("Run tests on current ROM: %s", current_rom_->title().c_str());
} else {
ImGui::SetTooltip("Load a ROM to enable ROM-dependent tests");
}
}
ImGui::SameLine();
if (ImGui::Button(absl::StrCat(ICON_MD_CLEAR, " Clear").c_str(), ImVec2(80, 0))) {
ClearResults(); ClearResults();
} }
} }
@@ -349,7 +383,7 @@ void TestManager::DrawTestDashboard() {
// Enhanced test results summary with better visuals // Enhanced test results summary with better visuals
if (last_results_.total_tests > 0) { if (last_results_.total_tests > 0) {
// Test summary header // Test summary header
ImGui::Text("📊 Test Results Summary"); ImGui::Text("%s Test Results Summary", ICON_MD_ASSESSMENT);
// Progress bar showing pass rate // Progress bar showing pass rate
float pass_rate = last_results_.GetPassRate(); float pass_rate = last_results_.GetPassRate();
@@ -363,18 +397,18 @@ void TestManager::DrawTestDashboard() {
ImGui::PopStyleColor(); ImGui::PopStyleColor();
// Test counts with icons // Test counts with icons
ImGui::Text("📈 Total: %zu", last_results_.total_tests); ImGui::Text("%s Total: %zu", ICON_MD_ANALYTICS, last_results_.total_tests);
ImGui::SameLine(); ImGui::SameLine();
ImGui::TextColored(GetTestStatusColor(TestStatus::kPassed), ImGui::TextColored(GetTestStatusColor(TestStatus::kPassed),
" %zu", last_results_.passed_tests); "%s %zu", ICON_MD_CHECK_CIRCLE, last_results_.passed_tests);
ImGui::SameLine(); ImGui::SameLine();
ImGui::TextColored(GetTestStatusColor(TestStatus::kFailed), ImGui::TextColored(GetTestStatusColor(TestStatus::kFailed),
" %zu", last_results_.failed_tests); "%s %zu", ICON_MD_ERROR, last_results_.failed_tests);
ImGui::SameLine(); ImGui::SameLine();
ImGui::TextColored(GetTestStatusColor(TestStatus::kSkipped), ImGui::TextColored(GetTestStatusColor(TestStatus::kSkipped),
"⏭️ %zu", last_results_.skipped_tests); "%s %zu", ICON_MD_SKIP_NEXT, last_results_.skipped_tests);
ImGui::Text("⏱️ Duration: %lld ms", last_results_.total_duration.count()); ImGui::Text("%s Duration: %lld ms", ICON_MD_TIMER, last_results_.total_duration.count());
// Test suite breakdown // Test suite breakdown
if (ImGui::CollapsingHeader("Test Suite Breakdown")) { if (ImGui::CollapsingHeader("Test Suite Breakdown")) {
@@ -399,7 +433,7 @@ void TestManager::DrawTestDashboard() {
ImGui::Separator(); ImGui::Separator();
// Enhanced test filter with category selection // Enhanced test filter with category selection
ImGui::Text("🔍 Filter & View Options"); ImGui::Text("%s Filter & View Options", ICON_MD_FILTER_LIST);
// Category filter // Category filter
const char* categories[] = {"All", "Unit", "Integration", "UI", "Performance", "Memory"}; const char* categories[] = {"All", "Unit", "Integration", "UI", "Performance", "Memory"};
@@ -449,12 +483,12 @@ void TestManager::DrawTestDashboard() {
ImGui::PushID(&result); ImGui::PushID(&result);
// Status icon and test name // Status icon and test name
const char* status_icon = ""; const char* status_icon = ICON_MD_HELP;
switch (result.status) { switch (result.status) {
case TestStatus::kPassed: status_icon = ""; break; case TestStatus::kPassed: status_icon = ICON_MD_CHECK_CIRCLE; break;
case TestStatus::kFailed: status_icon = ""; break; case TestStatus::kFailed: status_icon = ICON_MD_ERROR; break;
case TestStatus::kSkipped: status_icon = "⏭️"; break; case TestStatus::kSkipped: status_icon = ICON_MD_SKIP_NEXT; break;
case TestStatus::kRunning: status_icon = ""; break; case TestStatus::kRunning: status_icon = ICON_MD_PLAY_CIRCLE_FILLED; break;
default: break; default: break;
} }
@@ -475,7 +509,7 @@ void TestManager::DrawTestDashboard() {
if (result.status == TestStatus::kFailed && !result.error_message.empty()) { if (result.status == TestStatus::kFailed && !result.error_message.empty()) {
ImGui::Indent(); ImGui::Indent();
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 0.8f, 0.8f, 1.0f)); ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 0.8f, 0.8f, 1.0f));
ImGui::TextWrapped("💥 %s", result.error_message.c_str()); ImGui::TextWrapped("%s %s", ICON_MD_ERROR_OUTLINE, result.error_message.c_str());
ImGui::PopStyleColor(); ImGui::PopStyleColor();
ImGui::Unindent(); ImGui::Unindent();
} }
@@ -484,7 +518,7 @@ void TestManager::DrawTestDashboard() {
if (result.status == TestStatus::kPassed && !result.error_message.empty()) { if (result.status == TestStatus::kPassed && !result.error_message.empty()) {
ImGui::Indent(); ImGui::Indent();
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.8f, 1.0f, 0.8f, 1.0f)); ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.8f, 1.0f, 0.8f, 1.0f));
ImGui::TextWrapped(" %s", result.error_message.c_str()); ImGui::TextWrapped("%s %s", ICON_MD_INFO, result.error_message.c_str());
ImGui::PopStyleColor(); ImGui::PopStyleColor();
ImGui::Unindent(); ImGui::Unindent();
} }
@@ -499,14 +533,14 @@ void TestManager::DrawTestDashboard() {
// Resource monitor window // Resource monitor window
if (show_resource_monitor_) { if (show_resource_monitor_) {
ImGui::Begin("Resource Monitor", &show_resource_monitor_); ImGui::Begin(absl::StrCat(ICON_MD_MONITOR, " Resource Monitor").c_str(), &show_resource_monitor_);
if (!resource_history_.empty()) { if (!resource_history_.empty()) {
const auto& latest = resource_history_.back(); const auto& latest = resource_history_.back();
ImGui::Text("Textures: %zu", latest.texture_count); ImGui::Text("%s Textures: %zu", ICON_MD_TEXTURE, latest.texture_count);
ImGui::Text("Surfaces: %zu", latest.surface_count); ImGui::Text("%s Surfaces: %zu", ICON_MD_LAYERS, latest.surface_count);
ImGui::Text("Memory: %zu MB", latest.memory_usage_mb); ImGui::Text("%s Memory: %zu MB", ICON_MD_MEMORY, latest.memory_usage_mb);
ImGui::Text("FPS: %.1f", latest.frame_rate); ImGui::Text("%s FPS: %.1f", ICON_MD_SPEED, latest.frame_rate);
// Simple plot of resource usage over time // Simple plot of resource usage over time
if (resource_history_.size() > 1) { if (resource_history_.size() > 1) {

View File

@@ -1,13 +1,14 @@
#ifndef YAZE_APP_TEST_TEST_MANAGER_H #ifndef YAZE_APP_TEST_TEST_MANAGER_H
#define YAZE_APP_TEST_TEST_MANAGER_H #define YAZE_APP_TEST_TEST_MANAGER_H
#include <chrono>
#include <memory> #include <memory>
#include <string> #include <string>
#include <vector>
#include <unordered_map> #include <unordered_map>
#include <chrono> #include <vector>
#include "absl/status/status.h" #include "absl/status/status.h"
#include "app/rom.h"
#include "imgui/imgui.h" #include "imgui/imgui.h"
#ifdef YAZE_ENABLE_IMGUI_TEST_ENGINE #ifdef YAZE_ENABLE_IMGUI_TEST_ENGINE
@@ -21,22 +22,10 @@ namespace yaze {
namespace test { namespace test {
// Test execution status // Test execution status
enum class TestStatus { enum class TestStatus { kNotRun, kRunning, kPassed, kFailed, kSkipped };
kNotRun,
kRunning,
kPassed,
kFailed,
kSkipped
};
// Test categories for organization // Test categories for organization
enum class TestCategory { enum class TestCategory { kUnit, kIntegration, kUI, kPerformance, kMemory };
kUnit,
kIntegration,
kUI,
kPerformance,
kMemory
};
// Individual test result // Individual test result
struct TestResult { struct TestResult {
@@ -62,10 +51,17 @@ struct TestResults {
individual_results.push_back(result); individual_results.push_back(result);
total_tests++; total_tests++;
switch (result.status) { switch (result.status) {
case TestStatus::kPassed: passed_tests++; break; case TestStatus::kPassed:
case TestStatus::kFailed: failed_tests++; break; passed_tests++;
case TestStatus::kSkipped: skipped_tests++; break; break;
default: break; case TestStatus::kFailed:
failed_tests++;
break;
case TestStatus::kSkipped:
skipped_tests++;
break;
default:
break;
} }
total_duration += result.duration; total_duration += result.duration;
} }
@@ -77,7 +73,8 @@ struct TestResults {
} }
float GetPassRate() const { float GetPassRate() const {
return total_tests > 0 ? static_cast<float>(passed_tests) / total_tests : 0.0f; return total_tests > 0 ? static_cast<float>(passed_tests) / total_tests
: 0.0f;
} }
}; };
@@ -128,9 +125,7 @@ class TestManager {
void SetMaxConcurrentTests(size_t max_concurrent) { void SetMaxConcurrentTests(size_t max_concurrent) {
max_concurrent_tests_ = max_concurrent; max_concurrent_tests_ = max_concurrent;
} }
void SetTestTimeout(std::chrono::seconds timeout) { void SetTestTimeout(std::chrono::seconds timeout) { test_timeout_ = timeout; }
test_timeout_ = timeout;
}
// Resource monitoring // Resource monitoring
void UpdateResourceStats(); void UpdateResourceStats();
@@ -143,7 +138,8 @@ class TestManager {
ImGuiTestEngine* GetUITestEngine() { return ui_test_engine_; } ImGuiTestEngine* GetUITestEngine() { return ui_test_engine_; }
void InitializeUITesting(); void InitializeUITesting();
void StopUITesting(); // Stop test engine while ImGui context is valid void StopUITesting(); // Stop test engine while ImGui context is valid
void DestroyUITestingContext(); // Destroy test engine after ImGui context is destroyed void DestroyUITestingContext(); // Destroy test engine after ImGui context is
// destroyed
void ShutdownUITesting(); // Complete shutdown (calls both Stop and Destroy) void ShutdownUITesting(); // Complete shutdown (calls both Stop and Destroy)
#else #else
void* GetUITestEngine() { return nullptr; } void* GetUITestEngine() { return nullptr; }
@@ -161,6 +157,10 @@ class TestManager {
// UI Interface // UI Interface
void DrawTestDashboard(); void DrawTestDashboard();
// ROM-dependent testing
void SetCurrentRom(Rom* rom) { current_rom_ = rom; }
Rom* GetCurrentRom() const { return current_rom_; }
private: private:
TestManager(); TestManager();
~TestManager(); ~TestManager();
@@ -200,6 +200,9 @@ class TestManager {
bool show_resource_monitor_ = false; bool show_resource_monitor_ = false;
std::string test_filter_; std::string test_filter_;
TestCategory category_filter_ = TestCategory::kUnit; TestCategory category_filter_ = TestCategory::kUnit;
// ROM-dependent testing
Rom* current_rom_ = nullptr;
}; };
// Utility functions for test result formatting // Utility functions for test result formatting