Enhance testing framework and UI integration for YAZE

- Added a comprehensive testing framework with support for unit, integration, and UI tests, improving overall test coverage and reliability.
- Integrated ImGui Test Engine for UI testing, allowing for real-time feedback and visualization of test results.
- Updated CMake configuration to conditionally include testing components based on build options, enhancing flexibility for developers.
- Introduced a new command in the CLI for running asset loading tests on ROMs, providing a straightforward way to validate functionality.
- Enhanced error handling and resource management during testing, ensuring stability and clarity in test execution.
- Improved user interface with a dedicated test dashboard for monitoring test progress and results, enhancing developer experience.
This commit is contained in:
scawful
2025-09-25 13:26:56 -04:00
parent 77ceb0256b
commit 41adb1b70e
21 changed files with 1406 additions and 25 deletions

View File

@@ -4,15 +4,21 @@
#include <map>
#include <memory>
#include <SDL.h>
#include "absl/flags/flag.h"
#include "absl/flags/parse.h"
#include "absl/flags/usage.h"
#include "absl/strings/str_format.h"
#include "absl/strings/str_join.h"
#include "absl/strings/str_cat.h"
#include "cli/z3ed.h"
#include "cli/tui.h"
#include "app/core/asar_wrapper.h"
#include "app/gfx/arena.h"
#include "app/rom.h"
#include "app/zelda3/overworld/overworld.h"
// Global flags
ABSL_FLAG(bool, tui, false, "Launch the Text User Interface");
@@ -96,6 +102,15 @@ class ModernCLI {
}
};
commands_["test"] = {
.name = "test",
.description = "Run comprehensive asset loading tests on ROM",
.usage = "z3ed test [--rom=<rom_file>] [--graphics] [--overworld] [--dungeons]",
.handler = [this](const std::vector<std::string>& args) -> absl::Status {
return HandleTestCommand(args);
}
};
commands_["help"] = {
.name = "help",
.description = "Show help information",
@@ -273,6 +288,142 @@ class ModernCLI {
return absl::UnimplementedError("Address conversion functionality");
}
absl::Status HandleTestCommand(const std::vector<std::string>& args) {
std::string rom_file = absl::GetFlag(FLAGS_rom);
if (args.size() > 0 && args[0].find("--rom=") == 0) {
rom_file = args[0].substr(6);
}
if (rom_file.empty()) {
rom_file = "zelda3.sfc"; // Default ROM file
}
std::cout << "🧪 YAZE Asset Loading Test Suite" << std::endl;
std::cout << "ROM: " << rom_file << std::endl;
std::cout << "=================================" << std::endl;
// Initialize SDL for graphics tests
if (SDL_Init(SDL_INIT_VIDEO) != 0) {
return absl::InternalError(absl::StrCat("Failed to initialize SDL: ", SDL_GetError()));
}
int tests_passed = 0;
int tests_total = 0;
// Test 1: ROM Loading
std::cout << "📁 Testing ROM loading..." << std::flush;
tests_total++;
Rom test_rom;
auto status = test_rom.LoadFromFile(rom_file);
if (status.ok()) {
std::cout << " ✅ PASSED" << std::endl;
tests_passed++;
std::cout << " Title: " << test_rom.title() << std::endl;
std::cout << " Size: " << test_rom.size() << " bytes" << std::endl;
} else {
std::cout << " ❌ FAILED: " << status.message() << std::endl;
SDL_Quit();
return status;
}
// Test 2: Graphics Arena Resource Tracking
std::cout << "🎨 Testing graphics arena..." << std::flush;
tests_total++;
try {
auto& arena = gfx::Arena::Get();
size_t initial_textures = arena.GetTextureCount();
size_t initial_surfaces = arena.GetSurfaceCount();
std::cout << " ✅ PASSED" << std::endl;
std::cout << " Initial textures: " << initial_textures << std::endl;
std::cout << " Initial surfaces: " << initial_surfaces << std::endl;
tests_passed++;
} catch (const std::exception& e) {
std::cout << " ❌ FAILED: " << e.what() << std::endl;
}
// Test 3: Graphics Data Loading
bool test_graphics = true;
for (const auto& arg : args) {
if (arg == "--no-graphics") test_graphics = false;
}
if (test_graphics) {
std::cout << "🖼️ Testing graphics data loading..." << std::flush;
tests_total++;
try {
auto graphics_result = LoadAllGraphicsData(test_rom);
if (graphics_result.ok()) {
std::cout << " ✅ PASSED" << std::endl;
std::cout << " Loaded " << graphics_result.value().size() << " graphics sheets" << std::endl;
tests_passed++;
} else {
std::cout << " ❌ FAILED: " << graphics_result.status().message() << std::endl;
}
} catch (const std::exception& e) {
std::cout << " ❌ FAILED: " << e.what() << std::endl;
}
}
// Test 4: Overworld Loading
bool test_overworld = true;
for (const auto& arg : args) {
if (arg == "--no-overworld") test_overworld = false;
}
if (test_overworld) {
std::cout << "🗺️ Testing overworld loading..." << std::flush;
tests_total++;
try {
zelda3::Overworld overworld(&test_rom);
auto ow_status = overworld.Load(&test_rom);
if (ow_status.ok()) {
std::cout << " ✅ PASSED" << std::endl;
std::cout << " Loaded overworld data successfully" << std::endl;
tests_passed++;
} else {
std::cout << " ❌ FAILED: " << ow_status.message() << std::endl;
}
} catch (const std::exception& e) {
std::cout << " ❌ FAILED: " << e.what() << std::endl;
}
}
// Test 5: Arena Shutdown Test
std::cout << "🔄 Testing arena shutdown..." << std::flush;
tests_total++;
try {
auto& arena = gfx::Arena::Get();
size_t final_textures = arena.GetTextureCount();
size_t final_surfaces = arena.GetSurfaceCount();
// Test the shutdown method (this should not crash)
arena.Shutdown();
std::cout << " ✅ PASSED" << std::endl;
std::cout << " Final textures: " << final_textures << std::endl;
std::cout << " Final surfaces: " << final_surfaces << std::endl;
tests_passed++;
} catch (const std::exception& e) {
std::cout << " ❌ FAILED: " << e.what() << std::endl;
}
// Cleanup
SDL_Quit();
// Summary
std::cout << "=================================" << std::endl;
std::cout << "📊 Test Results: " << tests_passed << "/" << tests_total << " passed" << std::endl;
if (tests_passed == tests_total) {
std::cout << "🎉 All tests passed!" << std::endl;
return absl::OkStatus();
} else {
std::cout << "❌ Some tests failed." << std::endl;
return absl::InternalError("Test failures detected");
}
}
absl::Status HandleHelpCommand(const std::vector<std::string>& args) {
std::string command = args.empty() ? "" : args[0];
ShowHelp(command);