Add Overworld accessors and enhance testing framework
- Introduced new methods in `Controller`, `EditorManager`, and `OverworldEditor` to access the `Overworld` instance, improving modularity and interaction with the overworld data. - Added `GetTile` method in `Overworld` to retrieve tile data based on coordinates, enhancing functionality for tile manipulation. - Implemented a new testing framework with automated GUI tests, including `CanvasSelectionTest` and `FrameworkSmokeTest`, to validate user interactions and ensure robustness. - Updated `CMakeLists.txt` to include new test files and dependencies, streamlining the build process for testing. - Refactored logging behavior to ensure proper file handling during logging operations, improving reliability in logging outputs.
This commit is contained in:
@@ -32,6 +32,7 @@ class Controller {
|
|||||||
auto window() -> SDL_Window * { return window_.window_.get(); }
|
auto window() -> SDL_Window * { return window_.window_.get(); }
|
||||||
void set_active(bool active) { active_ = active; }
|
void set_active(bool active) { active_ = active; }
|
||||||
auto active() const { return active_; }
|
auto active() const { return active_; }
|
||||||
|
auto overworld() -> yaze::zelda3::Overworld* { return editor_manager_.overworld(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend int ::main(int argc, char **argv);
|
friend int ::main(int argc, char **argv);
|
||||||
|
|||||||
@@ -101,6 +101,7 @@ class EditorManager {
|
|||||||
absl::Status SetCurrentRom(Rom* rom);
|
absl::Status SetCurrentRom(Rom* rom);
|
||||||
auto GetCurrentRom() -> Rom* { return current_rom_; }
|
auto GetCurrentRom() -> Rom* { return current_rom_; }
|
||||||
auto GetCurrentEditorSet() -> EditorSet* { return current_editor_set_; }
|
auto GetCurrentEditorSet() -> EditorSet* { return current_editor_set_; }
|
||||||
|
auto overworld() -> yaze::zelda3::Overworld* { return ¤t_editor_set_->overworld_editor_.overworld(); }
|
||||||
|
|
||||||
// Get current session's feature flags (falls back to global if no session)
|
// Get current session's feature flags (falls back to global if no session)
|
||||||
core::FeatureFlags::Flags* GetCurrentFeatureFlags() {
|
core::FeatureFlags::Flags* GetCurrentFeatureFlags() {
|
||||||
|
|||||||
@@ -94,6 +94,7 @@ class OverworldEditor : public Editor, public gfx::GfxContext {
|
|||||||
absl::Status Find() override { return absl::UnimplementedError("Find"); }
|
absl::Status Find() override { return absl::UnimplementedError("Find"); }
|
||||||
absl::Status Save() override;
|
absl::Status Save() override;
|
||||||
absl::Status Clear() override;
|
absl::Status Clear() override;
|
||||||
|
zelda3::Overworld& overworld() { return overworld_; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Apply ZSCustomOverworld ASM patch to upgrade ROM version
|
* @brief Apply ZSCustomOverworld ASM patch to upgrade ROM version
|
||||||
|
|||||||
@@ -278,6 +278,15 @@ class Overworld {
|
|||||||
auto expanded_entrances() const { return expanded_entrances_; }
|
auto expanded_entrances() const { return expanded_entrances_; }
|
||||||
void set_current_map(int i) { current_map_ = i; }
|
void set_current_map(int i) { current_map_ = i; }
|
||||||
void set_current_world(int world) { current_world_ = world; }
|
void set_current_world(int world) { current_world_ = world; }
|
||||||
|
uint16_t GetTile(int x, int y) const {
|
||||||
|
if (current_world_ == 0) {
|
||||||
|
return map_tiles_.light_world[y][x];
|
||||||
|
} else if (current_world_ == 1) {
|
||||||
|
return map_tiles_.dark_world[y][x];
|
||||||
|
} else {
|
||||||
|
return map_tiles_.special_world[y][x];
|
||||||
|
}
|
||||||
|
}
|
||||||
auto map_tiles() const { return map_tiles_; }
|
auto map_tiles() const { return map_tiles_; }
|
||||||
auto mutable_map_tiles() { return &map_tiles_; }
|
auto mutable_map_tiles() { return &map_tiles_; }
|
||||||
auto all_items() const { return all_items_; }
|
auto all_items() const { return all_items_; }
|
||||||
|
|||||||
@@ -9,6 +9,12 @@
|
|||||||
#include "absl/flags/flag.h"
|
#include "absl/flags/flag.h"
|
||||||
#include "absl/flags/parse.h"
|
#include "absl/flags/parse.h"
|
||||||
#include "absl/flags/usage.h"
|
#include "absl/flags/usage.h"
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#ifdef __APPLE__
|
||||||
|
#include <mach-o/dyld.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "absl/strings/str_format.h"
|
#include "absl/strings/str_format.h"
|
||||||
#include "absl/strings/str_join.h"
|
#include "absl/strings/str_join.h"
|
||||||
#include "absl/strings/str_cat.h"
|
#include "absl/strings/str_cat.h"
|
||||||
@@ -29,6 +35,9 @@ ABSL_FLAG(std::string, rom, "", "Path to the ROM file");
|
|||||||
ABSL_FLAG(std::string, output, "", "Output file path");
|
ABSL_FLAG(std::string, output, "", "Output file path");
|
||||||
ABSL_FLAG(bool, dry_run, false, "Perform a dry run without making changes");
|
ABSL_FLAG(bool, dry_run, false, "Perform a dry run without making changes");
|
||||||
ABSL_FLAG(bool, backup, true, "Create a backup before modifying files");
|
ABSL_FLAG(bool, backup, true, "Create a backup before modifying files");
|
||||||
|
ABSL_FLAG(std::string, test, "", "Name of the test to run");
|
||||||
|
ABSL_FLAG(bool, show_gui, false, "Show the test engine GUI");
|
||||||
|
|
||||||
|
|
||||||
namespace yaze {
|
namespace yaze {
|
||||||
namespace cli {
|
namespace cli {
|
||||||
@@ -118,6 +127,15 @@ class ModernCLI {
|
|||||||
return HandleHelpCommand(args);
|
return HandleHelpCommand(args);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
commands_["test-gui"] = {
|
||||||
|
.name = "test-gui",
|
||||||
|
.description = "Run automated GUI tests",
|
||||||
|
.usage = "z3ed test-gui --rom=<rom_file> --test=<test_name>",
|
||||||
|
.handler = [this](const std::vector<std::string>& args) -> absl::Status {
|
||||||
|
return HandleTestGuiCommand(args);
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShowHelp(const std::string& command = "") {
|
void ShowHelp(const std::string& command = "") {
|
||||||
@@ -417,6 +435,78 @@ class ModernCLI {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
absl::Status HandleTestGuiCommand(const std::vector<std::string>& args) {
|
||||||
|
std::string rom_file = absl::GetFlag(FLAGS_rom);
|
||||||
|
std::string test_name = absl::GetFlag(FLAGS_test);
|
||||||
|
|
||||||
|
if (rom_file.empty()) {
|
||||||
|
return absl::InvalidArgumentError("ROM file required (use --rom=<file>)");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the path to the current executable
|
||||||
|
char exe_path[1024];
|
||||||
|
#ifdef __APPLE__
|
||||||
|
uint32_t size = sizeof(exe_path);
|
||||||
|
if (_NSGetExecutablePath(exe_path, &size) != 0) {
|
||||||
|
return absl::InternalError("Could not get executable path");
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
ssize_t len = readlink("/proc/self/exe", exe_path, sizeof(exe_path) - 1);
|
||||||
|
if (len == -1) {
|
||||||
|
return absl::InternalError("Could not get executable path");
|
||||||
|
}
|
||||||
|
exe_path[len] = '\0';
|
||||||
|
#endif
|
||||||
|
|
||||||
|
std::string exe_dir = std::string(exe_path);
|
||||||
|
exe_dir = exe_dir.substr(0, exe_dir.find_last_of("/"));
|
||||||
|
|
||||||
|
std::string yaze_test_path = exe_dir + "/yaze_test";
|
||||||
|
|
||||||
|
std::vector<std::string> command_args;
|
||||||
|
command_args.push_back(yaze_test_path);
|
||||||
|
command_args.push_back("--enable-ui-tests");
|
||||||
|
command_args.push_back("--rom-path=" + rom_file);
|
||||||
|
if (!test_name.empty()) {
|
||||||
|
command_args.push_back(test_name);
|
||||||
|
}
|
||||||
|
if (absl::GetFlag(FLAGS_show_gui)) {
|
||||||
|
command_args.push_back("--show-gui");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<char*> argv;
|
||||||
|
for (const auto& arg : command_args) {
|
||||||
|
argv.push_back((char*)arg.c_str());
|
||||||
|
}
|
||||||
|
argv.push_back(nullptr);
|
||||||
|
|
||||||
|
pid_t pid = fork();
|
||||||
|
if (pid == -1) {
|
||||||
|
return absl::InternalError("Failed to fork process");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pid == 0) {
|
||||||
|
// Child process
|
||||||
|
execv(yaze_test_path.c_str(), argv.data());
|
||||||
|
// If execv returns, it must have failed
|
||||||
|
return absl::InternalError("Failed to execute yaze_test");
|
||||||
|
} else {
|
||||||
|
// Parent process
|
||||||
|
int status;
|
||||||
|
waitpid(pid, &status, 0);
|
||||||
|
if (WIFEXITED(status)) {
|
||||||
|
int exit_code = WEXITSTATUS(status);
|
||||||
|
if (exit_code == 0) {
|
||||||
|
return absl::OkStatus();
|
||||||
|
} else {
|
||||||
|
return absl::InternalError(absl::StrFormat("yaze_test exited with code %d", exit_code));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return absl::OkStatus();
|
||||||
|
}
|
||||||
|
|
||||||
absl::Status HandleHelpCommand(const std::vector<std::string>& args) {
|
absl::Status HandleHelpCommand(const std::vector<std::string>& args) {
|
||||||
std::string command = args.empty() ? "" : args[0];
|
std::string command = args.empty() ? "" : args[0];
|
||||||
ShowHelp(command);
|
ShowHelp(command);
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ static void logf(const absl::FormatSpec<Args...> &format, const Args &...args) {
|
|||||||
// Reopen file if path changed
|
// Reopen file if path changed
|
||||||
if (g_log_file_path != last_log_path) {
|
if (g_log_file_path != last_log_path) {
|
||||||
fout.close();
|
fout.close();
|
||||||
fout.open(g_log_file_path, std::ios::out | std::ios::app);
|
fout.open(g_log_file_path, std::ios::out | std::ios::trunc);
|
||||||
last_log_path = g_log_file_path;
|
last_log_path = g_log_file_path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ if(YAZE_BUILD_TESTS AND NOT YAZE_BUILD_TESTS STREQUAL "OFF")
|
|||||||
test_editor.h
|
test_editor.h
|
||||||
testing.h
|
testing.h
|
||||||
test_utils.h
|
test_utils.h
|
||||||
|
test_utils.cc
|
||||||
|
|
||||||
# Unit Tests
|
# Unit Tests
|
||||||
unit/core/asar_wrapper_test.cc
|
unit/core/asar_wrapper_test.cc
|
||||||
@@ -101,6 +102,8 @@ if(YAZE_BUILD_TESTS AND NOT YAZE_BUILD_TESTS STREQUAL "OFF")
|
|||||||
integration/editor/editor_integration_test.h
|
integration/editor/editor_integration_test.h
|
||||||
|
|
||||||
# E2E Tests (included in development builds)
|
# E2E Tests (included in development builds)
|
||||||
|
e2e/canvas_selection_test.cc
|
||||||
|
e2e/framework_smoke_test.cc
|
||||||
e2e/rom_dependent/e2e_rom_test.cc
|
e2e/rom_dependent/e2e_rom_test.cc
|
||||||
e2e/zscustomoverworld/zscustomoverworld_upgrade_test.cc
|
e2e/zscustomoverworld/zscustomoverworld_upgrade_test.cc
|
||||||
|
|
||||||
@@ -212,7 +215,6 @@ endif()
|
|||||||
${PNG_LIBRARIES}
|
${PNG_LIBRARIES}
|
||||||
${OPENGL_LIBRARIES}
|
${OPENGL_LIBRARIES}
|
||||||
${CMAKE_DL_LIBS}
|
${CMAKE_DL_LIBS}
|
||||||
ImGui
|
|
||||||
gmock_main
|
gmock_main
|
||||||
gmock
|
gmock
|
||||||
gtest_main
|
gtest_main
|
||||||
|
|||||||
76
test/e2e/canvas_selection_test.cc
Normal file
76
test/e2e/canvas_selection_test.cc
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
#define IMGUI_DEFINE_MATH_OPERATORS
|
||||||
|
#include "e2e/canvas_selection_test.h"
|
||||||
|
#include "app/core/controller.h"
|
||||||
|
#include "test_utils.h"
|
||||||
|
|
||||||
|
void E2ETest_CanvasSelectionTest(ImGuiTestContext* ctx)
|
||||||
|
{
|
||||||
|
yaze::test::gui::LoadRomInTest(ctx, "zelda3.sfc");
|
||||||
|
yaze::core::Controller* controller = (yaze::core::Controller*)ctx->Test->UserData;
|
||||||
|
yaze::zelda3::Overworld* overworld = controller->overworld();
|
||||||
|
|
||||||
|
// 1. Open the Overworld Editor
|
||||||
|
yaze::test::gui::OpenEditorInTest(ctx, "Overworld Editor");
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
8
test/e2e/canvas_selection_test.h
Normal file
8
test/e2e/canvas_selection_test.h
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#ifndef YAZE_TEST_E2E_CANVAS_SELECTION_TEST_H
|
||||||
|
#define YAZE_TEST_E2E_CANVAS_SELECTION_TEST_H
|
||||||
|
|
||||||
|
#include "imgui_test_engine/imgui_te_context.h"
|
||||||
|
|
||||||
|
void E2ETest_CanvasSelectionTest(ImGuiTestContext* ctx);
|
||||||
|
|
||||||
|
#endif // YAZE_TEST_E2E_CANVAS_SELECTION_TEST_H
|
||||||
16
test/e2e/framework_smoke_test.cc
Normal file
16
test/e2e/framework_smoke_test.cc
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#include "e2e/framework_smoke_test.h"
|
||||||
|
#include "test_utils.h"
|
||||||
|
#include "imgui.h"
|
||||||
|
#include "imgui_test_engine/imgui_te_context.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");
|
||||||
|
}
|
||||||
8
test/e2e/framework_smoke_test.h
Normal file
8
test/e2e/framework_smoke_test.h
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#ifndef YAZE_TEST_E2E_FRAMEWORK_SMOKE_TEST_H
|
||||||
|
#define YAZE_TEST_E2E_FRAMEWORK_SMOKE_TEST_H
|
||||||
|
|
||||||
|
#include "imgui_test_engine/imgui_te_context.h"
|
||||||
|
|
||||||
|
void E2ETest_FrameworkSmokeTest(ImGuiTestContext* ctx);
|
||||||
|
|
||||||
|
#endif // YAZE_TEST_E2E_FRAMEWORK_SMOKE_TEST_H
|
||||||
19
test/test_utils.cc
Normal file
19
test/test_utils.cc
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
#include "test_utils.h"
|
||||||
|
#include "app/core/controller.h"
|
||||||
|
|
||||||
|
namespace yaze {
|
||||||
|
namespace test {
|
||||||
|
namespace gui {
|
||||||
|
|
||||||
|
void LoadRomInTest(ImGuiTestContext* ctx, const std::string& rom_path) {
|
||||||
|
yaze::core::Controller* controller = (yaze::core::Controller*)ctx->Test->UserData;
|
||||||
|
controller->OnEntry(rom_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenEditorInTest(ImGuiTestContext* ctx, const std::string& editor_name) {
|
||||||
|
ctx->MenuClick(absl::StrFormat("Editors/%s", editor_name).c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace gui
|
||||||
|
} // namespace test
|
||||||
|
} // namespace yaze
|
||||||
@@ -10,6 +10,9 @@
|
|||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
#include <gmock/gmock.h>
|
#include <gmock/gmock.h>
|
||||||
|
|
||||||
|
#include "absl/strings/str_format.h"
|
||||||
|
#include "imgui_test_engine/imgui_te_context.h"
|
||||||
|
|
||||||
namespace yaze {
|
namespace yaze {
|
||||||
namespace test {
|
namespace test {
|
||||||
|
|
||||||
@@ -150,6 +153,13 @@ class RomDependentTest : public ::testing::Test {
|
|||||||
std::vector<uint8_t> test_rom_;
|
std::vector<uint8_t> test_rom_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace gui {
|
||||||
|
|
||||||
|
void LoadRomInTest(ImGuiTestContext* ctx, const std::string& rom_path);
|
||||||
|
void OpenEditorInTest(ImGuiTestContext* ctx, const std::string& editor_name);
|
||||||
|
|
||||||
|
} // namespace gui
|
||||||
|
|
||||||
} // namespace test
|
} // namespace test
|
||||||
} // namespace yaze
|
} // namespace yaze
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,17 @@
|
|||||||
|
|
||||||
#include "absl/debugging/failure_signal_handler.h"
|
#include "absl/debugging/failure_signal_handler.h"
|
||||||
#include "absl/debugging/symbolize.h"
|
#include "absl/debugging/symbolize.h"
|
||||||
|
#include "imgui/imgui.h"
|
||||||
|
#include "imgui/backends/imgui_impl_sdl2.h"
|
||||||
|
#include "imgui/backends/imgui_impl_sdlrenderer2.h"
|
||||||
|
#include "imgui_test_engine/imgui_te_context.h"
|
||||||
|
#include "imgui_test_engine/imgui_te_engine.h"
|
||||||
|
#include "imgui_test_engine/imgui_te_ui.h"
|
||||||
|
#include "app/core/window.h"
|
||||||
|
#include "app/core/controller.h"
|
||||||
|
#include "e2e/canvas_selection_test.h"
|
||||||
|
#include "e2e/framework_smoke_test.h"
|
||||||
|
|
||||||
// #include "test_editor.h" // Not used in main
|
// #include "test_editor.h" // Not used in main
|
||||||
|
|
||||||
namespace yaze {
|
namespace yaze {
|
||||||
@@ -36,6 +47,7 @@ struct TestConfig {
|
|||||||
bool verbose = false;
|
bool verbose = false;
|
||||||
bool skip_rom_tests = false;
|
bool skip_rom_tests = false;
|
||||||
bool enable_ui_tests = false;
|
bool enable_ui_tests = false;
|
||||||
|
bool show_gui = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Parse command line arguments for better AI agent testing support
|
// Parse command line arguments for better AI agent testing support
|
||||||
@@ -98,6 +110,8 @@ TestConfig ParseArguments(int argc, char* argv[]) {
|
|||||||
config.enable_ui_tests = true;
|
config.enable_ui_tests = true;
|
||||||
} else if (arg == "--verbose") {
|
} else if (arg == "--verbose") {
|
||||||
config.verbose = true;
|
config.verbose = true;
|
||||||
|
} else if (arg == "--show-gui") {
|
||||||
|
config.show_gui = true;
|
||||||
} else if (arg.find("--") != 0) {
|
} else if (arg.find("--") != 0) {
|
||||||
// Test pattern (not a flag)
|
// Test pattern (not a flag)
|
||||||
config.mode = TestMode::kSpecific;
|
config.mode = TestMode::kSpecific;
|
||||||
@@ -224,11 +238,121 @@ int main(int argc, char* argv[]) {
|
|||||||
// Initialize Google Test
|
// Initialize Google Test
|
||||||
::testing::InitGoogleTest(&argc, argv);
|
::testing::InitGoogleTest(&argc, argv);
|
||||||
|
|
||||||
// Run tests
|
if (config.enable_ui_tests) {
|
||||||
int result = RUN_ALL_TESTS();
|
// Create a window
|
||||||
|
yaze::core::Window window;
|
||||||
// Cleanup SDL
|
yaze::core::CreateWindow(window, SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
|
||||||
SDL_Quit();
|
|
||||||
|
// Create a renderer
|
||||||
return result;
|
yaze::core::Renderer::Get().CreateRenderer(window.window_.get());
|
||||||
|
|
||||||
|
// Setup Dear ImGui context
|
||||||
|
IMGUI_CHECKVERSION();
|
||||||
|
ImGui::CreateContext();
|
||||||
|
ImGuiIO& io = ImGui::GetIO(); (void)io;
|
||||||
|
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
|
||||||
|
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking
|
||||||
|
io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; // Enable Multi-Viewport / Platform Windows
|
||||||
|
|
||||||
|
// Setup Dear ImGui style
|
||||||
|
ImGui::StyleColorsDark();
|
||||||
|
|
||||||
|
// When viewports are enabled we tweak WindowRounding/WindowBg so platform windows can look identical to regular ones.
|
||||||
|
ImGuiStyle& style = ImGui::GetStyle();
|
||||||
|
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) {
|
||||||
|
style.WindowRounding = 0.0f;
|
||||||
|
style.Colors[ImGuiCol_WindowBg].w = 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup Platform/Renderer backends
|
||||||
|
ImGui_ImplSDL2_InitForSDLRenderer(window.window_.get(), yaze::core::Renderer::Get().renderer());
|
||||||
|
ImGui_ImplSDLRenderer2_Init(yaze::core::Renderer::Get().renderer());
|
||||||
|
|
||||||
|
// Setup test engine
|
||||||
|
ImGuiTestEngine* engine = ImGuiTestEngine_CreateContext();
|
||||||
|
ImGuiTestEngineIO& test_io = ImGuiTestEngine_GetIO(engine);
|
||||||
|
test_io.ConfigRunSpeed = ImGuiTestRunSpeed_Fast;
|
||||||
|
test_io.ConfigVerboseLevel = ImGuiTestVerboseLevel_Info;
|
||||||
|
test_io.ConfigVerboseLevelOnError = ImGuiTestVerboseLevel_Debug;
|
||||||
|
|
||||||
|
yaze::core::Controller controller;
|
||||||
|
|
||||||
|
// Register smoke test
|
||||||
|
ImGuiTest* smoke_test = IM_REGISTER_TEST(engine, "E2ETest", "FrameworkSmokeTest");
|
||||||
|
smoke_test->TestFunc = E2ETest_FrameworkSmokeTest;
|
||||||
|
|
||||||
|
// Register canvas selection test
|
||||||
|
ImGuiTest* canvas_test = IM_REGISTER_TEST(engine, "E2ETest", "CanvasSelectionTest");
|
||||||
|
canvas_test->TestFunc = E2ETest_CanvasSelectionTest;
|
||||||
|
canvas_test->UserData = &controller;
|
||||||
|
|
||||||
|
// Main loop
|
||||||
|
bool done = false;
|
||||||
|
while (!done) {
|
||||||
|
SDL_Event event;
|
||||||
|
while (SDL_PollEvent(&event)) {
|
||||||
|
ImGui_ImplSDL2_ProcessEvent(&event);
|
||||||
|
if (event.type == SDL_QUIT) {
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
|
if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_CLOSE && event.window.windowID == SDL_GetWindowID(window.window_.get())) {
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start the Dear ImGui frame
|
||||||
|
ImGui_ImplSDLRenderer2_NewFrame();
|
||||||
|
ImGui_ImplSDL2_NewFrame();
|
||||||
|
ImGui::NewFrame();
|
||||||
|
|
||||||
|
// Render the UI
|
||||||
|
if (config.show_gui) {
|
||||||
|
ImGuiTestEngine_ShowTestEngineWindows(engine, &config.show_gui);
|
||||||
|
}
|
||||||
|
controller.DoRender();
|
||||||
|
|
||||||
|
// End the Dear ImGui frame
|
||||||
|
ImGui::Render();
|
||||||
|
yaze::core::Renderer::Get().Clear();
|
||||||
|
ImGui_ImplSDLRenderer2_RenderDrawData(ImGui::GetDrawData(), yaze::core::Renderer::Get().renderer());
|
||||||
|
yaze::core::Renderer::Get().Present();
|
||||||
|
|
||||||
|
// Update and Render additional Platform Windows
|
||||||
|
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) {
|
||||||
|
SDL_Window* backup_current_window = SDL_GL_GetCurrentWindow();
|
||||||
|
SDL_GLContext backup_current_context = SDL_GL_GetCurrentContext();
|
||||||
|
ImGui::UpdatePlatformWindows();
|
||||||
|
ImGui::RenderPlatformWindowsDefault();
|
||||||
|
SDL_GL_MakeCurrent(backup_current_window, backup_current_context);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run test engine
|
||||||
|
ImGuiTestEngine_PostSwap(engine);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get test result
|
||||||
|
ImGuiTestEngineResultSummary summary;
|
||||||
|
ImGuiTestEngine_GetResultSummary(engine, &summary);
|
||||||
|
int result = (summary.CountSuccess == summary.CountTested) ? 0 : 1;
|
||||||
|
|
||||||
|
// Cleanup
|
||||||
|
controller.OnExit();
|
||||||
|
ImGuiTestEngine_DestroyContext(engine);
|
||||||
|
ImGui_ImplSDLRenderer2_Shutdown();
|
||||||
|
ImGui_ImplSDL2_Shutdown();
|
||||||
|
ImGui::DestroyContext();
|
||||||
|
|
||||||
|
yaze::core::ShutdownWindow(window);
|
||||||
|
SDL_Quit();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
// Run tests
|
||||||
|
int result = RUN_ALL_TESTS();
|
||||||
|
|
||||||
|
// Cleanup SDL
|
||||||
|
SDL_Quit();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user