fix: apply clang-format to all source files
Fixes formatting violations that were causing CI failures. Applied clang-format-14 to ensure consistent code formatting across the codebase. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -3,74 +3,76 @@
|
||||
#include "app/controller.h"
|
||||
#include "test_utils.h"
|
||||
|
||||
void E2ETest_CanvasSelectionTest(ImGuiTestContext* ctx)
|
||||
{
|
||||
yaze::test::gui::LoadRomInTest(ctx, "zelda3.sfc");
|
||||
yaze::Controller* controller = (yaze::Controller*)ctx->Test->UserData;
|
||||
yaze::zelda3::Overworld* overworld = controller->overworld();
|
||||
void E2ETest_CanvasSelectionTest(ImGuiTestContext* ctx) {
|
||||
yaze::test::gui::LoadRomInTest(ctx, "zelda3.sfc");
|
||||
yaze::Controller* controller = (yaze::Controller*)ctx->Test->UserData;
|
||||
yaze::zelda3::Overworld* overworld = controller->overworld();
|
||||
|
||||
// 1. Open the Overworld Editor
|
||||
yaze::test::gui::OpenEditorInTest(ctx, "Overworld Editor");
|
||||
// 1. Open the Overworld Editor
|
||||
yaze::test::gui::OpenEditorInTest(ctx, "Overworld Editor");
|
||||
|
||||
// 2. Find the canvas
|
||||
ctx->WindowFocus("Overworld Editor");
|
||||
ctx->ItemClick("##Canvas");
|
||||
// 2. Find the canvas
|
||||
ctx->WindowFocus("Overworld Editor");
|
||||
ctx->ItemClick("##Canvas");
|
||||
|
||||
// 3. Get the original tile data
|
||||
// We'll check the 2x2 tile area at the paste location (600, 300)
|
||||
// The tile at (600, 300) is at (75, 37) in tile coordinates.
|
||||
// The overworld map is 128x128 tiles.
|
||||
uint16_t orig_tile1 = overworld->GetTile(75, 37);
|
||||
uint16_t orig_tile2 = overworld->GetTile(76, 37);
|
||||
uint16_t orig_tile3 = overworld->GetTile(75, 38);
|
||||
uint16_t orig_tile4 = overworld->GetTile(76, 38);
|
||||
// 3. Get the original tile data
|
||||
// We'll check the 2x2 tile area at the paste location (600, 300)
|
||||
// The tile at (600, 300) is at (75, 37) in tile coordinates.
|
||||
// The overworld map is 128x128 tiles.
|
||||
uint16_t orig_tile1 = overworld->GetTile(75, 37);
|
||||
uint16_t orig_tile2 = overworld->GetTile(76, 37);
|
||||
uint16_t orig_tile3 = overworld->GetTile(75, 38);
|
||||
uint16_t orig_tile4 = overworld->GetTile(76, 38);
|
||||
|
||||
// 4. Perform a rectangle selection that crosses a 512px boundary
|
||||
// The canvas is 1024x1024, with the top-left at (0,0).
|
||||
// We'll select a 2x2 tile area from (510, 256) to (514, 258).
|
||||
// This will cross the 512px boundary.
|
||||
ctx->MouseMoveToPos(ImVec2(510, 256));
|
||||
ctx->MouseDown(0);
|
||||
ctx->MouseMoveToPos(ImVec2(514, 258));
|
||||
ctx->MouseUp(0);
|
||||
// 4. Perform a rectangle selection that crosses a 512px boundary
|
||||
// The canvas is 1024x1024, with the top-left at (0,0).
|
||||
// We'll select a 2x2 tile area from (510, 256) to (514, 258).
|
||||
// This will cross the 512px boundary.
|
||||
ctx->MouseMoveToPos(ImVec2(510, 256));
|
||||
ctx->MouseDown(0);
|
||||
ctx->MouseMoveToPos(ImVec2(514, 258));
|
||||
ctx->MouseUp(0);
|
||||
|
||||
// 5. Copy the selection
|
||||
ctx->KeyDown(ImGuiKey_LeftCtrl);
|
||||
ctx->KeyPress(ImGuiKey_C);
|
||||
ctx->KeyUp(ImGuiKey_LeftCtrl);
|
||||
// 5. Copy the selection
|
||||
ctx->KeyDown(ImGuiKey_LeftCtrl);
|
||||
ctx->KeyPress(ImGuiKey_C);
|
||||
ctx->KeyUp(ImGuiKey_LeftCtrl);
|
||||
|
||||
// 6. Paste the selection
|
||||
ctx->MouseMoveToPos(ImVec2(600, 300));
|
||||
ctx->KeyDown(ImGuiKey_LeftCtrl);
|
||||
ctx->KeyPress(ImGuiKey_V);
|
||||
ctx->KeyUp(ImGuiKey_LeftCtrl);
|
||||
// 6. Paste the selection
|
||||
ctx->MouseMoveToPos(ImVec2(600, 300));
|
||||
ctx->KeyDown(ImGuiKey_LeftCtrl);
|
||||
ctx->KeyPress(ImGuiKey_V);
|
||||
ctx->KeyUp(ImGuiKey_LeftCtrl);
|
||||
|
||||
// 7. Verify that the pasted tiles are correct
|
||||
uint16_t new_tile1 = overworld->GetTile(75, 37);
|
||||
uint16_t new_tile2 = overworld->GetTile(76, 37);
|
||||
uint16_t new_tile3 = overworld->GetTile(75, 38);
|
||||
uint16_t new_tile4 = overworld->GetTile(76, 38);
|
||||
// 7. Verify that the pasted tiles are correct
|
||||
uint16_t new_tile1 = overworld->GetTile(75, 37);
|
||||
uint16_t new_tile2 = overworld->GetTile(76, 37);
|
||||
uint16_t new_tile3 = overworld->GetTile(75, 38);
|
||||
uint16_t new_tile4 = overworld->GetTile(76, 38);
|
||||
|
||||
// The bug is that the selection wraps around, so the pasted tiles are incorrect.
|
||||
// We expect the new tiles to be different from the original tiles.
|
||||
IM_CHECK_NE(orig_tile1, new_tile1);
|
||||
IM_CHECK_NE(orig_tile2, new_tile2);
|
||||
IM_CHECK_NE(orig_tile3, new_tile3);
|
||||
IM_CHECK_NE(orig_tile4, new_tile4);
|
||||
// The bug is that the selection wraps around, so the pasted tiles are incorrect.
|
||||
// We expect the new tiles to be different from the original tiles.
|
||||
IM_CHECK_NE(orig_tile1, new_tile1);
|
||||
IM_CHECK_NE(orig_tile2, new_tile2);
|
||||
IM_CHECK_NE(orig_tile3, new_tile3);
|
||||
IM_CHECK_NE(orig_tile4, new_tile4);
|
||||
|
||||
// We also expect the pasted tiles to be the same as the selected tiles.
|
||||
// The selected tiles are at (63, 32) and (64, 32), (63, 33) and (64, 33).
|
||||
uint16_t selected_tile1 = overworld->GetTile(63, 32);
|
||||
uint16_t selected_tile2 = overworld->GetTile(64, 32);
|
||||
uint16_t selected_tile3 = overworld->GetTile(63, 33);
|
||||
uint16_t selected_tile4 = overworld->GetTile(64, 33);
|
||||
// We also expect the pasted tiles to be the same as the selected tiles.
|
||||
// The selected tiles are at (63, 32) and (64, 32), (63, 33) and (64, 33).
|
||||
uint16_t selected_tile1 = overworld->GetTile(63, 32);
|
||||
uint16_t selected_tile2 = overworld->GetTile(64, 32);
|
||||
uint16_t selected_tile3 = overworld->GetTile(63, 33);
|
||||
uint16_t selected_tile4 = overworld->GetTile(64, 33);
|
||||
|
||||
IM_CHECK_EQ(new_tile1, selected_tile1);
|
||||
IM_CHECK_EQ(new_tile2, selected_tile2);
|
||||
IM_CHECK_EQ(new_tile3, selected_tile3);
|
||||
IM_CHECK_EQ(new_tile4, selected_tile4);
|
||||
IM_CHECK_EQ(new_tile1, selected_tile1);
|
||||
IM_CHECK_EQ(new_tile2, selected_tile2);
|
||||
IM_CHECK_EQ(new_tile3, selected_tile3);
|
||||
IM_CHECK_EQ(new_tile4, selected_tile4);
|
||||
|
||||
ctx->LogInfo("Original tiles: %d, %d, %d, %d", orig_tile1, orig_tile2, orig_tile3, orig_tile4);
|
||||
ctx->LogInfo("Selected tiles: %d, %d, %d, %d", selected_tile1, selected_tile2, selected_tile3, selected_tile4);
|
||||
ctx->LogInfo("New tiles: %d, %d, %d, %d", new_tile1, new_tile2, new_tile3, new_tile4);
|
||||
ctx->LogInfo("Original tiles: %d, %d, %d, %d", orig_tile1, orig_tile2,
|
||||
orig_tile3, orig_tile4);
|
||||
ctx->LogInfo("Selected tiles: %d, %d, %d, %d", selected_tile1, selected_tile2,
|
||||
selected_tile3, selected_tile4);
|
||||
ctx->LogInfo("New tiles: %d, %d, %d, %d", new_tile1, new_tile2, new_tile3,
|
||||
new_tile4);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "e2e/dungeon_editor_smoke_test.h"
|
||||
#include "test_utils.h"
|
||||
#include "app/controller.h"
|
||||
#include "imgui_test_engine/imgui_te_context.h"
|
||||
#include "test_utils.h"
|
||||
|
||||
/**
|
||||
* @brief Quick smoke test for DungeonEditorV2
|
||||
@@ -11,114 +11,113 @@
|
||||
* - Room cards function correctly
|
||||
* - Basic navigation works
|
||||
*/
|
||||
void E2ETest_DungeonEditorV2SmokeTest(ImGuiTestContext* ctx)
|
||||
{
|
||||
ctx->LogInfo("=== Starting DungeonEditorV2 Smoke Test ===");
|
||||
|
||||
// Load ROM first
|
||||
ctx->LogInfo("Loading ROM...");
|
||||
yaze::test::gui::LoadRomInTest(ctx, "zelda3.sfc");
|
||||
ctx->LogInfo("ROM loaded successfully");
|
||||
|
||||
// Open the Dungeon Editor
|
||||
ctx->LogInfo("Opening Dungeon Editor...");
|
||||
yaze::test::gui::OpenEditorInTest(ctx, "Dungeon");
|
||||
ctx->LogInfo("Dungeon Editor opened");
|
||||
|
||||
// Test 1: Control Panel Access
|
||||
ctx->LogInfo("--- Test 1: Control Panel ---");
|
||||
if (ctx->WindowInfo("Dungeon Controls").Window != nullptr) {
|
||||
ctx->WindowFocus("Dungeon Controls");
|
||||
ctx->LogInfo("Dungeon Controls panel is visible");
|
||||
} else {
|
||||
ctx->LogWarning("Dungeon Controls panel not visible - may be minimized");
|
||||
}
|
||||
|
||||
// Test 2: Open Room Selector Card
|
||||
ctx->LogInfo("--- Test 2: Room Selector Card ---");
|
||||
if (ctx->WindowInfo("Dungeon Controls").Window != nullptr) {
|
||||
ctx->SetRef("Dungeon Controls");
|
||||
ctx->ItemClick("Rooms"); // Toggle checkbox
|
||||
ctx->Yield();
|
||||
ctx->LogInfo("Toggled Room Selector visibility");
|
||||
}
|
||||
|
||||
// Test 3: Open Room Matrix Card
|
||||
ctx->LogInfo("--- Test 3: Room Matrix Card ---");
|
||||
if (ctx->WindowInfo("Dungeon Controls").Window != nullptr) {
|
||||
ctx->SetRef("Dungeon Controls");
|
||||
ctx->ItemClick("Matrix"); // Toggle checkbox
|
||||
ctx->Yield();
|
||||
ctx->LogInfo("Toggled Room Matrix visibility");
|
||||
}
|
||||
|
||||
// Test 4: Open a Room Card
|
||||
ctx->LogInfo("--- Test 4: Room Card ---");
|
||||
// Try to open room 0 by clicking in room selector
|
||||
if (ctx->WindowInfo("Room Selector").Window != nullptr) {
|
||||
ctx->SetRef("Room Selector");
|
||||
// Look for selectable room items
|
||||
if (ctx->ItemExists("Room 0x00")) {
|
||||
ctx->ItemDoubleClick("Room 0x00");
|
||||
ctx->Yield(2);
|
||||
ctx->LogInfo("Opened Room 0x00 card");
|
||||
|
||||
// Verify room card exists
|
||||
if (ctx->WindowInfo("Room 0x00").Window != nullptr) {
|
||||
ctx->LogInfo("Room 0x00 card successfully opened");
|
||||
ctx->SetRef("Room 0x00");
|
||||
|
||||
// Test 5: Per-Room Layer Controls
|
||||
ctx->LogInfo("--- Test 5: Per-Room Layer Controls ---");
|
||||
if (ctx->ItemExists("Show BG1")) {
|
||||
ctx->LogInfo("Found per-room BG1 control");
|
||||
// Toggle it
|
||||
ctx->ItemClick("Show BG1");
|
||||
ctx->Yield();
|
||||
ctx->ItemClick("Show BG1"); // Toggle back
|
||||
ctx->Yield();
|
||||
ctx->LogInfo("Per-room layer controls functional");
|
||||
}
|
||||
} else {
|
||||
ctx->LogWarning("Room card did not open");
|
||||
}
|
||||
} else {
|
||||
ctx->LogWarning("Room 0x00 not found in selector");
|
||||
void E2ETest_DungeonEditorV2SmokeTest(ImGuiTestContext* ctx) {
|
||||
ctx->LogInfo("=== Starting DungeonEditorV2 Smoke Test ===");
|
||||
|
||||
// Load ROM first
|
||||
ctx->LogInfo("Loading ROM...");
|
||||
yaze::test::gui::LoadRomInTest(ctx, "zelda3.sfc");
|
||||
ctx->LogInfo("ROM loaded successfully");
|
||||
|
||||
// Open the Dungeon Editor
|
||||
ctx->LogInfo("Opening Dungeon Editor...");
|
||||
yaze::test::gui::OpenEditorInTest(ctx, "Dungeon");
|
||||
ctx->LogInfo("Dungeon Editor opened");
|
||||
|
||||
// Test 1: Control Panel Access
|
||||
ctx->LogInfo("--- Test 1: Control Panel ---");
|
||||
if (ctx->WindowInfo("Dungeon Controls").Window != nullptr) {
|
||||
ctx->WindowFocus("Dungeon Controls");
|
||||
ctx->LogInfo("Dungeon Controls panel is visible");
|
||||
} else {
|
||||
ctx->LogWarning("Dungeon Controls panel not visible - may be minimized");
|
||||
}
|
||||
|
||||
// Test 2: Open Room Selector Card
|
||||
ctx->LogInfo("--- Test 2: Room Selector Card ---");
|
||||
if (ctx->WindowInfo("Dungeon Controls").Window != nullptr) {
|
||||
ctx->SetRef("Dungeon Controls");
|
||||
ctx->ItemClick("Rooms"); // Toggle checkbox
|
||||
ctx->Yield();
|
||||
ctx->LogInfo("Toggled Room Selector visibility");
|
||||
}
|
||||
|
||||
// Test 3: Open Room Matrix Card
|
||||
ctx->LogInfo("--- Test 3: Room Matrix Card ---");
|
||||
if (ctx->WindowInfo("Dungeon Controls").Window != nullptr) {
|
||||
ctx->SetRef("Dungeon Controls");
|
||||
ctx->ItemClick("Matrix"); // Toggle checkbox
|
||||
ctx->Yield();
|
||||
ctx->LogInfo("Toggled Room Matrix visibility");
|
||||
}
|
||||
|
||||
// Test 4: Open a Room Card
|
||||
ctx->LogInfo("--- Test 4: Room Card ---");
|
||||
// Try to open room 0 by clicking in room selector
|
||||
if (ctx->WindowInfo("Room Selector").Window != nullptr) {
|
||||
ctx->SetRef("Room Selector");
|
||||
// Look for selectable room items
|
||||
if (ctx->ItemExists("Room 0x00")) {
|
||||
ctx->ItemDoubleClick("Room 0x00");
|
||||
ctx->Yield(2);
|
||||
ctx->LogInfo("Opened Room 0x00 card");
|
||||
|
||||
// Verify room card exists
|
||||
if (ctx->WindowInfo("Room 0x00").Window != nullptr) {
|
||||
ctx->LogInfo("Room 0x00 card successfully opened");
|
||||
ctx->SetRef("Room 0x00");
|
||||
|
||||
// Test 5: Per-Room Layer Controls
|
||||
ctx->LogInfo("--- Test 5: Per-Room Layer Controls ---");
|
||||
if (ctx->ItemExists("Show BG1")) {
|
||||
ctx->LogInfo("Found per-room BG1 control");
|
||||
// Toggle it
|
||||
ctx->ItemClick("Show BG1");
|
||||
ctx->Yield();
|
||||
ctx->ItemClick("Show BG1"); // Toggle back
|
||||
ctx->Yield();
|
||||
ctx->LogInfo("Per-room layer controls functional");
|
||||
}
|
||||
} else {
|
||||
ctx->LogWarning("Room card did not open");
|
||||
}
|
||||
} else {
|
||||
ctx->LogWarning("Room Selector card not visible");
|
||||
ctx->LogWarning("Room 0x00 not found in selector");
|
||||
}
|
||||
|
||||
// Test 6: Object Editor Card
|
||||
ctx->LogInfo("--- Test 6: Object Editor Card ---");
|
||||
if (ctx->WindowInfo("Dungeon Controls").Window != nullptr) {
|
||||
ctx->SetRef("Dungeon Controls");
|
||||
ctx->ItemClick("Objects"); // Toggle checkbox
|
||||
ctx->Yield();
|
||||
ctx->LogInfo("Toggled Object Editor visibility");
|
||||
}
|
||||
|
||||
// Test 7: Palette Editor Card
|
||||
ctx->LogInfo("--- Test 7: Palette Editor Card ---");
|
||||
if (ctx->WindowInfo("Dungeon Controls").Window != nullptr) {
|
||||
ctx->SetRef("Dungeon Controls");
|
||||
ctx->ItemClick("Palette"); // Toggle checkbox
|
||||
ctx->Yield();
|
||||
ctx->LogInfo("Toggled Palette Editor visibility");
|
||||
}
|
||||
|
||||
// Test 8: Independent Cards can be closed
|
||||
ctx->LogInfo("--- Test 8: Close Independent Cards ---");
|
||||
// Close room card if it's open
|
||||
if (ctx->WindowInfo("Room 0x00").Window != nullptr) {
|
||||
ctx->WindowClose("Room 0x00");
|
||||
ctx->Yield();
|
||||
ctx->LogInfo("Closed Room 0x00 card");
|
||||
}
|
||||
|
||||
// Final verification
|
||||
ctx->LogInfo("=== DungeonEditorV2 Smoke Test Completed Successfully ===");
|
||||
ctx->LogInfo("Card-based architecture is functional");
|
||||
ctx->LogInfo("Independent windows can be opened and closed");
|
||||
ctx->LogInfo("Per-room settings are accessible");
|
||||
} else {
|
||||
ctx->LogWarning("Room Selector card not visible");
|
||||
}
|
||||
|
||||
// Test 6: Object Editor Card
|
||||
ctx->LogInfo("--- Test 6: Object Editor Card ---");
|
||||
if (ctx->WindowInfo("Dungeon Controls").Window != nullptr) {
|
||||
ctx->SetRef("Dungeon Controls");
|
||||
ctx->ItemClick("Objects"); // Toggle checkbox
|
||||
ctx->Yield();
|
||||
ctx->LogInfo("Toggled Object Editor visibility");
|
||||
}
|
||||
|
||||
// Test 7: Palette Editor Card
|
||||
ctx->LogInfo("--- Test 7: Palette Editor Card ---");
|
||||
if (ctx->WindowInfo("Dungeon Controls").Window != nullptr) {
|
||||
ctx->SetRef("Dungeon Controls");
|
||||
ctx->ItemClick("Palette"); // Toggle checkbox
|
||||
ctx->Yield();
|
||||
ctx->LogInfo("Toggled Palette Editor visibility");
|
||||
}
|
||||
|
||||
// Test 8: Independent Cards can be closed
|
||||
ctx->LogInfo("--- Test 8: Close Independent Cards ---");
|
||||
// Close room card if it's open
|
||||
if (ctx->WindowInfo("Room 0x00").Window != nullptr) {
|
||||
ctx->WindowClose("Room 0x00");
|
||||
ctx->Yield();
|
||||
ctx->LogInfo("Closed Room 0x00 card");
|
||||
}
|
||||
|
||||
// Final verification
|
||||
ctx->LogInfo("=== DungeonEditorV2 Smoke Test Completed Successfully ===");
|
||||
ctx->LogInfo("Card-based architecture is functional");
|
||||
ctx->LogInfo("Independent windows can be opened and closed");
|
||||
ctx->LogInfo("Per-room settings are accessible");
|
||||
}
|
||||
|
||||
@@ -15,4 +15,3 @@
|
||||
void E2ETest_DungeonEditorV2SmokeTest(ImGuiTestContext* ctx);
|
||||
|
||||
#endif // YAZE_TEST_E2E_DUNGEON_EDITOR_SMOKE_TEST_H
|
||||
|
||||
|
||||
@@ -57,12 +57,12 @@
|
||||
#include "imgui_test_engine/imgui_te_ui.h"
|
||||
|
||||
#include "app/controller.h"
|
||||
#include "app/platform/window.h"
|
||||
#include "app/editor/dungeon/dungeon_editor_v2.h"
|
||||
#include "app/platform/window.h"
|
||||
#include "app/rom.h"
|
||||
#include "test_utils.h"
|
||||
#include "zelda3/dungeon/room.h"
|
||||
#include "zelda3/dungeon/room_object.h"
|
||||
#include "test_utils.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace test {
|
||||
@@ -78,24 +78,24 @@ class DungeonObjectRenderingE2ETests : public TestRomManager::BoundRomTest {
|
||||
|
||||
// Initialize test environment
|
||||
rom_ = std::shared_ptr<Rom>(rom(), [](Rom*) {});
|
||||
|
||||
|
||||
dungeon_editor_ = std::make_unique<editor::DungeonEditorV2>();
|
||||
dungeon_editor_->set_rom(rom_.get());
|
||||
ASSERT_TRUE(dungeon_editor_->Load().ok());
|
||||
|
||||
|
||||
// Initialize imgui test engine
|
||||
engine_ = ImGuiTestEngine_CreateContext();
|
||||
ImGuiTestEngineIO& test_io = ImGuiTestEngine_GetIO(engine_);
|
||||
test_io.ConfigVerboseLevel = ImGuiTestVerboseLevel_Info;
|
||||
test_io.ConfigVerboseLevelOnError = ImGuiTestVerboseLevel_Debug;
|
||||
test_io.ConfigRunSpeed = ImGuiTestRunSpeed_Fast;
|
||||
|
||||
|
||||
ImGuiTestEngine_Start(engine_, ImGui::GetCurrentContext());
|
||||
|
||||
|
||||
// Register all test cases
|
||||
RegisterAllTests();
|
||||
}
|
||||
|
||||
|
||||
void TearDown() override {
|
||||
if (engine_) {
|
||||
ImGuiTestEngine_Stop(engine_);
|
||||
@@ -106,9 +106,9 @@ class DungeonObjectRenderingE2ETests : public TestRomManager::BoundRomTest {
|
||||
rom_.reset();
|
||||
BoundRomTest::TearDown();
|
||||
}
|
||||
|
||||
|
||||
void RegisterAllTests();
|
||||
|
||||
|
||||
// Test registration helpers
|
||||
void RegisterObjectBrowserTests();
|
||||
void RegisterObjectPlacementTests();
|
||||
@@ -117,7 +117,7 @@ class DungeonObjectRenderingE2ETests : public TestRomManager::BoundRomTest {
|
||||
void RegisterSaveWorkflowTests();
|
||||
void RegisterRenderingQualityTests();
|
||||
void RegisterPerformanceTests();
|
||||
|
||||
|
||||
ImGuiTestEngine* engine_ = nullptr;
|
||||
std::shared_ptr<Rom> rom_;
|
||||
std::unique_ptr<editor::DungeonEditorV2> dungeon_editor_;
|
||||
@@ -136,7 +136,8 @@ class DungeonObjectRenderingE2ETests : public TestRomManager::BoundRomTest {
|
||||
* - Object list is scrollable
|
||||
*/
|
||||
void DungeonObjectRenderingE2ETests::RegisterObjectBrowserTests() {
|
||||
ImGuiTest* test = IM_REGISTER_TEST(engine_, "DungeonObjectRendering", "ObjectBrowser_NavigateCategories");
|
||||
ImGuiTest* test = IM_REGISTER_TEST(engine_, "DungeonObjectRendering",
|
||||
"ObjectBrowser_NavigateCategories");
|
||||
test->GuiFunc = [](ImGuiTestContext* ctx) {
|
||||
// Render dungeon editor UI
|
||||
auto* self = (DungeonObjectRenderingE2ETests*)ctx->UserData;
|
||||
@@ -145,26 +146,22 @@ void DungeonObjectRenderingE2ETests::RegisterObjectBrowserTests() {
|
||||
test->TestFunc = [](ImGuiTestContext* ctx) {
|
||||
// Open dungeon editor window
|
||||
ctx->SetRef("Dungeon Editor");
|
||||
|
||||
|
||||
// Navigate to object selector
|
||||
ctx->ItemClick("Object Selector##tab");
|
||||
ctx->Yield();
|
||||
|
||||
|
||||
// Test category tabs
|
||||
const char* categories[] = {
|
||||
"Type1##tab",
|
||||
"Type2##tab",
|
||||
"Type3##tab",
|
||||
"All##tab"
|
||||
};
|
||||
|
||||
const char* categories[] = {"Type1##tab", "Type2##tab", "Type3##tab",
|
||||
"All##tab"};
|
||||
|
||||
for (const char* category : categories) {
|
||||
ctx->ItemClick(category);
|
||||
ctx->Yield();
|
||||
|
||||
|
||||
// Verify object list is visible and has content
|
||||
ctx->ItemExists("AssetBrowser##child");
|
||||
|
||||
|
||||
// Try scrolling the list
|
||||
ctx->ItemClick("AssetBrowser##child");
|
||||
ctx->KeyPress(ImGuiKey_DownArrow, 5);
|
||||
@@ -182,32 +179,34 @@ void DungeonObjectRenderingE2ETests::RegisterObjectBrowserTests() {
|
||||
* - Preview updates when object selected
|
||||
* - Object details window shows correct info
|
||||
*/
|
||||
void RegisterObjectBrowserTests_SelectObject(DungeonObjectRenderingE2ETests* self) {
|
||||
ImGuiTest* test = IM_REGISTER_TEST(self->engine_, "DungeonObjectRendering", "ObjectBrowser_SelectObject");
|
||||
void RegisterObjectBrowserTests_SelectObject(
|
||||
DungeonObjectRenderingE2ETests* self) {
|
||||
ImGuiTest* test = IM_REGISTER_TEST(self->engine_, "DungeonObjectRendering",
|
||||
"ObjectBrowser_SelectObject");
|
||||
test->GuiFunc = [](ImGuiTestContext* ctx) {
|
||||
auto* self = (DungeonObjectRenderingE2ETests*)ctx->UserData;
|
||||
self->dungeon_editor_->Update();
|
||||
};
|
||||
test->TestFunc = [](ImGuiTestContext* ctx) {
|
||||
ctx->SetRef("Dungeon Editor");
|
||||
|
||||
|
||||
// Navigate to object selector
|
||||
ctx->ItemClick("Object Selector##tab");
|
||||
ctx->Yield();
|
||||
|
||||
|
||||
// Select Type1 category
|
||||
ctx->ItemClick("Type1##tab");
|
||||
ctx->Yield();
|
||||
|
||||
|
||||
// Click on first object in list (wall object 0x10)
|
||||
ctx->SetRef("AssetBrowser");
|
||||
ctx->ItemClick("Object_0x10");
|
||||
ctx->Yield();
|
||||
|
||||
|
||||
// Verify object details window appears
|
||||
ctx->SetRef("Object Details");
|
||||
ctx->ItemExists("Object ID: 0x10");
|
||||
|
||||
|
||||
// Verify preview canvas shows object
|
||||
ctx->SetRef("Dungeon Editor/PreviewCanvas");
|
||||
ctx->ItemExists("**/canvas##child");
|
||||
@@ -223,28 +222,30 @@ void RegisterObjectBrowserTests_SelectObject(DungeonObjectRenderingE2ETests* sel
|
||||
* - Filtering by ID works
|
||||
* - Clearing search restores full list
|
||||
*/
|
||||
void RegisterObjectBrowserTests_SearchFilter(DungeonObjectRenderingE2ETests* self) {
|
||||
ImGuiTest* test = IM_REGISTER_TEST(self->engine_, "DungeonObjectRendering", "ObjectBrowser_SearchFilter");
|
||||
void RegisterObjectBrowserTests_SearchFilter(
|
||||
DungeonObjectRenderingE2ETests* self) {
|
||||
ImGuiTest* test = IM_REGISTER_TEST(self->engine_, "DungeonObjectRendering",
|
||||
"ObjectBrowser_SearchFilter");
|
||||
test->GuiFunc = [](ImGuiTestContext* ctx) {
|
||||
auto* self = (DungeonObjectRenderingE2ETests*)ctx->UserData;
|
||||
self->dungeon_editor_->Update();
|
||||
};
|
||||
test->TestFunc = [](ImGuiTestContext* ctx) {
|
||||
ctx->SetRef("Dungeon Editor/Object Selector");
|
||||
|
||||
|
||||
// Type in search box
|
||||
ctx->ItemClick("Search##input");
|
||||
ctx->KeyCharsAppend("0x10");
|
||||
ctx->Yield();
|
||||
|
||||
|
||||
// Verify filtered results
|
||||
ctx->ItemExists("Object_0x10");
|
||||
ctx->ItemVerifyNotExists("Object_0x20");
|
||||
|
||||
|
||||
// Clear search
|
||||
ctx->ItemClick("Clear##button");
|
||||
ctx->Yield();
|
||||
|
||||
|
||||
// Verify full list restored
|
||||
ctx->ItemExists("Object_0x10");
|
||||
ctx->ItemExists("Object_0x20");
|
||||
@@ -266,44 +267,45 @@ void RegisterObjectBrowserTests_SearchFilter(DungeonObjectRenderingE2ETests* sel
|
||||
* - Canvas renders placed object
|
||||
*/
|
||||
void DungeonObjectRenderingE2ETests::RegisterObjectPlacementTests() {
|
||||
ImGuiTest* test = IM_REGISTER_TEST(engine_, "DungeonObjectRendering", "ObjectPlacement_MouseClick");
|
||||
ImGuiTest* test = IM_REGISTER_TEST(engine_, "DungeonObjectRendering",
|
||||
"ObjectPlacement_MouseClick");
|
||||
test->GuiFunc = [](ImGuiTestContext* ctx) {
|
||||
auto* self = (DungeonObjectRenderingE2ETests*)ctx->UserData;
|
||||
self->dungeon_editor_->Update();
|
||||
};
|
||||
test->TestFunc = [](ImGuiTestContext* ctx) {
|
||||
ctx->SetRef("Dungeon Editor");
|
||||
|
||||
|
||||
// Select an object (wall 0x10)
|
||||
ctx->ItemClick("Object Selector##tab");
|
||||
ctx->Yield();
|
||||
ctx->SetRef("AssetBrowser");
|
||||
ctx->ItemClick("Object_0x10");
|
||||
ctx->Yield();
|
||||
|
||||
|
||||
// Switch to main canvas
|
||||
ctx->SetRef("Dungeon Editor");
|
||||
ctx->ItemClick("Canvas##tab");
|
||||
ctx->Yield();
|
||||
|
||||
|
||||
// Click on canvas to place object
|
||||
ctx->SetRef("Dungeon Editor/Canvas");
|
||||
// TODO: fix this
|
||||
// ImVec2 canvas_center = ctx->ItemRectCenter("canvas##child");
|
||||
// ctx->MouseMove(canvas_center);
|
||||
// ctx->Yield();
|
||||
|
||||
|
||||
// Verify preview is visible
|
||||
// (Actual verification would check rendering)
|
||||
|
||||
|
||||
ctx->MouseClick();
|
||||
ctx->Yield();
|
||||
|
||||
|
||||
// Verify object was placed
|
||||
ctx->SetRef("Dungeon Editor");
|
||||
ctx->ItemClick("Room Objects##tab");
|
||||
ctx->Yield();
|
||||
|
||||
|
||||
// Check object appears in list
|
||||
ctx->ItemExists("Object ID: 0x10");
|
||||
};
|
||||
@@ -318,33 +320,35 @@ void DungeonObjectRenderingE2ETests::RegisterObjectPlacementTests() {
|
||||
* - Object positions align to grid
|
||||
* - Grid size can be changed
|
||||
*/
|
||||
void RegisterObjectPlacementTests_SnapToGrid(DungeonObjectRenderingE2ETests* self) {
|
||||
ImGuiTest* test = IM_REGISTER_TEST(self->engine_, "DungeonObjectRendering", "ObjectPlacement_SnapToGrid");
|
||||
void RegisterObjectPlacementTests_SnapToGrid(
|
||||
DungeonObjectRenderingE2ETests* self) {
|
||||
ImGuiTest* test = IM_REGISTER_TEST(self->engine_, "DungeonObjectRendering",
|
||||
"ObjectPlacement_SnapToGrid");
|
||||
test->GuiFunc = [](ImGuiTestContext* ctx) {
|
||||
auto* self = (DungeonObjectRenderingE2ETests*)ctx->UserData;
|
||||
self->dungeon_editor_->Update();
|
||||
};
|
||||
test->TestFunc = [](ImGuiTestContext* ctx) {
|
||||
ctx->SetRef("Dungeon Editor");
|
||||
|
||||
|
||||
// Enable snap to grid
|
||||
ctx->ItemClick("Options##menu");
|
||||
ctx->ItemClick("Snap to Grid##checkbox");
|
||||
ctx->Yield();
|
||||
|
||||
|
||||
// Select object
|
||||
ctx->ItemClick("Object Selector##tab");
|
||||
ctx->SetRef("AssetBrowser");
|
||||
ctx->ItemClick("Object_0x10");
|
||||
ctx->Yield();
|
||||
|
||||
|
||||
// Place object at arbitrary position
|
||||
ctx->SetRef("Dungeon Editor/Canvas");
|
||||
ImVec2 canvas_pos = ctx->ItemRectMin("canvas##child");
|
||||
ctx->MouseMove(ImVec2(canvas_pos.x + 37, canvas_pos.y + 49));
|
||||
ctx->MouseClick();
|
||||
ctx->Yield();
|
||||
|
||||
|
||||
// Verify object was placed at snapped position (32, 48)
|
||||
ctx->SetRef("Dungeon Editor/Object Details");
|
||||
ctx->ItemVerifyValue("X Position", 32);
|
||||
@@ -361,25 +365,27 @@ void RegisterObjectPlacementTests_SnapToGrid(DungeonObjectRenderingE2ETests* sel
|
||||
* - Each placement is independent
|
||||
* - All placed objects render correctly
|
||||
*/
|
||||
void RegisterObjectPlacementTests_MultipleObjects(DungeonObjectRenderingE2ETests* self) {
|
||||
ImGuiTest* test = IM_REGISTER_TEST(self->engine_, "DungeonObjectRendering", "ObjectPlacement_MultipleObjects");
|
||||
void RegisterObjectPlacementTests_MultipleObjects(
|
||||
DungeonObjectRenderingE2ETests* self) {
|
||||
ImGuiTest* test = IM_REGISTER_TEST(self->engine_, "DungeonObjectRendering",
|
||||
"ObjectPlacement_MultipleObjects");
|
||||
test->GuiFunc = [](ImGuiTestContext* ctx) {
|
||||
auto* self = (DungeonObjectRenderingE2ETests*)ctx->UserData;
|
||||
self->dungeon_editor_->Update();
|
||||
};
|
||||
test->TestFunc = [](ImGuiTestContext* ctx) {
|
||||
ctx->SetRef("Dungeon Editor");
|
||||
|
||||
|
||||
// Place 5 different objects
|
||||
const uint16_t object_ids[] = {0x10, 0x11, 0x20, 0x100, 0xF99};
|
||||
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
// Select object
|
||||
ctx->ItemClick("Object Selector##tab");
|
||||
ctx->SetRef("AssetBrowser");
|
||||
ctx->ItemClick(ImGuiTestRef_Str("Object_0x%02X", object_ids[i]));
|
||||
ctx->Yield();
|
||||
|
||||
|
||||
// Place at different position
|
||||
ctx->SetRef("Dungeon Editor/Canvas");
|
||||
ImVec2 canvas_pos = ctx->ItemRectMin("canvas##child");
|
||||
@@ -387,7 +393,7 @@ void RegisterObjectPlacementTests_MultipleObjects(DungeonObjectRenderingE2ETests
|
||||
ctx->MouseClick();
|
||||
ctx->Yield();
|
||||
}
|
||||
|
||||
|
||||
// Verify all 5 objects in room
|
||||
ctx->SetRef("Dungeon Editor/Room Objects");
|
||||
ctx->ItemExists("Object Count: 5");
|
||||
@@ -408,7 +414,8 @@ void RegisterObjectPlacementTests_MultipleObjects(DungeonObjectRenderingE2ETests
|
||||
* - Object details update
|
||||
*/
|
||||
void DungeonObjectRenderingE2ETests::RegisterObjectSelectionTests() {
|
||||
ImGuiTest* test = IM_REGISTER_TEST(engine_, "DungeonObjectRendering", "ObjectSelection_Click");
|
||||
ImGuiTest* test = IM_REGISTER_TEST(engine_, "DungeonObjectRendering",
|
||||
"ObjectSelection_Click");
|
||||
test->GuiFunc = [](ImGuiTestContext* ctx) {
|
||||
auto* self = (DungeonObjectRenderingE2ETests*)ctx->UserData;
|
||||
self->dungeon_editor_->Update();
|
||||
@@ -420,18 +427,18 @@ void DungeonObjectRenderingE2ETests::RegisterObjectSelectionTests() {
|
||||
ctx->SetRef("AssetBrowser");
|
||||
ctx->ItemClick("Object_0x10");
|
||||
ctx->Yield();
|
||||
|
||||
|
||||
ctx->SetRef("Dungeon Editor/Canvas");
|
||||
ImVec2 canvas_center = ctx->ItemRectCenter("canvas##child");
|
||||
ctx->MouseMove(canvas_center);
|
||||
ctx->MouseClick();
|
||||
ctx->Yield();
|
||||
|
||||
|
||||
// Now try to select it
|
||||
ctx->MouseMove(canvas_center);
|
||||
ctx->MouseClick();
|
||||
ctx->Yield();
|
||||
|
||||
|
||||
// Verify object is selected
|
||||
ctx->SetRef("Dungeon Editor/Object Details");
|
||||
ctx->ItemExists("Selected Object");
|
||||
@@ -448,8 +455,10 @@ void DungeonObjectRenderingE2ETests::RegisterObjectSelectionTests() {
|
||||
* - All objects in box are selected
|
||||
* - Selection count is correct
|
||||
*/
|
||||
void RegisterObjectSelectionTests_MultiSelect(DungeonObjectRenderingE2ETests* self) {
|
||||
ImGuiTest* test = IM_REGISTER_TEST(self->engine_, "DungeonObjectRendering", "ObjectSelection_MultiSelect");
|
||||
void RegisterObjectSelectionTests_MultiSelect(
|
||||
DungeonObjectRenderingE2ETests* self) {
|
||||
ImGuiTest* test = IM_REGISTER_TEST(self->engine_, "DungeonObjectRendering",
|
||||
"ObjectSelection_MultiSelect");
|
||||
test->GuiFunc = [](ImGuiTestContext* ctx) {
|
||||
auto* self = (DungeonObjectRenderingE2ETests*)ctx->UserData;
|
||||
self->dungeon_editor_->Update();
|
||||
@@ -462,14 +471,14 @@ void RegisterObjectSelectionTests_MultiSelect(DungeonObjectRenderingE2ETests* se
|
||||
ctx->SetRef("AssetBrowser");
|
||||
ctx->ItemClick("Object_0x10");
|
||||
ctx->Yield();
|
||||
|
||||
|
||||
ctx->SetRef("Dungeon Editor/Canvas");
|
||||
ImVec2 canvas_pos = ctx->ItemRectMin("canvas##child");
|
||||
ctx->MouseMove(ImVec2(canvas_pos.x + (i * 32) + 16, canvas_pos.y + 16));
|
||||
ctx->MouseClick();
|
||||
ctx->Yield();
|
||||
}
|
||||
|
||||
|
||||
// Ctrl+drag to select all
|
||||
ctx->KeyDown(ImGuiKey_LeftCtrl);
|
||||
ImVec2 canvas_pos = ctx->ItemRectMin("canvas##child");
|
||||
@@ -479,7 +488,7 @@ void RegisterObjectSelectionTests_MultiSelect(DungeonObjectRenderingE2ETests* se
|
||||
ctx->MouseUp();
|
||||
ctx->KeyUp(ImGuiKey_LeftCtrl);
|
||||
ctx->Yield();
|
||||
|
||||
|
||||
// Verify 3 objects selected
|
||||
ctx->SetRef("Dungeon Editor");
|
||||
ctx->ItemVerifyValue("Selected Objects", 3);
|
||||
@@ -495,8 +504,10 @@ void RegisterObjectSelectionTests_MultiSelect(DungeonObjectRenderingE2ETests* se
|
||||
* - Object position updates during drag
|
||||
* - Final position is correct
|
||||
*/
|
||||
void RegisterObjectSelectionTests_MoveObject(DungeonObjectRenderingE2ETests* self) {
|
||||
ImGuiTest* test = IM_REGISTER_TEST(self->engine_, "DungeonObjectRendering", "ObjectSelection_MoveObject");
|
||||
void RegisterObjectSelectionTests_MoveObject(
|
||||
DungeonObjectRenderingE2ETests* self) {
|
||||
ImGuiTest* test = IM_REGISTER_TEST(self->engine_, "DungeonObjectRendering",
|
||||
"ObjectSelection_MoveObject");
|
||||
test->GuiFunc = [](ImGuiTestContext* ctx) {
|
||||
auto* self = (DungeonObjectRenderingE2ETests*)ctx->UserData;
|
||||
self->dungeon_editor_->Update();
|
||||
@@ -508,14 +519,14 @@ void RegisterObjectSelectionTests_MoveObject(DungeonObjectRenderingE2ETests* sel
|
||||
ctx->SetRef("AssetBrowser");
|
||||
ctx->ItemClick("Object_0x10");
|
||||
ctx->Yield();
|
||||
|
||||
|
||||
ctx->SetRef("Dungeon Editor/Canvas");
|
||||
ImVec2 canvas_pos = ctx->ItemRectMin("canvas##child");
|
||||
ImVec2 initial_pos = ImVec2(canvas_pos.x + 16, canvas_pos.y + 16);
|
||||
ctx->MouseMove(initial_pos);
|
||||
ctx->MouseClick();
|
||||
ctx->Yield();
|
||||
|
||||
|
||||
// Select and drag to (48, 48)
|
||||
ctx->MouseMove(initial_pos);
|
||||
ctx->MouseClick();
|
||||
@@ -523,7 +534,7 @@ void RegisterObjectSelectionTests_MoveObject(DungeonObjectRenderingE2ETests* sel
|
||||
ctx->MouseMove(ImVec2(canvas_pos.x + 48, canvas_pos.y + 48));
|
||||
ctx->MouseUp();
|
||||
ctx->Yield();
|
||||
|
||||
|
||||
// Verify new position
|
||||
ctx->SetRef("Dungeon Editor/Object Details");
|
||||
ctx->ItemVerifyValue("X Position", 48);
|
||||
@@ -540,8 +551,10 @@ void RegisterObjectSelectionTests_MoveObject(DungeonObjectRenderingE2ETests* sel
|
||||
* - Object no longer in room list
|
||||
* - Canvas no longer renders object
|
||||
*/
|
||||
void RegisterObjectSelectionTests_DeleteObject(DungeonObjectRenderingE2ETests* self) {
|
||||
ImGuiTest* test = IM_REGISTER_TEST(self->engine_, "DungeonObjectRendering", "ObjectSelection_DeleteObject");
|
||||
void RegisterObjectSelectionTests_DeleteObject(
|
||||
DungeonObjectRenderingE2ETests* self) {
|
||||
ImGuiTest* test = IM_REGISTER_TEST(self->engine_, "DungeonObjectRendering",
|
||||
"ObjectSelection_DeleteObject");
|
||||
test->GuiFunc = [](ImGuiTestContext* ctx) {
|
||||
auto* self = (DungeonObjectRenderingE2ETests*)ctx->UserData;
|
||||
self->dungeon_editor_->Update();
|
||||
@@ -553,21 +566,21 @@ void RegisterObjectSelectionTests_DeleteObject(DungeonObjectRenderingE2ETests* s
|
||||
ctx->SetRef("AssetBrowser");
|
||||
ctx->ItemClick("Object_0x10");
|
||||
ctx->Yield();
|
||||
|
||||
|
||||
ctx->SetRef("Dungeon Editor/Canvas");
|
||||
ImVec2 canvas_center = ctx->ItemRectCenter("canvas##child");
|
||||
ctx->MouseMove(canvas_center);
|
||||
ctx->MouseClick();
|
||||
ctx->Yield();
|
||||
|
||||
|
||||
// Select object
|
||||
ctx->MouseClick();
|
||||
ctx->Yield();
|
||||
|
||||
|
||||
// Delete with Delete key
|
||||
ctx->KeyPress(ImGuiKey_Delete);
|
||||
ctx->Yield();
|
||||
|
||||
|
||||
// Verify object removed
|
||||
ctx->SetRef("Dungeon Editor/Room Objects");
|
||||
ctx->ItemVerifyValue("Object Count", 0);
|
||||
@@ -588,29 +601,30 @@ void RegisterObjectSelectionTests_DeleteObject(DungeonObjectRenderingE2ETests* s
|
||||
* - Layer can be shown again
|
||||
*/
|
||||
void DungeonObjectRenderingE2ETests::RegisterLayerManagementTests() {
|
||||
ImGuiTest* test = IM_REGISTER_TEST(engine_, "DungeonObjectRendering", "LayerManagement_ToggleVisibility");
|
||||
ImGuiTest* test = IM_REGISTER_TEST(engine_, "DungeonObjectRendering",
|
||||
"LayerManagement_ToggleVisibility");
|
||||
test->GuiFunc = [](ImGuiTestContext* ctx) {
|
||||
auto* self = (DungeonObjectRenderingE2ETests*)ctx->UserData;
|
||||
self->dungeon_editor_->Update();
|
||||
};
|
||||
test->TestFunc = [](ImGuiTestContext* ctx) {
|
||||
ctx->SetRef("Dungeon Editor");
|
||||
|
||||
|
||||
// Open layer management panel
|
||||
ctx->ItemClick("Layers##tab");
|
||||
ctx->Yield();
|
||||
|
||||
|
||||
// Toggle Layer 1 visibility
|
||||
ctx->ItemClick("Layer 1 Visible##checkbox");
|
||||
ctx->Yield();
|
||||
|
||||
|
||||
// Verify checkbox state
|
||||
ctx->ItemVerifyValue("Layer 1 Visible##checkbox", false);
|
||||
|
||||
|
||||
// Toggle back on
|
||||
ctx->ItemClick("Layer 1 Visible##checkbox");
|
||||
ctx->Yield();
|
||||
|
||||
|
||||
ctx->ItemVerifyValue("Layer 1 Visible##checkbox", true);
|
||||
};
|
||||
test->UserData = this;
|
||||
@@ -624,51 +638,53 @@ void DungeonObjectRenderingE2ETests::RegisterLayerManagementTests() {
|
||||
* - Objects placed on correct layer
|
||||
* - Layer indicator shows current layer
|
||||
*/
|
||||
void RegisterLayerManagementTests_PlaceOnLayers(DungeonObjectRenderingE2ETests* self) {
|
||||
ImGuiTest* test = IM_REGISTER_TEST(self->engine_, "DungeonObjectRendering", "LayerManagement_PlaceOnLayers");
|
||||
void RegisterLayerManagementTests_PlaceOnLayers(
|
||||
DungeonObjectRenderingE2ETests* self) {
|
||||
ImGuiTest* test = IM_REGISTER_TEST(self->engine_, "DungeonObjectRendering",
|
||||
"LayerManagement_PlaceOnLayers");
|
||||
test->GuiFunc = [](ImGuiTestContext* ctx) {
|
||||
auto* self = (DungeonObjectRenderingE2ETests*)ctx->UserData;
|
||||
self->dungeon_editor_->Update();
|
||||
};
|
||||
test->TestFunc = [](ImGuiTestContext* ctx) {
|
||||
ctx->SetRef("Dungeon Editor");
|
||||
|
||||
|
||||
// Place object on Layer 0
|
||||
ctx->ItemClick("Layers##tab");
|
||||
ctx->ItemClick("Layer 0##radio");
|
||||
ctx->Yield();
|
||||
|
||||
|
||||
ctx->ItemClick("Object Selector##tab");
|
||||
ctx->SetRef("AssetBrowser");
|
||||
ctx->ItemClick("Object_0x10");
|
||||
ctx->Yield();
|
||||
|
||||
|
||||
ctx->SetRef("Dungeon Editor/Canvas");
|
||||
ImVec2 canvas_pos = ctx->ItemRectMin("canvas##child");
|
||||
ctx->MouseMove(ImVec2(canvas_pos.x + 16, canvas_pos.y + 16));
|
||||
ctx->MouseClick();
|
||||
ctx->Yield();
|
||||
|
||||
|
||||
// Verify object on Layer 0
|
||||
ctx->SetRef("Dungeon Editor/Object Details");
|
||||
ctx->ItemVerifyValue("Layer", 0);
|
||||
|
||||
|
||||
// Switch to Layer 1 and place another object
|
||||
ctx->SetRef("Dungeon Editor");
|
||||
ctx->ItemClick("Layers##tab");
|
||||
ctx->ItemClick("Layer 1##radio");
|
||||
ctx->Yield();
|
||||
|
||||
|
||||
ctx->ItemClick("Object Selector##tab");
|
||||
ctx->SetRef("AssetBrowser");
|
||||
ctx->ItemClick("Object_0x20");
|
||||
ctx->Yield();
|
||||
|
||||
|
||||
ctx->SetRef("Dungeon Editor/Canvas");
|
||||
ctx->MouseMove(ImVec2(canvas_pos.x + 48, canvas_pos.y + 48));
|
||||
ctx->MouseClick();
|
||||
ctx->Yield();
|
||||
|
||||
|
||||
// Verify object on Layer 1
|
||||
ctx->SetRef("Dungeon Editor/Object Details");
|
||||
ctx->ItemVerifyValue("Layer", 1);
|
||||
@@ -684,8 +700,10 @@ void RegisterLayerManagementTests_PlaceOnLayers(DungeonObjectRenderingE2ETests*
|
||||
* - Overlapping objects render correctly
|
||||
* - Visual inspection of layer order
|
||||
*/
|
||||
void RegisterLayerManagementTests_RenderingOrder(DungeonObjectRenderingE2ETests* self) {
|
||||
ImGuiTest* test = IM_REGISTER_TEST(self->engine_, "DungeonObjectRendering", "LayerManagement_RenderingOrder");
|
||||
void RegisterLayerManagementTests_RenderingOrder(
|
||||
DungeonObjectRenderingE2ETests* self) {
|
||||
ImGuiTest* test = IM_REGISTER_TEST(self->engine_, "DungeonObjectRendering",
|
||||
"LayerManagement_RenderingOrder");
|
||||
test->GuiFunc = [](ImGuiTestContext* ctx) {
|
||||
auto* self = (DungeonObjectRenderingE2ETests*)ctx->UserData;
|
||||
self->dungeon_editor_->Update();
|
||||
@@ -693,28 +711,28 @@ void RegisterLayerManagementTests_RenderingOrder(DungeonObjectRenderingE2ETests*
|
||||
test->TestFunc = [](ImGuiTestContext* ctx) {
|
||||
// Place 3 objects at same position on different layers
|
||||
ctx->SetRef("Dungeon Editor");
|
||||
|
||||
|
||||
for (int layer = 0; layer < 3; layer++) {
|
||||
ctx->ItemClick("Layers##tab");
|
||||
ctx->ItemClick(ImGuiTestRef_Str("Layer %d##radio", layer));
|
||||
ctx->Yield();
|
||||
|
||||
|
||||
ctx->ItemClick("Object Selector##tab");
|
||||
ctx->SetRef("AssetBrowser");
|
||||
ctx->ItemClick(ImGuiTestRef_Str("Object_0x%02X", 0x10 + layer));
|
||||
ctx->Yield();
|
||||
|
||||
|
||||
ctx->SetRef("Dungeon Editor/Canvas");
|
||||
ImVec2 canvas_center = ctx->ItemRectCenter("canvas##child");
|
||||
ctx->MouseMove(canvas_center);
|
||||
ctx->MouseClick();
|
||||
ctx->Yield();
|
||||
}
|
||||
|
||||
|
||||
// Verify all 3 objects exist
|
||||
ctx->SetRef("Dungeon Editor/Room Objects");
|
||||
ctx->ItemVerifyValue("Object Count", 3);
|
||||
|
||||
|
||||
// Visual verification would be done with snapshot comparison
|
||||
// Here we just verify the objects are in the right layers
|
||||
ctx->ItemExists("Layer 0: 1 object");
|
||||
@@ -737,7 +755,8 @@ void RegisterLayerManagementTests_RenderingOrder(DungeonObjectRenderingE2ETests*
|
||||
* - No errors during save
|
||||
*/
|
||||
void DungeonObjectRenderingE2ETests::RegisterSaveWorkflowTests() {
|
||||
ImGuiTest* test = IM_REGISTER_TEST(engine_, "DungeonObjectRendering", "SaveWorkflow_SaveRoom");
|
||||
ImGuiTest* test = IM_REGISTER_TEST(engine_, "DungeonObjectRendering",
|
||||
"SaveWorkflow_SaveRoom");
|
||||
test->GuiFunc = [](ImGuiTestContext* ctx) {
|
||||
auto* self = (DungeonObjectRenderingE2ETests*)ctx->UserData;
|
||||
self->dungeon_editor_->Update();
|
||||
@@ -749,19 +768,19 @@ void DungeonObjectRenderingE2ETests::RegisterSaveWorkflowTests() {
|
||||
ctx->SetRef("AssetBrowser");
|
||||
ctx->ItemClick("Object_0x10");
|
||||
ctx->Yield();
|
||||
|
||||
|
||||
ctx->SetRef("Dungeon Editor/Canvas");
|
||||
ImVec2 canvas_center = ctx->ItemRectCenter("canvas##child");
|
||||
ctx->MouseMove(canvas_center);
|
||||
ctx->MouseClick();
|
||||
ctx->Yield();
|
||||
|
||||
|
||||
// Save room
|
||||
ctx->SetRef("Dungeon Editor");
|
||||
ctx->ItemClick("File##menu");
|
||||
ctx->ItemClick("Save Room##menuitem");
|
||||
ctx->Yield();
|
||||
|
||||
|
||||
// Verify save success message
|
||||
ctx->ItemExists("Save successful");
|
||||
};
|
||||
@@ -777,7 +796,8 @@ void DungeonObjectRenderingE2ETests::RegisterSaveWorkflowTests() {
|
||||
* - No data corruption
|
||||
*/
|
||||
void RegisterSaveWorkflowTests_RoundTrip(DungeonObjectRenderingE2ETests* self) {
|
||||
ImGuiTest* test = IM_REGISTER_TEST(self->engine_, "DungeonObjectRendering", "SaveWorkflow_RoundTrip");
|
||||
ImGuiTest* test = IM_REGISTER_TEST(self->engine_, "DungeonObjectRendering",
|
||||
"SaveWorkflow_RoundTrip");
|
||||
test->GuiFunc = [](ImGuiTestContext* ctx) {
|
||||
auto* self = (DungeonObjectRenderingE2ETests*)ctx->UserData;
|
||||
self->dungeon_editor_->Update();
|
||||
@@ -789,30 +809,30 @@ void RegisterSaveWorkflowTests_RoundTrip(DungeonObjectRenderingE2ETests* self) {
|
||||
ctx->SetRef("AssetBrowser");
|
||||
ctx->ItemClick("Object_0x10");
|
||||
ctx->Yield();
|
||||
|
||||
|
||||
ctx->SetRef("Dungeon Editor/Canvas");
|
||||
ImVec2 canvas_pos = ctx->ItemRectMin("canvas##child");
|
||||
ctx->MouseMove(ImVec2(canvas_pos.x + 64, canvas_pos.y + 96));
|
||||
ctx->MouseClick();
|
||||
ctx->Yield();
|
||||
|
||||
|
||||
// Verify initial state
|
||||
ctx->SetRef("Dungeon Editor/Object Details");
|
||||
int initial_x = ctx->ItemGetValue<int>("X Position");
|
||||
int initial_y = ctx->ItemGetValue<int>("Y Position");
|
||||
int initial_id = ctx->ItemGetValue<int>("Object ID");
|
||||
|
||||
|
||||
// Save room
|
||||
ctx->SetRef("Dungeon Editor");
|
||||
ctx->ItemClick("File##menu");
|
||||
ctx->ItemClick("Save Room##menuitem");
|
||||
ctx->Yield();
|
||||
|
||||
|
||||
// Reload room
|
||||
ctx->ItemClick("File##menu");
|
||||
ctx->ItemClick("Reload Room##menuitem");
|
||||
ctx->Yield();
|
||||
|
||||
|
||||
// Verify object persisted with same properties
|
||||
ctx->SetRef("Dungeon Editor/Object Details");
|
||||
ctx->ItemVerifyValue("X Position", initial_x);
|
||||
@@ -830,8 +850,10 @@ void RegisterSaveWorkflowTests_RoundTrip(DungeonObjectRenderingE2ETests* self) {
|
||||
* - Encoding is correct for each type
|
||||
* - All objects reload correctly
|
||||
*/
|
||||
void RegisterSaveWorkflowTests_MultipleTypes(DungeonObjectRenderingE2ETests* self) {
|
||||
ImGuiTest* test = IM_REGISTER_TEST(self->engine_, "DungeonObjectRendering", "SaveWorkflow_MultipleTypes");
|
||||
void RegisterSaveWorkflowTests_MultipleTypes(
|
||||
DungeonObjectRenderingE2ETests* self) {
|
||||
ImGuiTest* test = IM_REGISTER_TEST(self->engine_, "DungeonObjectRendering",
|
||||
"SaveWorkflow_MultipleTypes");
|
||||
test->GuiFunc = [](ImGuiTestContext* ctx) {
|
||||
auto* self = (DungeonObjectRenderingE2ETests*)ctx->UserData;
|
||||
self->dungeon_editor_->Update();
|
||||
@@ -839,40 +861,40 @@ void RegisterSaveWorkflowTests_MultipleTypes(DungeonObjectRenderingE2ETests* sel
|
||||
test->TestFunc = [](ImGuiTestContext* ctx) {
|
||||
// Place one of each object type
|
||||
const uint16_t object_ids[] = {
|
||||
0x10, // Type1
|
||||
0x125, // Type2
|
||||
0xF99 // Type3 (chest)
|
||||
0x10, // Type1
|
||||
0x125, // Type2
|
||||
0xF99 // Type3 (chest)
|
||||
};
|
||||
|
||||
|
||||
ctx->SetRef("Dungeon Editor");
|
||||
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
ctx->ItemClick("Object Selector##tab");
|
||||
ctx->SetRef("AssetBrowser");
|
||||
ctx->ItemClick(ImGuiTestRef_Str("Object_0x%02X", object_ids[i]));
|
||||
ctx->Yield();
|
||||
|
||||
|
||||
ctx->SetRef("Dungeon Editor/Canvas");
|
||||
ImVec2 canvas_pos = ctx->ItemRectMin("canvas##child");
|
||||
ctx->MouseMove(ImVec2(canvas_pos.x + (i * 32), canvas_pos.y + (i * 32)));
|
||||
ctx->MouseClick();
|
||||
ctx->Yield();
|
||||
}
|
||||
|
||||
|
||||
// Save and reload
|
||||
ctx->SetRef("Dungeon Editor");
|
||||
ctx->ItemClick("File##menu");
|
||||
ctx->ItemClick("Save Room##menuitem");
|
||||
ctx->Yield();
|
||||
|
||||
|
||||
ctx->ItemClick("File##menu");
|
||||
ctx->ItemClick("Reload Room##menuitem");
|
||||
ctx->Yield();
|
||||
|
||||
|
||||
// Verify all 3 objects reloaded
|
||||
ctx->SetRef("Dungeon Editor/Room Objects");
|
||||
ctx->ItemVerifyValue("Object Count", 3);
|
||||
|
||||
|
||||
// Verify each object type
|
||||
for (int i = 0; i < 3; i++) {
|
||||
ctx->ItemExists(ImGuiTestRef_Str("Object ID: 0x%02X", object_ids[i]));
|
||||
@@ -895,7 +917,8 @@ void RegisterSaveWorkflowTests_MultipleTypes(DungeonObjectRenderingE2ETests* sel
|
||||
* - All render at correct positions
|
||||
*/
|
||||
void DungeonObjectRenderingE2ETests::RegisterRenderingQualityTests() {
|
||||
ImGuiTest* test = IM_REGISTER_TEST(engine_, "DungeonObjectRendering", "RenderingQuality_AllTypes");
|
||||
ImGuiTest* test = IM_REGISTER_TEST(engine_, "DungeonObjectRendering",
|
||||
"RenderingQuality_AllTypes");
|
||||
test->GuiFunc = [](ImGuiTestContext* ctx) {
|
||||
auto* self = (DungeonObjectRenderingE2ETests*)ctx->UserData;
|
||||
self->dungeon_editor_->Update();
|
||||
@@ -903,28 +926,29 @@ void DungeonObjectRenderingE2ETests::RegisterRenderingQualityTests() {
|
||||
test->TestFunc = [](ImGuiTestContext* ctx) {
|
||||
// This would typically involve visual snapshot comparison
|
||||
// For now, we verify objects are placed and rendered without errors
|
||||
|
||||
|
||||
const uint16_t object_ids[] = {
|
||||
0x10, 0x11, 0x20, // Type1 objects
|
||||
0x100, 0x125, // Type2 objects
|
||||
0xF99, 0xFB1 // Type3 objects
|
||||
0x10, 0x11, 0x20, // Type1 objects
|
||||
0x100, 0x125, // Type2 objects
|
||||
0xF99, 0xFB1 // Type3 objects
|
||||
};
|
||||
|
||||
|
||||
ctx->SetRef("Dungeon Editor");
|
||||
|
||||
|
||||
for (int i = 0; i < 7; i++) {
|
||||
ctx->ItemClick("Object Selector##tab");
|
||||
ctx->SetRef("AssetBrowser");
|
||||
ctx->ItemClick(ImGuiTestRef_Str("Object_0x%02X", object_ids[i]));
|
||||
ctx->Yield();
|
||||
|
||||
|
||||
ctx->SetRef("Dungeon Editor/Canvas");
|
||||
ImVec2 canvas_pos = ctx->ItemRectMin("canvas##child");
|
||||
ctx->MouseMove(ImVec2(canvas_pos.x + ((i % 4) * 48), canvas_pos.y + ((i / 4) * 48)));
|
||||
ctx->MouseMove(
|
||||
ImVec2(canvas_pos.x + ((i % 4) * 48), canvas_pos.y + ((i / 4) * 48)));
|
||||
ctx->MouseClick();
|
||||
ctx->Yield();
|
||||
}
|
||||
|
||||
|
||||
// Verify all objects rendered without errors
|
||||
ctx->SetRef("Dungeon Editor/Room Objects");
|
||||
ctx->ItemVerifyValue("Object Count", 7);
|
||||
@@ -941,8 +965,10 @@ void DungeonObjectRenderingE2ETests::RegisterRenderingQualityTests() {
|
||||
* - Objects render with correct colors
|
||||
* - No palette-related rendering errors
|
||||
*/
|
||||
void RegisterRenderingQualityTests_Palettes(DungeonObjectRenderingE2ETests* self) {
|
||||
ImGuiTest* test = IM_REGISTER_TEST(self->engine_, "DungeonObjectRendering", "RenderingQuality_Palettes");
|
||||
void RegisterRenderingQualityTests_Palettes(
|
||||
DungeonObjectRenderingE2ETests* self) {
|
||||
ImGuiTest* test = IM_REGISTER_TEST(self->engine_, "DungeonObjectRendering",
|
||||
"RenderingQuality_Palettes");
|
||||
test->GuiFunc = [](ImGuiTestContext* ctx) {
|
||||
auto* self = (DungeonObjectRenderingE2ETests*)ctx->UserData;
|
||||
self->dungeon_editor_->Update();
|
||||
@@ -954,22 +980,22 @@ void RegisterRenderingQualityTests_Palettes(DungeonObjectRenderingE2ETests* self
|
||||
ctx->SetRef("AssetBrowser");
|
||||
ctx->ItemClick("Object_0x10");
|
||||
ctx->Yield();
|
||||
|
||||
|
||||
ctx->SetRef("Dungeon Editor/Canvas");
|
||||
ImVec2 canvas_center = ctx->ItemRectCenter("canvas##child");
|
||||
ctx->MouseMove(canvas_center);
|
||||
ctx->MouseClick();
|
||||
ctx->Yield();
|
||||
|
||||
|
||||
// Switch palettes and verify rendering
|
||||
const int palette_ids[] = {0, 1, 2, 3, 4, 5};
|
||||
|
||||
|
||||
for (int palette : palette_ids) {
|
||||
ctx->SetRef("Dungeon Editor");
|
||||
ctx->ItemClick("Options##menu");
|
||||
ctx->ItemInput("Palette##input", palette);
|
||||
ctx->Yield();
|
||||
|
||||
|
||||
// Verify no rendering errors
|
||||
ctx->ItemVerifyNotExists("Rendering Error");
|
||||
}
|
||||
@@ -985,8 +1011,10 @@ void RegisterRenderingQualityTests_Palettes(DungeonObjectRenderingE2ETests* self
|
||||
* - Performance is acceptable
|
||||
* - No rendering artifacts
|
||||
*/
|
||||
void RegisterRenderingQualityTests_ComplexRoom(DungeonObjectRenderingE2ETests* self) {
|
||||
ImGuiTest* test = IM_REGISTER_TEST(self->engine_, "DungeonObjectRendering", "RenderingQuality_ComplexRoom");
|
||||
void RegisterRenderingQualityTests_ComplexRoom(
|
||||
DungeonObjectRenderingE2ETests* self) {
|
||||
ImGuiTest* test = IM_REGISTER_TEST(self->engine_, "DungeonObjectRendering",
|
||||
"RenderingQuality_ComplexRoom");
|
||||
test->GuiFunc = [](ImGuiTestContext* ctx) {
|
||||
auto* self = (DungeonObjectRenderingE2ETests*)ctx->UserData;
|
||||
self->dungeon_editor_->Update();
|
||||
@@ -994,7 +1022,7 @@ void RegisterRenderingQualityTests_ComplexRoom(DungeonObjectRenderingE2ETests* s
|
||||
test->TestFunc = [](ImGuiTestContext* ctx) {
|
||||
// Place many objects to create complex room
|
||||
ctx->SetRef("Dungeon Editor");
|
||||
|
||||
|
||||
// Place wall perimeter (Type1 objects)
|
||||
for (int x = 0; x < 16; x++) {
|
||||
for (int side = 0; side < 2; side++) {
|
||||
@@ -1002,16 +1030,17 @@ void RegisterRenderingQualityTests_ComplexRoom(DungeonObjectRenderingE2ETests* s
|
||||
ctx->SetRef("AssetBrowser");
|
||||
ctx->ItemClick("Object_0x10");
|
||||
ctx->Yield();
|
||||
|
||||
|
||||
ctx->SetRef("Dungeon Editor/Canvas");
|
||||
ImVec2 canvas_pos = ctx->ItemRectMin("canvas##child");
|
||||
int y = side == 0 ? 0 : 10;
|
||||
ctx->MouseMove(ImVec2(canvas_pos.x + (x * 16), canvas_pos.y + (y * 16)));
|
||||
ctx->MouseMove(
|
||||
ImVec2(canvas_pos.x + (x * 16), canvas_pos.y + (y * 16)));
|
||||
ctx->MouseClick();
|
||||
ctx->Yield();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Add some decorative objects
|
||||
const uint16_t decorative_objects[] = {0x20, 0x21, 0xF99};
|
||||
for (int i = 0; i < 3; i++) {
|
||||
@@ -1019,18 +1048,18 @@ void RegisterRenderingQualityTests_ComplexRoom(DungeonObjectRenderingE2ETests* s
|
||||
ctx->SetRef("AssetBrowser");
|
||||
ctx->ItemClick(ImGuiTestRef_Str("Object_0x%02X", decorative_objects[i]));
|
||||
ctx->Yield();
|
||||
|
||||
|
||||
ctx->SetRef("Dungeon Editor/Canvas");
|
||||
ImVec2 canvas_pos = ctx->ItemRectMin("canvas##child");
|
||||
ctx->MouseMove(ImVec2(canvas_pos.x + (i * 64) + 32, canvas_pos.y + 80));
|
||||
ctx->MouseClick();
|
||||
ctx->Yield();
|
||||
}
|
||||
|
||||
|
||||
// Verify all objects rendered
|
||||
ctx->SetRef("Dungeon Editor/Room Objects");
|
||||
ctx->ItemVerifyValue("Object Count", 35); // 32 walls + 3 decorative
|
||||
|
||||
|
||||
// Verify no performance issues (frame time < 16ms for 60fps)
|
||||
ctx->SetRef("Dungeon Editor");
|
||||
ctx->ItemVerifyLessThan("Frame Time (ms)", 16.0f);
|
||||
@@ -1051,38 +1080,37 @@ void RegisterRenderingQualityTests_ComplexRoom(DungeonObjectRenderingE2ETests* s
|
||||
* - Memory usage is reasonable
|
||||
*/
|
||||
void DungeonObjectRenderingE2ETests::RegisterPerformanceTests() {
|
||||
ImGuiTest* test = IM_REGISTER_TEST(engine_, "DungeonObjectRendering", "Performance_LargeRoom");
|
||||
ImGuiTest* test = IM_REGISTER_TEST(engine_, "DungeonObjectRendering",
|
||||
"Performance_LargeRoom");
|
||||
test->GuiFunc = [](ImGuiTestContext* ctx) {
|
||||
auto* self = (DungeonObjectRenderingE2ETests*)ctx->UserData;
|
||||
self->dungeon_editor_->Update();
|
||||
};
|
||||
test->TestFunc = [](ImGuiTestContext* ctx) {
|
||||
ctx->SetRef("Dungeon Editor");
|
||||
|
||||
|
||||
// Place 100 objects
|
||||
for (int i = 0; i < 100; i++) {
|
||||
ctx->ItemClick("Object Selector##tab");
|
||||
ctx->SetRef("AssetBrowser");
|
||||
ctx->ItemClick("Object_0x10");
|
||||
ctx->Yield();
|
||||
|
||||
|
||||
ctx->SetRef("Dungeon Editor/Canvas");
|
||||
ImVec2 canvas_pos = ctx->ItemRectMin("canvas##child");
|
||||
ctx->MouseMove(ImVec2(
|
||||
canvas_pos.x + ((i % 16) * 16),
|
||||
canvas_pos.y + ((i / 16) * 16)
|
||||
));
|
||||
ctx->MouseMove(ImVec2(canvas_pos.x + ((i % 16) * 16),
|
||||
canvas_pos.y + ((i / 16) * 16)));
|
||||
ctx->MouseClick();
|
||||
ctx->Yield();
|
||||
}
|
||||
|
||||
|
||||
// Measure rendering performance
|
||||
ctx->SetRef("Dungeon Editor");
|
||||
float frame_time = ctx->ItemGetValue<float>("Frame Time (ms)");
|
||||
|
||||
|
||||
// Verify acceptable performance (< 16ms for 60fps)
|
||||
IM_CHECK_LT(frame_time, 16.0f);
|
||||
|
||||
|
||||
// Verify object count
|
||||
ctx->SetRef("Dungeon Editor/Room Objects");
|
||||
ctx->ItemVerifyValue("Object Count", 100);
|
||||
@@ -1102,7 +1130,7 @@ void DungeonObjectRenderingE2ETests::RegisterAllTests() {
|
||||
RegisterSaveWorkflowTests();
|
||||
RegisterRenderingQualityTests();
|
||||
RegisterPerformanceTests();
|
||||
|
||||
|
||||
// Register additional helper tests
|
||||
RegisterObjectBrowserTests_SelectObject(this);
|
||||
RegisterObjectBrowserTests_SearchFilter(this);
|
||||
@@ -1127,13 +1155,12 @@ TEST_F(DungeonObjectRenderingE2ETests, RunAllTests) {
|
||||
// Run all registered tests
|
||||
ImGuiTestEngine_QueueTests(engine_, ImGuiTestGroup_Tests, nullptr, nullptr);
|
||||
ImGuiTestEngine_Run(engine_);
|
||||
|
||||
|
||||
// Verify all tests passed
|
||||
ImGuiTestEngineIO& test_io = ImGuiTestEngine_GetIO(engine_);
|
||||
EXPECT_EQ(test_io.TestsFailedCount, 0)
|
||||
<< "Some E2E tests failed. Check test engine output for details.";
|
||||
EXPECT_EQ(test_io.TestsFailedCount, 0)
|
||||
<< "Some E2E tests failed. Check test engine output for details.";
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
} // namespace yaze
|
||||
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
#include "e2e/framework_smoke_test.h"
|
||||
#include "test_utils.h"
|
||||
#include "imgui.h"
|
||||
#include "imgui_test_engine/imgui_te_context.h"
|
||||
#include "test_utils.h"
|
||||
|
||||
// Smoke test for the E2E testing framework.
|
||||
// This test is run by the `test-gui` command.
|
||||
// It opens a window, clicks a button, and verifies that the button was clicked.
|
||||
// The GUI for this test is rendered in `test/yaze_test.cc`.
|
||||
void E2ETest_FrameworkSmokeTest(ImGuiTestContext* ctx)
|
||||
{
|
||||
yaze::test::gui::LoadRomInTest(ctx, "zelda3.sfc");
|
||||
ctx->SetRef("Hello World Window");
|
||||
ctx->ItemClick("Button");
|
||||
ctx->ItemCheck("Clicked 1 times");
|
||||
void E2ETest_FrameworkSmokeTest(ImGuiTestContext* ctx) {
|
||||
yaze::test::gui::LoadRomInTest(ctx, "zelda3.sfc");
|
||||
ctx->SetRef("Hello World Window");
|
||||
ctx->ItemClick("Button");
|
||||
ctx->ItemCheck("Clicked 1 times");
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <filesystem>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "app/rom.h"
|
||||
#include "testing.h"
|
||||
#include "zelda3/overworld/overworld.h"
|
||||
#include "zelda3/overworld/overworld_map.h"
|
||||
#include "testing.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace test {
|
||||
@@ -34,7 +34,7 @@ class OverworldE2ETest : public ::testing::Test {
|
||||
// Get ROM path from environment or use default
|
||||
const char* rom_path_env = getenv("YAZE_TEST_ROM_PATH");
|
||||
vanilla_rom_path_ = rom_path_env ? rom_path_env : "zelda3.sfc";
|
||||
|
||||
|
||||
if (!std::filesystem::exists(vanilla_rom_path_)) {
|
||||
GTEST_SKIP() << "Test ROM not found: " << vanilla_rom_path_;
|
||||
}
|
||||
@@ -43,7 +43,7 @@ class OverworldE2ETest : public ::testing::Test {
|
||||
vanilla_test_path_ = "test_vanilla_e2e.sfc";
|
||||
edited_test_path_ = "test_edited_e2e.sfc";
|
||||
golden_data_path_ = "golden_data_e2e.h";
|
||||
|
||||
|
||||
// Copy vanilla ROM for testing
|
||||
std::filesystem::copy_file(vanilla_rom_path_, vanilla_test_path_);
|
||||
}
|
||||
@@ -51,9 +51,8 @@ class OverworldE2ETest : public ::testing::Test {
|
||||
void TearDown() override {
|
||||
// Clean up test files
|
||||
std::vector<std::string> test_files = {
|
||||
vanilla_test_path_, edited_test_path_, golden_data_path_
|
||||
};
|
||||
|
||||
vanilla_test_path_, edited_test_path_, golden_data_path_};
|
||||
|
||||
for (const auto& file : test_files) {
|
||||
if (std::filesystem::exists(file)) {
|
||||
std::filesystem::remove(file);
|
||||
@@ -62,32 +61,37 @@ class OverworldE2ETest : public ::testing::Test {
|
||||
}
|
||||
|
||||
// Helper to extract golden data from ROM
|
||||
absl::Status ExtractGoldenData(const std::string& rom_path,
|
||||
absl::Status ExtractGoldenData(const std::string& rom_path,
|
||||
const std::string& output_path) {
|
||||
// Run the golden data extractor
|
||||
std::string command = "./overworld_golden_data_extractor " + rom_path + " " + output_path;
|
||||
std::string command =
|
||||
"./overworld_golden_data_extractor " + rom_path + " " + output_path;
|
||||
int result = system(command.c_str());
|
||||
|
||||
|
||||
if (result != 0) {
|
||||
return absl::InternalError("Failed to extract golden data");
|
||||
}
|
||||
|
||||
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
// Helper to validate ROM against golden data
|
||||
bool ValidateROMAgainstGoldenData(Rom& rom, const std::string& /* golden_data_path */) {
|
||||
bool ValidateROMAgainstGoldenData(Rom& rom,
|
||||
const std::string& /* golden_data_path */) {
|
||||
// This would load the generated golden data header and compare values
|
||||
// For now, we'll do basic validation
|
||||
|
||||
|
||||
// Check basic ROM properties
|
||||
if (rom.title().empty()) return false;
|
||||
if (rom.size() < 1024*1024) return false; // At least 1MB
|
||||
|
||||
if (rom.title().empty())
|
||||
return false;
|
||||
if (rom.size() < 1024 * 1024)
|
||||
return false; // At least 1MB
|
||||
|
||||
// Check ASM version
|
||||
auto asm_version = rom.ReadByte(0x140145);
|
||||
if (!asm_version.ok()) return false;
|
||||
|
||||
if (!asm_version.ok())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -101,13 +105,13 @@ class OverworldE2ETest : public ::testing::Test {
|
||||
TEST_F(OverworldE2ETest, ExtractVanillaGoldenData) {
|
||||
std::unique_ptr<Rom> rom = std::make_unique<Rom>();
|
||||
ASSERT_OK(rom->LoadFromFile(vanilla_test_path_));
|
||||
|
||||
|
||||
// Extract golden data
|
||||
ASSERT_OK(ExtractGoldenData(vanilla_test_path_, golden_data_path_));
|
||||
|
||||
|
||||
// Verify golden data file was created
|
||||
EXPECT_TRUE(std::filesystem::exists(golden_data_path_));
|
||||
|
||||
|
||||
// Validate ROM against golden data
|
||||
EXPECT_TRUE(ValidateROMAgainstGoldenData(*rom, golden_data_path_));
|
||||
}
|
||||
@@ -116,37 +120,37 @@ TEST_F(OverworldE2ETest, ExtractVanillaGoldenData) {
|
||||
TEST_F(OverworldE2ETest, LoadVanillaOverworldData) {
|
||||
std::unique_ptr<Rom> rom = std::make_unique<Rom>();
|
||||
ASSERT_OK(rom->LoadFromFile(vanilla_test_path_));
|
||||
|
||||
|
||||
zelda3::Overworld overworld(rom.get());
|
||||
auto status = overworld.Load(rom.get());
|
||||
ASSERT_TRUE(status.ok());
|
||||
|
||||
|
||||
// Validate basic overworld structure
|
||||
EXPECT_TRUE(overworld.is_loaded());
|
||||
|
||||
|
||||
const auto& maps = overworld.overworld_maps();
|
||||
EXPECT_EQ(maps.size(), 160);
|
||||
|
||||
|
||||
// Validate that we have a vanilla ROM (ASM version 0xFF)
|
||||
auto asm_version = rom->ReadByte(0x140145);
|
||||
ASSERT_TRUE(asm_version.ok());
|
||||
EXPECT_EQ(*asm_version, 0xFF);
|
||||
|
||||
|
||||
// Validate expansion flags for vanilla
|
||||
EXPECT_FALSE(overworld.expanded_tile16());
|
||||
EXPECT_FALSE(overworld.expanded_tile32());
|
||||
|
||||
|
||||
// Validate data structures
|
||||
const auto& entrances = overworld.entrances();
|
||||
const auto& exits = overworld.exits();
|
||||
const auto& holes = overworld.holes();
|
||||
const auto& items = overworld.all_items();
|
||||
|
||||
|
||||
EXPECT_EQ(entrances.size(), 129);
|
||||
EXPECT_EQ(exits->size(), 0x4F);
|
||||
EXPECT_EQ(holes.size(), 0x13);
|
||||
EXPECT_GE(items.size(), 0);
|
||||
|
||||
|
||||
// Validate sprite data (3 game states)
|
||||
const auto& sprites = overworld.all_sprites();
|
||||
EXPECT_EQ(sprites.size(), 3);
|
||||
@@ -156,31 +160,31 @@ TEST_F(OverworldE2ETest, LoadVanillaOverworldData) {
|
||||
TEST_F(OverworldE2ETest, ApplyZSCustomOverworldV3) {
|
||||
std::unique_ptr<Rom> rom = std::make_unique<Rom>();
|
||||
ASSERT_OK(rom->LoadFromFile(vanilla_test_path_));
|
||||
|
||||
|
||||
// Apply ZSCustomOverworld v3 ASM
|
||||
// This would typically be done through the editor, but we can simulate it
|
||||
ASSERT_OK(rom->WriteByte(0x140145, 0x03)); // Set ASM version to v3
|
||||
|
||||
ASSERT_OK(rom->WriteByte(0x140145, 0x03)); // Set ASM version to v3
|
||||
|
||||
// Enable v3 features
|
||||
ASSERT_OK(rom->WriteByte(0x140146, 0x01)); // Enable main palettes
|
||||
ASSERT_OK(rom->WriteByte(0x140147, 0x01)); // Enable area-specific BG
|
||||
ASSERT_OK(rom->WriteByte(0x140148, 0x01)); // Enable subscreen overlay
|
||||
ASSERT_OK(rom->WriteByte(0x140149, 0x01)); // Enable animated GFX
|
||||
ASSERT_OK(rom->WriteByte(0x14014A, 0x01)); // Enable custom tile GFX groups
|
||||
ASSERT_OK(rom->WriteByte(0x14014B, 0x01)); // Enable mosaic
|
||||
|
||||
ASSERT_OK(rom->WriteByte(0x140146, 0x01)); // Enable main palettes
|
||||
ASSERT_OK(rom->WriteByte(0x140147, 0x01)); // Enable area-specific BG
|
||||
ASSERT_OK(rom->WriteByte(0x140148, 0x01)); // Enable subscreen overlay
|
||||
ASSERT_OK(rom->WriteByte(0x140149, 0x01)); // Enable animated GFX
|
||||
ASSERT_OK(rom->WriteByte(0x14014A, 0x01)); // Enable custom tile GFX groups
|
||||
ASSERT_OK(rom->WriteByte(0x14014B, 0x01)); // Enable mosaic
|
||||
|
||||
// Save the modified ROM
|
||||
ASSERT_OK(rom->SaveToFile(Rom::SaveSettings{.filename = edited_test_path_}));
|
||||
|
||||
|
||||
// Reload and validate
|
||||
std::unique_ptr<Rom> reloaded_rom = std::make_unique<Rom>();
|
||||
ASSERT_OK(reloaded_rom->LoadFromFile(edited_test_path_));
|
||||
|
||||
|
||||
// Validate ASM version was applied
|
||||
auto asm_version = reloaded_rom->ReadByte(0x140145);
|
||||
ASSERT_TRUE(asm_version.ok());
|
||||
EXPECT_EQ(*asm_version, 0x03);
|
||||
|
||||
|
||||
// Validate feature flags
|
||||
auto main_palettes = reloaded_rom->ReadByte(0x140146);
|
||||
auto area_bg = reloaded_rom->ReadByte(0x140147);
|
||||
@@ -188,26 +192,26 @@ TEST_F(OverworldE2ETest, ApplyZSCustomOverworldV3) {
|
||||
auto animated_gfx = reloaded_rom->ReadByte(0x140149);
|
||||
auto custom_tiles = reloaded_rom->ReadByte(0x14014A);
|
||||
auto mosaic = reloaded_rom->ReadByte(0x14014B);
|
||||
|
||||
|
||||
ASSERT_TRUE(main_palettes.ok());
|
||||
ASSERT_TRUE(area_bg.ok());
|
||||
ASSERT_TRUE(subscreen_overlay.ok());
|
||||
ASSERT_TRUE(animated_gfx.ok());
|
||||
ASSERT_TRUE(custom_tiles.ok());
|
||||
ASSERT_TRUE(mosaic.ok());
|
||||
|
||||
|
||||
EXPECT_EQ(*main_palettes, 0x01);
|
||||
EXPECT_EQ(*area_bg, 0x01);
|
||||
EXPECT_EQ(*subscreen_overlay, 0x01);
|
||||
EXPECT_EQ(*animated_gfx, 0x01);
|
||||
EXPECT_EQ(*custom_tiles, 0x01);
|
||||
EXPECT_EQ(*mosaic, 0x01);
|
||||
|
||||
|
||||
// Load overworld and validate v3 features are detected
|
||||
zelda3::Overworld overworld(reloaded_rom.get());
|
||||
auto status = overworld.Load(reloaded_rom.get());
|
||||
ASSERT_TRUE(status.ok());
|
||||
|
||||
|
||||
// v3 should have expanded features available
|
||||
EXPECT_TRUE(overworld.expanded_tile16());
|
||||
EXPECT_TRUE(overworld.expanded_tile32());
|
||||
@@ -217,37 +221,37 @@ TEST_F(OverworldE2ETest, ApplyZSCustomOverworldV3) {
|
||||
TEST_F(OverworldE2ETest, OverworldEditPersistence) {
|
||||
std::unique_ptr<Rom> rom = std::make_unique<Rom>();
|
||||
ASSERT_OK(rom->LoadFromFile(vanilla_test_path_));
|
||||
|
||||
|
||||
// Load overworld
|
||||
zelda3::Overworld overworld(rom.get());
|
||||
auto status = overworld.Load(rom.get());
|
||||
ASSERT_TRUE(status.ok());
|
||||
|
||||
|
||||
// Make some edits to overworld maps
|
||||
auto* map0 = overworld.mutable_overworld_map(0);
|
||||
uint8_t original_gfx = map0->area_graphics();
|
||||
uint8_t original_palette = map0->main_palette();
|
||||
|
||||
|
||||
// Change graphics and palette
|
||||
map0->set_area_graphics(0x01);
|
||||
map0->set_main_palette(0x02);
|
||||
|
||||
|
||||
// Save the changes
|
||||
auto save_maps_status = overworld.SaveOverworldMaps();
|
||||
ASSERT_TRUE(save_maps_status.ok());
|
||||
auto save_props_status = overworld.SaveMapProperties();
|
||||
ASSERT_TRUE(save_props_status.ok());
|
||||
|
||||
|
||||
// Save ROM
|
||||
ASSERT_OK(rom->SaveToFile(Rom::SaveSettings{.filename = edited_test_path_}));
|
||||
|
||||
|
||||
// Reload ROM and validate changes persisted
|
||||
std::unique_ptr<Rom> reloaded_rom = std::make_unique<Rom>();
|
||||
ASSERT_OK(reloaded_rom->LoadFromFile(edited_test_path_));
|
||||
|
||||
|
||||
zelda3::Overworld reloaded_overworld(reloaded_rom.get());
|
||||
ASSERT_OK(reloaded_overworld.Load(reloaded_rom.get()));
|
||||
|
||||
|
||||
const auto& reloaded_map0 = reloaded_overworld.overworld_map(0);
|
||||
EXPECT_EQ(reloaded_map0->area_graphics(), 0x01);
|
||||
EXPECT_EQ(reloaded_map0->main_palette(), 0x02);
|
||||
@@ -257,48 +261,52 @@ TEST_F(OverworldE2ETest, OverworldEditPersistence) {
|
||||
TEST_F(OverworldE2ETest, CoordinateCalculationValidation) {
|
||||
std::unique_ptr<Rom> rom = std::make_unique<Rom>();
|
||||
ASSERT_OK(rom->LoadFromFile(vanilla_test_path_));
|
||||
|
||||
|
||||
zelda3::Overworld overworld(rom.get());
|
||||
ASSERT_OK(overworld.Load(rom.get()));
|
||||
|
||||
|
||||
const auto& entrances = overworld.entrances();
|
||||
EXPECT_EQ(entrances.size(), 129);
|
||||
|
||||
|
||||
// Test coordinate calculation for first 10 entrances
|
||||
for (int i = 0; i < std::min(10, static_cast<int>(entrances.size())); i++) {
|
||||
const auto& entrance = entrances[i];
|
||||
|
||||
|
||||
// ZScream coordinate calculation logic
|
||||
uint16_t map_pos = entrance.map_pos_;
|
||||
uint16_t map_id = entrance.map_id_;
|
||||
|
||||
|
||||
int position = map_pos >> 1;
|
||||
int x_coord = position % 64;
|
||||
int y_coord = position >> 6;
|
||||
int expected_x = (x_coord * 16) + (((map_id % 64) - (((map_id % 64) / 8) * 8)) * 512);
|
||||
int expected_x =
|
||||
(x_coord * 16) + (((map_id % 64) - (((map_id % 64) / 8) * 8)) * 512);
|
||||
int expected_y = (y_coord * 16) + (((map_id % 64) / 8) * 512);
|
||||
|
||||
EXPECT_EQ(entrance.x_, expected_x) << "Entrance " << i << " X coordinate mismatch";
|
||||
EXPECT_EQ(entrance.y_, expected_y) << "Entrance " << i << " Y coordinate mismatch";
|
||||
|
||||
EXPECT_EQ(entrance.x_, expected_x)
|
||||
<< "Entrance " << i << " X coordinate mismatch";
|
||||
EXPECT_EQ(entrance.y_, expected_y)
|
||||
<< "Entrance " << i << " Y coordinate mismatch";
|
||||
}
|
||||
|
||||
|
||||
// Test hole coordinate calculation with 0x400 offset
|
||||
const auto& holes = overworld.holes();
|
||||
EXPECT_EQ(holes.size(), 0x13);
|
||||
|
||||
|
||||
for (int i = 0; i < std::min(5, static_cast<int>(holes.size())); i++) {
|
||||
const auto& hole = holes[i];
|
||||
|
||||
|
||||
// ZScream hole coordinate calculation with 0x400 offset
|
||||
uint16_t map_pos = hole.map_pos_;
|
||||
uint16_t map_id = hole.map_id_;
|
||||
|
||||
|
||||
int position = map_pos >> 1;
|
||||
int x_coord = position % 64;
|
||||
int y_coord = position >> 6;
|
||||
int expected_x = (x_coord * 16) + (((map_id % 64) - (((map_id % 64) / 8) * 8)) * 512);
|
||||
int expected_x =
|
||||
(x_coord * 16) + (((map_id % 64) - (((map_id % 64) / 8) * 8)) * 512);
|
||||
int expected_y = (y_coord * 16) + (((map_id % 64) / 8) * 512);
|
||||
|
||||
|
||||
EXPECT_EQ(hole.x_, expected_x) << "Hole " << i << " X coordinate mismatch";
|
||||
EXPECT_EQ(hole.y_, expected_y) << "Hole " << i << " Y coordinate mismatch";
|
||||
EXPECT_TRUE(hole.is_hole_) << "Hole " << i << " should be marked as hole";
|
||||
@@ -309,48 +317,52 @@ TEST_F(OverworldE2ETest, CoordinateCalculationValidation) {
|
||||
TEST_F(OverworldE2ETest, BeforeAfterValidation) {
|
||||
// Extract golden data from vanilla ROM
|
||||
ASSERT_OK(ExtractGoldenData(vanilla_test_path_, golden_data_path_));
|
||||
|
||||
|
||||
// Load vanilla ROM and make some changes
|
||||
std::unique_ptr<Rom> vanilla_rom = std::make_unique<Rom>();
|
||||
ASSERT_OK(vanilla_rom->LoadFromFile(vanilla_test_path_));
|
||||
|
||||
|
||||
// Store some original values for comparison
|
||||
auto original_asm_version = vanilla_rom->ReadByte(0x140145);
|
||||
auto original_graphics_0 = vanilla_rom->ReadByte(0x7C9C); // First map graphics
|
||||
auto original_palette_0 = vanilla_rom->ReadByte(0x7D1C); // First map palette
|
||||
|
||||
auto original_graphics_0 =
|
||||
vanilla_rom->ReadByte(0x7C9C); // First map graphics
|
||||
auto original_palette_0 = vanilla_rom->ReadByte(0x7D1C); // First map palette
|
||||
|
||||
ASSERT_TRUE(original_asm_version.ok());
|
||||
ASSERT_TRUE(original_graphics_0.ok());
|
||||
ASSERT_TRUE(original_palette_0.ok());
|
||||
|
||||
|
||||
// Make changes
|
||||
auto write1 = vanilla_rom->WriteByte(0x140145, 0x03); // Apply v3 ASM
|
||||
auto write1 = vanilla_rom->WriteByte(0x140145, 0x03); // Apply v3 ASM
|
||||
ASSERT_TRUE(write1.ok());
|
||||
auto write2 = vanilla_rom->WriteByte(0x7C9C, 0x01); // Change first map graphics
|
||||
auto write2 =
|
||||
vanilla_rom->WriteByte(0x7C9C, 0x01); // Change first map graphics
|
||||
ASSERT_TRUE(write2.ok());
|
||||
auto write3 = vanilla_rom->WriteByte(0x7D1C, 0x02); // Change first map palette
|
||||
auto write3 =
|
||||
vanilla_rom->WriteByte(0x7D1C, 0x02); // Change first map palette
|
||||
ASSERT_TRUE(write3.ok());
|
||||
|
||||
|
||||
// Save modified ROM
|
||||
ASSERT_OK(vanilla_rom->SaveToFile(Rom::SaveSettings{.filename = edited_test_path_}));
|
||||
|
||||
ASSERT_OK(vanilla_rom->SaveToFile(
|
||||
Rom::SaveSettings{.filename = edited_test_path_}));
|
||||
|
||||
// Reload and validate changes
|
||||
std::unique_ptr<Rom> modified_rom = std::make_unique<Rom>();
|
||||
ASSERT_OK(modified_rom->LoadFromFile(edited_test_path_));
|
||||
|
||||
|
||||
auto modified_asm_version = modified_rom->ReadByte(0x140145);
|
||||
auto modified_graphics_0 = modified_rom->ReadByte(0x7C9C);
|
||||
auto modified_palette_0 = modified_rom->ReadByte(0x7D1C);
|
||||
|
||||
|
||||
ASSERT_TRUE(modified_asm_version.ok());
|
||||
ASSERT_TRUE(modified_graphics_0.ok());
|
||||
ASSERT_TRUE(modified_palette_0.ok());
|
||||
|
||||
|
||||
// Validate changes were applied
|
||||
EXPECT_EQ(*modified_asm_version, 0x03);
|
||||
EXPECT_EQ(*modified_graphics_0, 0x01);
|
||||
EXPECT_EQ(*modified_palette_0, 0x02);
|
||||
|
||||
|
||||
// Validate original values were different
|
||||
EXPECT_NE(*original_asm_version, *modified_asm_version);
|
||||
EXPECT_NE(*original_graphics_0, *modified_graphics_0);
|
||||
@@ -361,37 +373,37 @@ TEST_F(OverworldE2ETest, BeforeAfterValidation) {
|
||||
TEST_F(OverworldE2ETest, RomDependentTestSuiteIntegration) {
|
||||
std::unique_ptr<Rom> rom = std::make_unique<Rom>();
|
||||
ASSERT_OK(rom->LoadFromFile(vanilla_test_path_));
|
||||
|
||||
|
||||
// Test that our overworld loading works with RomDependentTestSuite patterns
|
||||
zelda3::Overworld overworld(rom.get());
|
||||
auto status = overworld.Load(rom.get());
|
||||
ASSERT_TRUE(status.ok());
|
||||
|
||||
|
||||
// Validate ROM-dependent features work correctly
|
||||
EXPECT_TRUE(overworld.is_loaded());
|
||||
|
||||
|
||||
const auto& maps = overworld.overworld_maps();
|
||||
EXPECT_EQ(maps.size(), 160);
|
||||
|
||||
|
||||
// Test that we can access the same data structures as RomDependentTestSuite
|
||||
for (int i = 0; i < std::min(10, static_cast<int>(maps.size())); i++) {
|
||||
const auto& map = maps[i];
|
||||
|
||||
|
||||
// Verify map properties are accessible
|
||||
EXPECT_GE(map.area_graphics(), 0);
|
||||
EXPECT_GE(map.main_palette(), 0);
|
||||
EXPECT_GE(map.area_size(), zelda3::AreaSizeEnum::SmallArea);
|
||||
EXPECT_LE(map.area_size(), zelda3::AreaSizeEnum::TallArea);
|
||||
}
|
||||
|
||||
|
||||
// Test that sprite data is accessible (matches RomDependentTestSuite expectations)
|
||||
const auto& sprites = overworld.all_sprites();
|
||||
EXPECT_EQ(sprites.size(), 3); // Three game states
|
||||
|
||||
EXPECT_EQ(sprites.size(), 3); // Three game states
|
||||
|
||||
// Test that item data is accessible
|
||||
const auto& items = overworld.all_items();
|
||||
EXPECT_GE(items.size(), 0);
|
||||
|
||||
|
||||
// Test that entrance/exit data is accessible
|
||||
const auto& entrances = overworld.entrances();
|
||||
const auto& exits = overworld.exits();
|
||||
@@ -403,20 +415,21 @@ TEST_F(OverworldE2ETest, RomDependentTestSuiteIntegration) {
|
||||
TEST_F(OverworldE2ETest, PerformanceAndStability) {
|
||||
std::unique_ptr<Rom> rom = std::make_unique<Rom>();
|
||||
ASSERT_OK(rom->LoadFromFile(vanilla_test_path_));
|
||||
|
||||
|
||||
// Test multiple load/unload cycles
|
||||
for (int cycle = 0; cycle < 5; cycle++) {
|
||||
zelda3::Overworld overworld(rom.get());
|
||||
auto status = overworld.Load(rom.get());
|
||||
ASSERT_TRUE(status.ok()) << "Load failed on cycle " << cycle;
|
||||
|
||||
|
||||
// Validate basic structure
|
||||
const auto& maps = overworld.overworld_maps();
|
||||
EXPECT_EQ(maps.size(), 160) << "Map count mismatch on cycle " << cycle;
|
||||
|
||||
|
||||
const auto& entrances = overworld.entrances();
|
||||
EXPECT_EQ(entrances.size(), 129) << "Entrance count mismatch on cycle " << cycle;
|
||||
|
||||
EXPECT_EQ(entrances.size(), 129)
|
||||
<< "Entrance count mismatch on cycle " << cycle;
|
||||
|
||||
const auto& exits = overworld.exits();
|
||||
EXPECT_EQ(exits->size(), 0x4F) << "Exit count mismatch on cycle " << cycle;
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "app/rom.h"
|
||||
#include "app/transaction.h"
|
||||
@@ -33,7 +33,7 @@ class E2ERomDependentTest : public ::testing::Test {
|
||||
// Get ROM path from environment or use default
|
||||
const char* rom_path_env = getenv("YAZE_TEST_ROM_PATH");
|
||||
vanilla_rom_path_ = rom_path_env ? rom_path_env : "zelda3.sfc";
|
||||
|
||||
|
||||
if (!std::filesystem::exists(vanilla_rom_path_)) {
|
||||
GTEST_SKIP() << "Test ROM not found: " << vanilla_rom_path_;
|
||||
}
|
||||
@@ -41,7 +41,7 @@ class E2ERomDependentTest : public ::testing::Test {
|
||||
// Create test ROM copies
|
||||
test_rom_path_ = "test_rom_edit.sfc";
|
||||
backup_rom_path_ = "test_rom_backup.sfc";
|
||||
|
||||
|
||||
// Copy vanilla ROM for testing
|
||||
std::filesystem::copy_file(vanilla_rom_path_, test_rom_path_);
|
||||
std::filesystem::copy_file(vanilla_rom_path_, backup_rom_path_);
|
||||
@@ -58,51 +58,53 @@ class E2ERomDependentTest : public ::testing::Test {
|
||||
}
|
||||
|
||||
// Helper to load ROM and verify basic integrity
|
||||
static absl::Status LoadAndVerifyROM(const std::string& path, std::unique_ptr<Rom>& rom) {
|
||||
static absl::Status LoadAndVerifyROM(const std::string& path,
|
||||
std::unique_ptr<Rom>& rom) {
|
||||
rom = std::make_unique<Rom>();
|
||||
RETURN_IF_ERROR(rom->LoadFromFile(path));
|
||||
|
||||
|
||||
// Basic ROM integrity checks
|
||||
EXPECT_EQ(rom->size(), 0x200000) << "ROM size should be 2MB";
|
||||
EXPECT_NE(rom->data(), nullptr) << "ROM data should not be null";
|
||||
|
||||
|
||||
// Check ROM header
|
||||
auto header_byte = rom->ReadByte(0x7FC0);
|
||||
RETURN_IF_ERROR(header_byte.status());
|
||||
EXPECT_EQ(*header_byte, 0x21) << "ROM should be LoROM format";
|
||||
|
||||
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
// Helper to verify ROM data integrity by comparing checksums
|
||||
static bool VerifyROMIntegrity(const std::string& path1, const std::string& path2,
|
||||
const std::vector<uint32_t>& exclude_ranges = {}) {
|
||||
static bool VerifyROMIntegrity(
|
||||
const std::string& path1, const std::string& path2,
|
||||
const std::vector<uint32_t>& exclude_ranges = {}) {
|
||||
std::ifstream file1(path1, std::ios::binary);
|
||||
std::ifstream file2(path2, std::ios::binary);
|
||||
|
||||
|
||||
if (!file1.is_open() || !file2.is_open()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
file1.seekg(0, std::ios::end);
|
||||
file2.seekg(0, std::ios::end);
|
||||
|
||||
|
||||
size_t size1 = file1.tellg();
|
||||
size_t size2 = file2.tellg();
|
||||
|
||||
|
||||
if (size1 != size2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
file1.seekg(0);
|
||||
file2.seekg(0);
|
||||
|
||||
|
||||
std::vector<char> buffer1(size1);
|
||||
std::vector<char> buffer2(size2);
|
||||
|
||||
|
||||
file1.read(buffer1.data(), size1);
|
||||
file2.read(buffer2.data(), size2);
|
||||
|
||||
|
||||
// Compare byte by byte, excluding specified ranges
|
||||
for (size_t i = 0; i < size1; i++) {
|
||||
bool in_exclude_range = false;
|
||||
@@ -112,12 +114,12 @@ class E2ERomDependentTest : public ::testing::Test {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!in_exclude_range && buffer1[i] != buffer2[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -130,10 +132,10 @@ class E2ERomDependentTest : public ::testing::Test {
|
||||
TEST_F(E2ERomDependentTest, BasicROMLoadSave) {
|
||||
std::unique_ptr<Rom> rom;
|
||||
ASSERT_OK(LoadAndVerifyROM(vanilla_rom_path_, rom));
|
||||
|
||||
|
||||
// Save ROM to test path
|
||||
ASSERT_OK(rom->SaveToFile(Rom::SaveSettings{.filename = test_rom_path_}));
|
||||
|
||||
|
||||
// Verify saved ROM matches original
|
||||
EXPECT_TRUE(VerifyROMIntegrity(vanilla_rom_path_, test_rom_path_));
|
||||
}
|
||||
@@ -142,35 +144,35 @@ TEST_F(E2ERomDependentTest, BasicROMLoadSave) {
|
||||
TEST_F(E2ERomDependentTest, ROMDataEditWorkflow) {
|
||||
std::unique_ptr<Rom> rom;
|
||||
ASSERT_OK(LoadAndVerifyROM(vanilla_rom_path_, rom));
|
||||
|
||||
|
||||
// Get initial state
|
||||
auto initial_byte = rom->ReadByte(0x1000);
|
||||
ASSERT_TRUE(initial_byte.ok());
|
||||
|
||||
|
||||
// Make edits
|
||||
ASSERT_OK(rom->WriteByte(0x1000, 0xAA));
|
||||
ASSERT_OK(rom->WriteByte(0x2000, 0xBB));
|
||||
ASSERT_OK(rom->WriteWord(0x3000, 0xCCDD));
|
||||
|
||||
|
||||
// Save changes
|
||||
ASSERT_OK(rom->SaveToFile(Rom::SaveSettings{.filename = test_rom_path_}));
|
||||
|
||||
|
||||
// Reload and verify
|
||||
std::unique_ptr<Rom> reloaded_rom;
|
||||
ASSERT_OK(LoadAndVerifyROM(test_rom_path_, reloaded_rom));
|
||||
|
||||
|
||||
auto byte1 = reloaded_rom->ReadByte(0x1000);
|
||||
ASSERT_OK(byte1.status());
|
||||
EXPECT_EQ(*byte1, 0xAA);
|
||||
|
||||
|
||||
auto byte2 = reloaded_rom->ReadByte(0x2000);
|
||||
ASSERT_OK(byte2.status());
|
||||
EXPECT_EQ(*byte2, 0xBB);
|
||||
|
||||
|
||||
auto word1 = reloaded_rom->ReadWord(0x3000);
|
||||
ASSERT_OK(word1.status());
|
||||
EXPECT_EQ(*word1, 0xCCDD);
|
||||
|
||||
|
||||
// Verify other data wasn't corrupted
|
||||
EXPECT_NE(*byte1, *initial_byte);
|
||||
}
|
||||
@@ -179,36 +181,36 @@ TEST_F(E2ERomDependentTest, ROMDataEditWorkflow) {
|
||||
TEST_F(E2ERomDependentTest, TransactionSystem) {
|
||||
std::unique_ptr<Rom> rom;
|
||||
ASSERT_OK(LoadAndVerifyROM(vanilla_rom_path_, rom));
|
||||
|
||||
|
||||
// Create transaction
|
||||
auto transaction = std::make_unique<yaze::Transaction>(*rom);
|
||||
|
||||
|
||||
// Make multiple edits in transaction
|
||||
transaction->WriteByte(0x1000, 0xAA);
|
||||
transaction->WriteByte(0x2000, 0xBB);
|
||||
transaction->WriteWord(0x3000, 0xCCDD);
|
||||
|
||||
|
||||
// Commit the transaction
|
||||
ASSERT_OK(transaction->Commit());
|
||||
|
||||
|
||||
// Commit transaction
|
||||
ASSERT_OK(transaction->Commit());
|
||||
|
||||
|
||||
// Save ROM
|
||||
ASSERT_OK(rom->SaveToFile(Rom::SaveSettings{.filename = test_rom_path_}));
|
||||
|
||||
|
||||
// Reload and verify all changes
|
||||
std::unique_ptr<Rom> reloaded_rom;
|
||||
ASSERT_OK(LoadAndVerifyROM(test_rom_path_, reloaded_rom));
|
||||
|
||||
|
||||
auto byte1 = reloaded_rom->ReadByte(0x1000);
|
||||
ASSERT_OK(byte1.status());
|
||||
EXPECT_EQ(*byte1, 0xAA);
|
||||
|
||||
|
||||
auto byte2 = reloaded_rom->ReadByte(0x2000);
|
||||
ASSERT_OK(byte2.status());
|
||||
EXPECT_EQ(*byte2, 0xBB);
|
||||
|
||||
|
||||
auto word1 = reloaded_rom->ReadWord(0x3000);
|
||||
ASSERT_OK(word1.status());
|
||||
EXPECT_EQ(*word1, 0xCCDD);
|
||||
@@ -218,22 +220,22 @@ TEST_F(E2ERomDependentTest, TransactionSystem) {
|
||||
TEST_F(E2ERomDependentTest, CorruptionDetection) {
|
||||
std::unique_ptr<Rom> rom;
|
||||
ASSERT_OK(LoadAndVerifyROM(vanilla_rom_path_, rom));
|
||||
|
||||
|
||||
// Corrupt some data
|
||||
ASSERT_OK(rom->WriteByte(0x1000, 0xFF)); // Corrupt some data
|
||||
ASSERT_OK(rom->WriteByte(0x2000, 0xAA)); // Corrupt more data
|
||||
|
||||
|
||||
// Save corrupted ROM
|
||||
ASSERT_OK(rom->SaveToFile(Rom::SaveSettings{.filename = test_rom_path_}));
|
||||
|
||||
|
||||
// Verify corruption is detected
|
||||
std::unique_ptr<Rom> reloaded_rom;
|
||||
ASSERT_OK(LoadAndVerifyROM(test_rom_path_, reloaded_rom));
|
||||
|
||||
|
||||
auto corrupt_byte1 = reloaded_rom->ReadByte(0x1000);
|
||||
ASSERT_OK(corrupt_byte1.status());
|
||||
EXPECT_EQ(*corrupt_byte1, 0xFF);
|
||||
|
||||
|
||||
auto corrupt_byte2 = reloaded_rom->ReadByte(0x2000);
|
||||
ASSERT_OK(corrupt_byte2.status());
|
||||
EXPECT_EQ(*corrupt_byte2, 0xAA);
|
||||
@@ -243,25 +245,25 @@ TEST_F(E2ERomDependentTest, CorruptionDetection) {
|
||||
TEST_F(E2ERomDependentTest, LargeScaleEditing) {
|
||||
std::unique_ptr<Rom> rom;
|
||||
ASSERT_OK(LoadAndVerifyROM(vanilla_rom_path_, rom));
|
||||
|
||||
|
||||
// Edit multiple areas
|
||||
for (int i = 0; i < 10; i++) {
|
||||
ASSERT_OK(rom->WriteByte(0x1000 + i, i % 16));
|
||||
ASSERT_OK(rom->WriteByte(0x2000 + i, (i + 1) % 16));
|
||||
}
|
||||
|
||||
|
||||
// Save and reload
|
||||
ASSERT_OK(rom->SaveToFile(Rom::SaveSettings{.filename = test_rom_path_}));
|
||||
|
||||
|
||||
std::unique_ptr<Rom> reloaded_rom;
|
||||
ASSERT_OK(LoadAndVerifyROM(test_rom_path_, reloaded_rom));
|
||||
|
||||
|
||||
// Verify all changes
|
||||
for (int i = 0; i < 10; i++) {
|
||||
auto byte1 = reloaded_rom->ReadByte(0x1000 + i);
|
||||
ASSERT_OK(byte1.status());
|
||||
EXPECT_EQ(*byte1, i % 16);
|
||||
|
||||
|
||||
auto byte2 = reloaded_rom->ReadByte(0x2000 + i);
|
||||
ASSERT_OK(byte2.status());
|
||||
EXPECT_EQ(*byte2, (i + 1) % 16);
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <filesystem>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "app/rom.h"
|
||||
#include "testing.h"
|
||||
@@ -32,7 +32,7 @@ class ZSCustomOverworldUpgradeTest : public ::testing::Test {
|
||||
// Get ROM path from environment or use default
|
||||
const char* rom_path_env = getenv("YAZE_TEST_ROM_PATH");
|
||||
vanilla_rom_path_ = rom_path_env ? rom_path_env : "zelda3.sfc";
|
||||
|
||||
|
||||
if (!std::filesystem::exists(vanilla_rom_path_)) {
|
||||
GTEST_SKIP() << "Test ROM not found: " << vanilla_rom_path_;
|
||||
}
|
||||
@@ -41,20 +41,19 @@ class ZSCustomOverworldUpgradeTest : public ::testing::Test {
|
||||
vanilla_test_path_ = "test_vanilla.sfc";
|
||||
v2_test_path_ = "test_v2.sfc";
|
||||
v3_test_path_ = "test_v3.sfc";
|
||||
|
||||
|
||||
// Copy vanilla ROM for testing
|
||||
std::filesystem::copy_file(vanilla_rom_path_, vanilla_test_path_);
|
||||
|
||||
|
||||
// Define version-specific addresses and features
|
||||
InitializeVersionData();
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
// Clean up test files
|
||||
std::vector<std::string> test_files = {
|
||||
vanilla_test_path_, v2_test_path_, v3_test_path_
|
||||
};
|
||||
|
||||
std::vector<std::string> test_files = {vanilla_test_path_, v2_test_path_,
|
||||
v3_test_path_};
|
||||
|
||||
for (const auto& file : test_files) {
|
||||
if (std::filesystem::exists(file)) {
|
||||
std::filesystem::remove(file);
|
||||
@@ -65,41 +64,41 @@ class ZSCustomOverworldUpgradeTest : public ::testing::Test {
|
||||
void InitializeVersionData() {
|
||||
// Vanilla ROM addresses and values
|
||||
vanilla_data_ = {
|
||||
{"version_flag", {0x140145, 0xFF}}, // OverworldCustomASMHasBeenApplied
|
||||
{"message_ids", {0x3F51D, 0x00}}, // Message ID table start
|
||||
{"area_graphics", {0x7C9C, 0x00}}, // Area graphics table
|
||||
{"area_palettes", {0x7D1C, 0x00}}, // Area palettes table
|
||||
{"screen_sizes", {0x1788D, 0x01}}, // Screen sizes table
|
||||
{"sprite_sets", {0x7A41, 0x00}}, // Sprite sets table
|
||||
{"sprite_palettes", {0x7B41, 0x00}}, // Sprite palettes table
|
||||
{"version_flag", {0x140145, 0xFF}}, // OverworldCustomASMHasBeenApplied
|
||||
{"message_ids", {0x3F51D, 0x00}}, // Message ID table start
|
||||
{"area_graphics", {0x7C9C, 0x00}}, // Area graphics table
|
||||
{"area_palettes", {0x7D1C, 0x00}}, // Area palettes table
|
||||
{"screen_sizes", {0x1788D, 0x01}}, // Screen sizes table
|
||||
{"sprite_sets", {0x7A41, 0x00}}, // Sprite sets table
|
||||
{"sprite_palettes", {0x7B41, 0x00}}, // Sprite palettes table
|
||||
};
|
||||
|
||||
// v2 ROM addresses and values
|
||||
v2_data_ = {
|
||||
{"version_flag", {0x140145, 0x02}}, // v2 version
|
||||
{"message_ids", {0x1417F8, 0x00}}, // Expanded message ID table
|
||||
{"area_graphics", {0x7C9C, 0x00}}, // Same as vanilla
|
||||
{"area_palettes", {0x7D1C, 0x00}}, // Same as vanilla
|
||||
{"screen_sizes", {0x1788D, 0x01}}, // Same as vanilla
|
||||
{"sprite_sets", {0x7A41, 0x00}}, // Same as vanilla
|
||||
{"sprite_palettes", {0x7B41, 0x00}}, // Same as vanilla
|
||||
{"main_palettes", {0x140160, 0x00}}, // New v2 feature
|
||||
{"version_flag", {0x140145, 0x02}}, // v2 version
|
||||
{"message_ids", {0x1417F8, 0x00}}, // Expanded message ID table
|
||||
{"area_graphics", {0x7C9C, 0x00}}, // Same as vanilla
|
||||
{"area_palettes", {0x7D1C, 0x00}}, // Same as vanilla
|
||||
{"screen_sizes", {0x1788D, 0x01}}, // Same as vanilla
|
||||
{"sprite_sets", {0x7A41, 0x00}}, // Same as vanilla
|
||||
{"sprite_palettes", {0x7B41, 0x00}}, // Same as vanilla
|
||||
{"main_palettes", {0x140160, 0x00}}, // New v2 feature
|
||||
};
|
||||
|
||||
// v3 ROM addresses and values
|
||||
v3_data_ = {
|
||||
{"version_flag", {0x140145, 0x03}}, // v3 version
|
||||
{"message_ids", {0x1417F8, 0x00}}, // Same as v2
|
||||
{"area_graphics", {0x7C9C, 0x00}}, // Same as vanilla
|
||||
{"area_palettes", {0x7D1C, 0x00}}, // Same as vanilla
|
||||
{"screen_sizes", {0x1788D, 0x01}}, // Same as vanilla
|
||||
{"sprite_sets", {0x7A41, 0x00}}, // Same as vanilla
|
||||
{"sprite_palettes", {0x7B41, 0x00}}, // Same as vanilla
|
||||
{"main_palettes", {0x140160, 0x00}}, // Same as v2
|
||||
{"bg_colors", {0x140000, 0x00}}, // New v3 feature
|
||||
{"subscreen_overlays", {0x140340, 0x00}}, // New v3 feature
|
||||
{"animated_gfx", {0x1402A0, 0x00}}, // New v3 feature
|
||||
{"custom_tiles", {0x140480, 0x00}}, // New v3 feature
|
||||
{"version_flag", {0x140145, 0x03}}, // v3 version
|
||||
{"message_ids", {0x1417F8, 0x00}}, // Same as v2
|
||||
{"area_graphics", {0x7C9C, 0x00}}, // Same as vanilla
|
||||
{"area_palettes", {0x7D1C, 0x00}}, // Same as vanilla
|
||||
{"screen_sizes", {0x1788D, 0x01}}, // Same as vanilla
|
||||
{"sprite_sets", {0x7A41, 0x00}}, // Same as vanilla
|
||||
{"sprite_palettes", {0x7B41, 0x00}}, // Same as vanilla
|
||||
{"main_palettes", {0x140160, 0x00}}, // Same as v2
|
||||
{"bg_colors", {0x140000, 0x00}}, // New v3 feature
|
||||
{"subscreen_overlays", {0x140340, 0x00}}, // New v3 feature
|
||||
{"animated_gfx", {0x1402A0, 0x00}}, // New v3 feature
|
||||
{"custom_tiles", {0x140480, 0x00}}, // New v3 feature
|
||||
};
|
||||
}
|
||||
|
||||
@@ -120,15 +119,18 @@ class ZSCustomOverworldUpgradeTest : public ::testing::Test {
|
||||
// Apply version-specific features
|
||||
if (version == "v2") {
|
||||
// Enable v2 features
|
||||
RETURN_IF_ERROR(rom.WriteByte(0x140146, 0x01)); // Enable main palettes
|
||||
RETURN_IF_ERROR(rom.WriteByte(0x140146, 0x01)); // Enable main palettes
|
||||
} else if (version == "v3") {
|
||||
// Enable v3 features
|
||||
RETURN_IF_ERROR(rom.WriteByte(0x140146, 0x01)); // Enable main palettes
|
||||
RETURN_IF_ERROR(rom.WriteByte(0x140147, 0x01)); // Enable area-specific BG
|
||||
RETURN_IF_ERROR(rom.WriteByte(0x140148, 0x01)); // Enable subscreen overlay
|
||||
RETURN_IF_ERROR(rom.WriteByte(0x140149, 0x01)); // Enable animated GFX
|
||||
RETURN_IF_ERROR(rom.WriteByte(0x14014A, 0x01)); // Enable custom tile GFX groups
|
||||
RETURN_IF_ERROR(rom.WriteByte(0x14014B, 0x01)); // Enable mosaic
|
||||
RETURN_IF_ERROR(rom.WriteByte(0x140146, 0x01)); // Enable main palettes
|
||||
RETURN_IF_ERROR(
|
||||
rom.WriteByte(0x140147, 0x01)); // Enable area-specific BG
|
||||
RETURN_IF_ERROR(
|
||||
rom.WriteByte(0x140148, 0x01)); // Enable subscreen overlay
|
||||
RETURN_IF_ERROR(rom.WriteByte(0x140149, 0x01)); // Enable animated GFX
|
||||
RETURN_IF_ERROR(
|
||||
rom.WriteByte(0x14014A, 0x01)); // Enable custom tile GFX groups
|
||||
RETURN_IF_ERROR(rom.WriteByte(0x14014B, 0x01)); // Enable mosaic
|
||||
}
|
||||
|
||||
return absl::OkStatus();
|
||||
@@ -157,7 +159,7 @@ class ZSCustomOverworldUpgradeTest : public ::testing::Test {
|
||||
std::string vanilla_test_path_;
|
||||
std::string v2_test_path_;
|
||||
std::string v3_test_path_;
|
||||
|
||||
|
||||
std::map<std::string, std::pair<uint32_t, uint8_t>> vanilla_data_;
|
||||
std::map<std::string, std::pair<uint32_t, uint8_t>> v2_data_;
|
||||
std::map<std::string, std::pair<uint32_t, uint8_t>> v3_data_;
|
||||
@@ -167,10 +169,10 @@ class ZSCustomOverworldUpgradeTest : public ::testing::Test {
|
||||
TEST_F(ZSCustomOverworldUpgradeTest, VanillaBaseline) {
|
||||
std::unique_ptr<Rom> rom = std::make_unique<Rom>();
|
||||
ASSERT_OK(rom->LoadFromFile(vanilla_test_path_));
|
||||
|
||||
|
||||
// Validate vanilla addresses
|
||||
EXPECT_TRUE(ValidateVersionAddresses(*rom, "vanilla"));
|
||||
|
||||
|
||||
// Verify version flag
|
||||
auto version_byte = rom->ReadByte(0x140145);
|
||||
ASSERT_TRUE(version_byte.ok());
|
||||
@@ -182,20 +184,20 @@ TEST_F(ZSCustomOverworldUpgradeTest, VanillaToV2Upgrade) {
|
||||
// Load vanilla ROM
|
||||
std::unique_ptr<Rom> rom = std::make_unique<Rom>();
|
||||
ASSERT_OK(rom->LoadFromFile(vanilla_test_path_));
|
||||
|
||||
|
||||
// Apply v2 patch
|
||||
ASSERT_OK(ApplyVersionPatch(*rom, "v2"));
|
||||
|
||||
|
||||
// Validate v2 addresses
|
||||
EXPECT_TRUE(ValidateVersionAddresses(*rom, "v2"));
|
||||
|
||||
|
||||
// Save v2 ROM
|
||||
ASSERT_OK(rom->SaveToFile(Rom::SaveSettings{.filename = v2_test_path_}));
|
||||
|
||||
|
||||
// Reload and verify
|
||||
std::unique_ptr<Rom> reloaded_rom = std::make_unique<Rom>();
|
||||
ASSERT_OK(reloaded_rom->LoadFromFile(v2_test_path_));
|
||||
|
||||
|
||||
EXPECT_TRUE(ValidateVersionAddresses(*reloaded_rom, "v2"));
|
||||
auto version_byte = reloaded_rom->ReadByte(0x140145);
|
||||
ASSERT_TRUE(version_byte.ok());
|
||||
@@ -207,23 +209,23 @@ TEST_F(ZSCustomOverworldUpgradeTest, V2ToV3Upgrade) {
|
||||
// Load vanilla ROM
|
||||
std::unique_ptr<Rom> rom = std::make_unique<Rom>();
|
||||
ASSERT_OK(rom->LoadFromFile(vanilla_test_path_));
|
||||
|
||||
|
||||
// Apply v2 patch first
|
||||
ASSERT_OK(ApplyVersionPatch(*rom, "v2"));
|
||||
|
||||
|
||||
// Apply v3 patch
|
||||
ASSERT_OK(ApplyVersionPatch(*rom, "v3"));
|
||||
|
||||
|
||||
// Validate v3 addresses
|
||||
EXPECT_TRUE(ValidateVersionAddresses(*rom, "v3"));
|
||||
|
||||
|
||||
// Save v3 ROM
|
||||
ASSERT_OK(rom->SaveToFile(Rom::SaveSettings{.filename = v3_test_path_}));
|
||||
|
||||
|
||||
// Reload and verify
|
||||
std::unique_ptr<Rom> reloaded_rom = std::make_unique<Rom>();
|
||||
ASSERT_OK(reloaded_rom->LoadFromFile(v3_test_path_));
|
||||
|
||||
|
||||
EXPECT_TRUE(ValidateVersionAddresses(*reloaded_rom, "v3"));
|
||||
auto version_byte = reloaded_rom->ReadByte(0x140145);
|
||||
ASSERT_TRUE(version_byte.ok());
|
||||
@@ -235,20 +237,20 @@ TEST_F(ZSCustomOverworldUpgradeTest, VanillaToV3Upgrade) {
|
||||
// Load vanilla ROM
|
||||
std::unique_ptr<Rom> rom = std::make_unique<Rom>();
|
||||
ASSERT_OK(rom->LoadFromFile(vanilla_test_path_));
|
||||
|
||||
|
||||
// Apply v3 patch directly
|
||||
ASSERT_OK(ApplyVersionPatch(*rom, "v3"));
|
||||
|
||||
|
||||
// Validate v3 addresses
|
||||
EXPECT_TRUE(ValidateVersionAddresses(*rom, "v3"));
|
||||
|
||||
|
||||
// Save v3 ROM
|
||||
ASSERT_OK(rom->SaveToFile(Rom::SaveSettings{.filename = v3_test_path_}));
|
||||
|
||||
|
||||
// Reload and verify
|
||||
std::unique_ptr<Rom> reloaded_rom = std::make_unique<Rom>();
|
||||
ASSERT_OK(reloaded_rom->LoadFromFile(v3_test_path_));
|
||||
|
||||
|
||||
EXPECT_TRUE(ValidateVersionAddresses(*reloaded_rom, "v3"));
|
||||
auto version_byte = reloaded_rom->ReadByte(0x140145);
|
||||
ASSERT_TRUE(version_byte.ok());
|
||||
@@ -261,11 +263,11 @@ TEST_F(ZSCustomOverworldUpgradeTest, AddressValidation) {
|
||||
std::unique_ptr<Rom> vanilla_rom = std::make_unique<Rom>();
|
||||
ASSERT_OK(vanilla_rom->LoadFromFile(vanilla_test_path_));
|
||||
EXPECT_TRUE(ValidateVersionAddresses(*vanilla_rom, "vanilla"));
|
||||
|
||||
|
||||
// Test v2 addresses
|
||||
ASSERT_OK(ApplyVersionPatch(*vanilla_rom, "v2"));
|
||||
EXPECT_TRUE(ValidateVersionAddresses(*vanilla_rom, "v2"));
|
||||
|
||||
|
||||
// Test v3 addresses
|
||||
ASSERT_OK(ApplyVersionPatch(*vanilla_rom, "v3"));
|
||||
EXPECT_TRUE(ValidateVersionAddresses(*vanilla_rom, "v3"));
|
||||
@@ -276,7 +278,7 @@ TEST_F(ZSCustomOverworldUpgradeTest, FeatureToggle) {
|
||||
std::unique_ptr<Rom> rom = std::make_unique<Rom>();
|
||||
ASSERT_OK(rom->LoadFromFile(vanilla_test_path_));
|
||||
ASSERT_OK(ApplyVersionPatch(*rom, "v3"));
|
||||
|
||||
|
||||
// Test feature flags
|
||||
auto main_palettes = rom->ReadByte(0x140146);
|
||||
auto area_bg = rom->ReadByte(0x140147);
|
||||
@@ -284,44 +286,44 @@ TEST_F(ZSCustomOverworldUpgradeTest, FeatureToggle) {
|
||||
auto animated_gfx = rom->ReadByte(0x140149);
|
||||
auto custom_tiles = rom->ReadByte(0x14014A);
|
||||
auto mosaic = rom->ReadByte(0x14014B);
|
||||
|
||||
|
||||
ASSERT_TRUE(main_palettes.ok());
|
||||
ASSERT_TRUE(area_bg.ok());
|
||||
ASSERT_TRUE(subscreen_overlay.ok());
|
||||
ASSERT_TRUE(animated_gfx.ok());
|
||||
ASSERT_TRUE(custom_tiles.ok());
|
||||
ASSERT_TRUE(mosaic.ok());
|
||||
|
||||
EXPECT_EQ(*main_palettes, 0x01); // Main palettes enabled
|
||||
EXPECT_EQ(*area_bg, 0x01); // Area-specific BG enabled
|
||||
EXPECT_EQ(*subscreen_overlay, 0x01); // Subscreen overlay enabled
|
||||
EXPECT_EQ(*animated_gfx, 0x01); // Animated GFX enabled
|
||||
EXPECT_EQ(*custom_tiles, 0x01); // Custom tile GFX groups enabled
|
||||
EXPECT_EQ(*mosaic, 0x01); // Mosaic enabled
|
||||
|
||||
|
||||
EXPECT_EQ(*main_palettes, 0x01); // Main palettes enabled
|
||||
EXPECT_EQ(*area_bg, 0x01); // Area-specific BG enabled
|
||||
EXPECT_EQ(*subscreen_overlay, 0x01); // Subscreen overlay enabled
|
||||
EXPECT_EQ(*animated_gfx, 0x01); // Animated GFX enabled
|
||||
EXPECT_EQ(*custom_tiles, 0x01); // Custom tile GFX groups enabled
|
||||
EXPECT_EQ(*mosaic, 0x01); // Mosaic enabled
|
||||
|
||||
// Disable some features
|
||||
ASSERT_OK(rom->WriteByte(0x140147, 0x00)); // Disable area-specific BG
|
||||
ASSERT_OK(rom->WriteByte(0x140149, 0x00)); // Disable animated GFX
|
||||
|
||||
ASSERT_OK(rom->WriteByte(0x140147, 0x00)); // Disable area-specific BG
|
||||
ASSERT_OK(rom->WriteByte(0x140149, 0x00)); // Disable animated GFX
|
||||
|
||||
// Verify features are disabled
|
||||
auto disabled_area_bg = rom->ReadByte(0x140147);
|
||||
auto disabled_animated_gfx = rom->ReadByte(0x140149);
|
||||
ASSERT_TRUE(disabled_area_bg.ok());
|
||||
ASSERT_TRUE(disabled_animated_gfx.ok());
|
||||
|
||||
|
||||
EXPECT_EQ(*disabled_area_bg, 0x00);
|
||||
EXPECT_EQ(*disabled_animated_gfx, 0x00);
|
||||
|
||||
|
||||
// Re-enable features
|
||||
ASSERT_OK(rom->WriteByte(0x140147, 0x01));
|
||||
ASSERT_OK(rom->WriteByte(0x140149, 0x01));
|
||||
|
||||
|
||||
// Verify features are re-enabled
|
||||
auto reenabled_area_bg = rom->ReadByte(0x140147);
|
||||
auto reenabled_animated_gfx = rom->ReadByte(0x140149);
|
||||
ASSERT_TRUE(reenabled_area_bg.ok());
|
||||
ASSERT_TRUE(reenabled_animated_gfx.ok());
|
||||
|
||||
|
||||
EXPECT_EQ(*reenabled_area_bg, 0x01);
|
||||
EXPECT_EQ(*reenabled_animated_gfx, 0x01);
|
||||
}
|
||||
@@ -330,47 +332,47 @@ TEST_F(ZSCustomOverworldUpgradeTest, FeatureToggle) {
|
||||
TEST_F(ZSCustomOverworldUpgradeTest, DataIntegrity) {
|
||||
std::unique_ptr<Rom> rom = std::make_unique<Rom>();
|
||||
ASSERT_OK(rom->LoadFromFile(vanilla_test_path_));
|
||||
|
||||
|
||||
// Store some original data
|
||||
auto original_graphics = rom->ReadByte(0x7C9C);
|
||||
auto original_palette = rom->ReadByte(0x7D1C);
|
||||
auto original_sprite_set = rom->ReadByte(0x7A41);
|
||||
|
||||
|
||||
ASSERT_TRUE(original_graphics.ok());
|
||||
ASSERT_TRUE(original_palette.ok());
|
||||
ASSERT_TRUE(original_sprite_set.ok());
|
||||
|
||||
|
||||
// Upgrade to v3
|
||||
ASSERT_OK(ApplyVersionPatch(*rom, "v3"));
|
||||
|
||||
|
||||
// Verify original data is preserved
|
||||
auto preserved_graphics = rom->ReadByte(0x7C9C);
|
||||
auto preserved_palette = rom->ReadByte(0x7D1C);
|
||||
auto preserved_sprite_set = rom->ReadByte(0x7A41);
|
||||
|
||||
|
||||
ASSERT_TRUE(preserved_graphics.ok());
|
||||
ASSERT_TRUE(preserved_palette.ok());
|
||||
ASSERT_TRUE(preserved_sprite_set.ok());
|
||||
|
||||
|
||||
EXPECT_EQ(*preserved_graphics, *original_graphics);
|
||||
EXPECT_EQ(*preserved_palette, *original_palette);
|
||||
EXPECT_EQ(*preserved_sprite_set, *original_sprite_set);
|
||||
|
||||
|
||||
// Verify new v3 data is initialized
|
||||
auto bg_colors = rom->ReadByte(0x140000);
|
||||
auto subscreen_overlays = rom->ReadByte(0x140340);
|
||||
auto animated_gfx = rom->ReadByte(0x1402A0);
|
||||
auto custom_tiles = rom->ReadByte(0x140480);
|
||||
|
||||
|
||||
ASSERT_TRUE(bg_colors.ok());
|
||||
ASSERT_TRUE(subscreen_overlays.ok());
|
||||
ASSERT_TRUE(animated_gfx.ok());
|
||||
ASSERT_TRUE(custom_tiles.ok());
|
||||
|
||||
EXPECT_EQ(*bg_colors, 0x00); // BG colors
|
||||
EXPECT_EQ(*subscreen_overlays, 0x00); // Subscreen overlays
|
||||
EXPECT_EQ(*animated_gfx, 0x00); // Animated GFX
|
||||
EXPECT_EQ(*custom_tiles, 0x00); // Custom tiles
|
||||
|
||||
EXPECT_EQ(*bg_colors, 0x00); // BG colors
|
||||
EXPECT_EQ(*subscreen_overlays, 0x00); // Subscreen overlays
|
||||
EXPECT_EQ(*animated_gfx, 0x00); // Animated GFX
|
||||
EXPECT_EQ(*custom_tiles, 0x00); // Custom tiles
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
|
||||
Reference in New Issue
Block a user