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:
@@ -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
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
343
src/app/test/rom_dependent_test_suite.h
Normal file
343
src/app/test/rom_dependent_test_suite.h
Normal 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
|
||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user