diff --git a/src/app/editor/editor.cmake b/src/app/editor/editor.cmake index fc05255e..eeb9f7d5 100644 --- a/src/app/editor/editor.cmake +++ b/src/app/editor/editor.cmake @@ -26,5 +26,6 @@ set( app/editor/system/popup_manager.cc app/test/test_manager.cc app/test/integrated_test_suite.h + app/test/rom_dependent_test_suite.h app/test/unit_test_suite.h ) diff --git a/src/app/editor/editor_manager.cc b/src/app/editor/editor_manager.cc index da013822..428fab11 100644 --- a/src/app/editor/editor_manager.cc +++ b/src/app/editor/editor_manager.cc @@ -22,6 +22,7 @@ #include "app/rom.h" #include "app/test/test_manager.h" #include "app/test/integrated_test_suite.h" +#include "app/test/rom_dependent_test_suite.h" #ifdef YAZE_ENABLE_GTEST #include "app/test/unit_test_suite.h" #endif @@ -118,6 +119,7 @@ void EditorManager::InitializeTestSuites() { test_manager.RegisterTestSuite(std::make_unique()); test_manager.RegisterTestSuite(std::make_unique()); test_manager.RegisterTestSuite(std::make_unique()); + test_manager.RegisterTestSuite(std::make_unique()); // Register Google Test suite if available #ifdef YAZE_ENABLE_GTEST @@ -833,6 +835,9 @@ absl::Status EditorManager::LoadRom() { } current_rom_ = &session.rom; 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"); manager.Load(); @@ -956,6 +961,10 @@ absl::Status EditorManager::SetCurrentRom(Rom *rom) { if (&session.rom == rom) { current_rom_ = &session.rom; current_editor_set_ = &session.editors; + + // Update test manager with current ROM for ROM-dependent tests + test::TestManager::Get().SetCurrentRom(current_rom_); + return absl::OkStatus(); } } diff --git a/src/app/test/integrated_test_suite.h b/src/app/test/integrated_test_suite.h index b8b0ef07..696f2d20 100644 --- a/src/app/test/integrated_test_suite.h +++ b/src/app/test/integrated_test_suite.h @@ -151,32 +151,41 @@ class IntegratedTestSuite : public TestSuite { result.error_message = "ROM testing disabled in configuration"; } else { try { - // Test ROM class instantiation - Rom test_rom; + // First try to use currently loaded ROM from editor + Rom* current_rom = TestManager::Get().GetCurrentRom(); - // Test with actual ROM file if available - std::string rom_path = test_rom_path_; - if (rom_path.empty()) { - rom_path = "zelda3.sfc"; - } - - if (std::filesystem::exists(rom_path)) { - auto status = test_rom.LoadFromFile(rom_path); - if (status.ok()) { - result.status = TestStatus::kPassed; - result.error_message = absl::StrFormat( - "ROM loaded successfully: %s (%zu bytes)", - test_rom.title().c_str(), test_rom.size()); + 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_; + if (rom_path.empty()) { + rom_path = "zelda3.sfc"; + } + + if (std::filesystem::exists(rom_path)) { + auto status = test_rom.LoadFromFile(rom_path); + if (status.ok()) { + result.status = TestStatus::kPassed; + result.error_message = absl::StrFormat( + "ROM loaded from file: %s (%zu bytes)", + test_rom.title().c_str(), test_rom.size()); + } else { + result.status = TestStatus::kFailed; + result.error_message = "ROM loading failed: " + std::string(status.message()); + } + } else if (skip_missing_rom_) { + result.status = TestStatus::kSkipped; + result.error_message = "No current ROM and file not found: " + rom_path; } else { result.status = TestStatus::kFailed; - result.error_message = "ROM loading failed: " + std::string(status.message()); + result.error_message = "No current ROM and required file not found: " + rom_path; } - } else if (skip_missing_rom_) { - result.status = TestStatus::kSkipped; - result.error_message = "ROM file not found: " + rom_path; - } else { - result.status = TestStatus::kFailed; - result.error_message = "Required ROM file not found: " + rom_path; } } catch (const std::exception& e) { diff --git a/src/app/test/rom_dependent_test_suite.h b/src/app/test/rom_dependent_test_suite.h new file mode 100644 index 00000000..fd080628 --- /dev/null +++ b/src/app/test/rom_dependent_test_suite.h @@ -0,0 +1,343 @@ +#ifndef YAZE_APP_TEST_ROM_DEPENDENT_TEST_SUITE_H +#define YAZE_APP_TEST_ROM_DEPENDENT_TEST_SUITE_H + +#include +#include +#include + +#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( + 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( + 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( + 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( + 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( + 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( + 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 diff --git a/src/app/test/test_manager.cc b/src/app/test/test_manager.cc index 7ffce0a8..5d079ffd 100644 --- a/src/app/test/test_manager.cc +++ b/src/app/test/test_manager.cc @@ -1,7 +1,9 @@ #include "app/test/test_manager.h" #include "absl/strings/str_format.h" +#include "absl/strings/str_cat.h" #include "app/gfx/arena.h" +#include "app/gui/icons.h" #include "imgui/imgui.h" #ifdef YAZE_ENABLE_IMGUI_TEST_ENGINE @@ -274,6 +276,17 @@ void TestManager::DrawTestDashboard() { 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 if (ImGui::BeginMenuBar()) { if (ImGui::BeginMenu("Run")) { @@ -321,25 +334,46 @@ void TestManager::DrawTestDashboard() { // Enhanced test execution status if (is_running_) { 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::ProgressBar(progress_, ImVec2(-1, 0), absl::StrFormat("%.0f%%", progress_ * 100.0f).c_str()); } else { // Enhanced control buttons 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(); } ImGui::PopStyleColor(); 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); } 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(); } } @@ -349,7 +383,7 @@ void TestManager::DrawTestDashboard() { // Enhanced test results summary with better visuals if (last_results_.total_tests > 0) { // Test summary header - ImGui::Text("๐Ÿ“Š Test Results Summary"); + ImGui::Text("%s Test Results Summary", ICON_MD_ASSESSMENT); // Progress bar showing pass rate float pass_rate = last_results_.GetPassRate(); @@ -363,18 +397,18 @@ void TestManager::DrawTestDashboard() { ImGui::PopStyleColor(); // 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::TextColored(GetTestStatusColor(TestStatus::kPassed), - "โœ… %zu", last_results_.passed_tests); + "%s %zu", ICON_MD_CHECK_CIRCLE, last_results_.passed_tests); ImGui::SameLine(); ImGui::TextColored(GetTestStatusColor(TestStatus::kFailed), - "โŒ %zu", last_results_.failed_tests); + "%s %zu", ICON_MD_ERROR, last_results_.failed_tests); ImGui::SameLine(); 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 if (ImGui::CollapsingHeader("Test Suite Breakdown")) { @@ -399,7 +433,7 @@ void TestManager::DrawTestDashboard() { ImGui::Separator(); // Enhanced test filter with category selection - ImGui::Text("๐Ÿ” Filter & View Options"); + ImGui::Text("%s Filter & View Options", ICON_MD_FILTER_LIST); // Category filter const char* categories[] = {"All", "Unit", "Integration", "UI", "Performance", "Memory"}; @@ -449,12 +483,12 @@ void TestManager::DrawTestDashboard() { ImGui::PushID(&result); // Status icon and test name - const char* status_icon = "โ“"; + const char* status_icon = ICON_MD_HELP; switch (result.status) { - case TestStatus::kPassed: status_icon = "โœ…"; break; - case TestStatus::kFailed: status_icon = "โŒ"; break; - case TestStatus::kSkipped: status_icon = "โญ๏ธ"; break; - case TestStatus::kRunning: status_icon = "โšก"; break; + case TestStatus::kPassed: status_icon = ICON_MD_CHECK_CIRCLE; break; + case TestStatus::kFailed: status_icon = ICON_MD_ERROR; break; + case TestStatus::kSkipped: status_icon = ICON_MD_SKIP_NEXT; break; + case TestStatus::kRunning: status_icon = ICON_MD_PLAY_CIRCLE_FILLED; break; default: break; } @@ -475,7 +509,7 @@ void TestManager::DrawTestDashboard() { if (result.status == TestStatus::kFailed && !result.error_message.empty()) { ImGui::Indent(); 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::Unindent(); } @@ -484,7 +518,7 @@ void TestManager::DrawTestDashboard() { if (result.status == TestStatus::kPassed && !result.error_message.empty()) { ImGui::Indent(); 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::Unindent(); } @@ -499,14 +533,14 @@ void TestManager::DrawTestDashboard() { // Resource monitor window 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()) { const auto& latest = resource_history_.back(); - ImGui::Text("Textures: %zu", latest.texture_count); - ImGui::Text("Surfaces: %zu", latest.surface_count); - ImGui::Text("Memory: %zu MB", latest.memory_usage_mb); - ImGui::Text("FPS: %.1f", latest.frame_rate); + ImGui::Text("%s Textures: %zu", ICON_MD_TEXTURE, latest.texture_count); + ImGui::Text("%s Surfaces: %zu", ICON_MD_LAYERS, latest.surface_count); + ImGui::Text("%s Memory: %zu MB", ICON_MD_MEMORY, latest.memory_usage_mb); + ImGui::Text("%s FPS: %.1f", ICON_MD_SPEED, latest.frame_rate); // Simple plot of resource usage over time if (resource_history_.size() > 1) { diff --git a/src/app/test/test_manager.h b/src/app/test/test_manager.h index f693b16e..b2eac100 100644 --- a/src/app/test/test_manager.h +++ b/src/app/test/test_manager.h @@ -1,13 +1,14 @@ #ifndef YAZE_APP_TEST_TEST_MANAGER_H #define YAZE_APP_TEST_TEST_MANAGER_H +#include #include #include -#include #include -#include +#include #include "absl/status/status.h" +#include "app/rom.h" #include "imgui/imgui.h" #ifdef YAZE_ENABLE_IMGUI_TEST_ENGINE @@ -21,22 +22,10 @@ namespace yaze { namespace test { // Test execution status -enum class TestStatus { - kNotRun, - kRunning, - kPassed, - kFailed, - kSkipped -}; +enum class TestStatus { kNotRun, kRunning, kPassed, kFailed, kSkipped }; // Test categories for organization -enum class TestCategory { - kUnit, - kIntegration, - kUI, - kPerformance, - kMemory -}; +enum class TestCategory { kUnit, kIntegration, kUI, kPerformance, kMemory }; // Individual test result struct TestResult { @@ -57,27 +46,35 @@ struct TestResults { size_t failed_tests = 0; size_t skipped_tests = 0; std::chrono::milliseconds total_duration{0}; - + void AddResult(const TestResult& result) { individual_results.push_back(result); total_tests++; switch (result.status) { - case TestStatus::kPassed: passed_tests++; break; - case TestStatus::kFailed: failed_tests++; break; - case TestStatus::kSkipped: skipped_tests++; break; - default: break; + case TestStatus::kPassed: + passed_tests++; + break; + case TestStatus::kFailed: + failed_tests++; + break; + case TestStatus::kSkipped: + skipped_tests++; + break; + default: + break; } total_duration += result.duration; } - + void Clear() { individual_results.clear(); total_tests = passed_tests = failed_tests = skipped_tests = 0; total_duration = std::chrono::milliseconds{0}; } - + float GetPassRate() const { - return total_tests > 0 ? static_cast(passed_tests) / total_tests : 0.0f; + return total_tests > 0 ? static_cast(passed_tests) / total_tests + : 0.0f; } }; @@ -91,7 +88,7 @@ class TestSuite { virtual void DrawConfiguration() {} virtual bool IsEnabled() const { return enabled_; } virtual void SetEnabled(bool enabled) { enabled_ = enabled; } - + protected: bool enabled_ = true; }; @@ -109,41 +106,40 @@ struct ResourceStats { class TestManager { public: static TestManager& Get(); - + // Core test execution absl::Status RunAllTests(); absl::Status RunTestsByCategory(TestCategory category); absl::Status RunTestSuite(const std::string& suite_name); - + // Test suite management void RegisterTestSuite(std::unique_ptr suite); std::vector GetTestSuiteNames() const; TestSuite* GetTestSuite(const std::string& name); - + // Results access const TestResults& GetLastResults() const { return last_results_; } void ClearResults() { last_results_.Clear(); } - + // Configuration - void SetMaxConcurrentTests(size_t max_concurrent) { - max_concurrent_tests_ = max_concurrent; + void SetMaxConcurrentTests(size_t max_concurrent) { + max_concurrent_tests_ = max_concurrent; } - void SetTestTimeout(std::chrono::seconds timeout) { - test_timeout_ = timeout; - } - + void SetTestTimeout(std::chrono::seconds timeout) { test_timeout_ = timeout; } + // Resource monitoring void UpdateResourceStats(); - const std::vector& GetResourceHistory() const { - return resource_history_; + const std::vector& GetResourceHistory() const { + return resource_history_; } - + // UI Testing (ImGui Test Engine integration) #ifdef YAZE_ENABLE_IMGUI_TEST_ENGINE ImGuiTestEngine* GetUITestEngine() { return ui_test_engine_; } void InitializeUITesting(); 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) #else void* GetUITestEngine() { return nullptr; } @@ -152,54 +148,61 @@ class TestManager { void DestroyUITestingContext() {} void ShutdownUITesting() {} #endif - + // Status queries bool IsTestRunning() const { return is_running_; } const std::string& GetCurrentTestName() const { return current_test_name_; } float GetProgress() const { return progress_; } - + // UI Interface void DrawTestDashboard(); - + + // ROM-dependent testing + void SetCurrentRom(Rom* rom) { current_rom_ = rom; } + Rom* GetCurrentRom() const { return current_rom_; } + private: TestManager(); ~TestManager(); - + // Test execution helpers absl::Status ExecuteTestSuite(TestSuite* suite); void UpdateProgress(); - + // Resource monitoring helpers void CollectResourceStats(); void TrimResourceHistory(); - + // Member variables std::vector> test_suites_; std::unordered_map suite_lookup_; - + TestResults last_results_; bool is_running_ = false; std::string current_test_name_; float progress_ = 0.0f; - + // Configuration size_t max_concurrent_tests_ = 1; std::chrono::seconds test_timeout_{30}; - + // Resource monitoring std::vector resource_history_; static constexpr size_t kMaxResourceHistorySize = 1000; - + // UI Testing #ifdef YAZE_ENABLE_IMGUI_TEST_ENGINE ImGuiTestEngine* ui_test_engine_ = nullptr; #endif - + // UI State bool show_dashboard_ = false; bool show_resource_monitor_ = false; std::string test_filter_; TestCategory category_filter_ = TestCategory::kUnit; + + // ROM-dependent testing + Rom* current_rom_ = nullptr; }; // Utility functions for test result formatting