yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
yaze_test.cc
Go to the documentation of this file.
1#define SDL_MAIN_HANDLED
2
3// Must define before any ImGui includes
4#ifndef IMGUI_DEFINE_MATH_OPERATORS
5#define IMGUI_DEFINE_MATH_OPERATORS
6#endif
7
8#include <gtest/gtest.h>
9#include <SDL.h>
10#include <iostream>
11#include <string>
12#include <vector>
13#include <cstdlib>
14
15#include "absl/debugging/failure_signal_handler.h"
16#include "absl/debugging/symbolize.h"
17#include "imgui/imgui.h"
18#include "imgui/backends/imgui_impl_sdl2.h"
19#include "imgui/backends/imgui_impl_sdlrenderer2.h"
20#include "imgui_test_engine/imgui_te_context.h"
21#include "imgui_test_engine/imgui_te_engine.h"
22#include "imgui_test_engine/imgui_te_ui.h"
23#include "app/core/window.h"
24#include "app/core/controller.h"
29
30// #include "test_editor.h" // Not used in main
31
32namespace yaze {
33namespace test {
34
35// Test execution modes for AI agents and developers
36enum class TestMode {
37 kAll, // Run all tests (default)
38 kUnit, // Run only unit tests
39 kIntegration, // Run only integration tests
40 kE2E, // Run only end-to-end tests
41 kRomDependent, // Run ROM-dependent tests only
42 kZSCustomOverworld, // Run ZSCustomOverworld specific tests
43 kCore, // Run core functionality tests
44 kGraphics, // Run graphics-related tests
45 kEditor, // Run editor tests
46 kDeprecated, // Run deprecated tests (for cleanup)
47 kSpecific // Run specific test pattern
48};
49
50struct TestConfig {
52 std::string test_pattern;
53 std::string rom_path = "zelda3.sfc";
54 bool verbose = false;
55 bool skip_rom_tests = false;
56 bool enable_ui_tests = false;
57 bool show_gui = false;
58 ImGuiTestRunSpeed test_speed = ImGuiTestRunSpeed_Fast;
59};
60
61// Parse command line arguments for better AI agent testing support
62TestConfig ParseArguments(int argc, char* argv[]) {
63 TestConfig config;
64
65 std::cout << "Available options:\n"
66 << " --ui : Enable UI tests\n"
67 << " --show-gui : Show GUI during tests\n"
68 << " --fast : Run tests at max speed (default)\n"
69 << " --normal : Run tests at watchable speed\n"
70 << " --cinematic : Run tests in slow-motion with pauses\n"
71 << " --rom=<path> : Specify ROM file path\n"
72 << " --pattern=<pat> : Run tests matching pattern\n"
73 << std::endl;
74
75 for (int i = 1; i < argc; i++) {
76 std::string arg = argv[i];
77
78 if (arg == "--help" || arg == "-h") {
79 std::cout << "YAZE Test Runner - Enhanced for AI Agent Testing\n\n";
80 std::cout << "Usage: yaze_test [options] [test_pattern]\n\n";
81 std::cout << "Test Modes:\n";
82 std::cout << " --unit Run unit tests only\n";
83 std::cout << " --integration Run integration tests only\n";
84 std::cout << " --e2e Run end-to-end tests only\n";
85 std::cout << " --rom-dependent Run ROM-dependent tests only\n";
86 std::cout << " --zscustomoverworld Run ZSCustomOverworld tests only\n";
87 std::cout << " --core Run core functionality tests\n";
88 std::cout << " --graphics Run graphics tests\n";
89 std::cout << " --editor Run editor tests\n";
90 std::cout << " --deprecated Run deprecated tests\n\n";
91 std::cout << "Options:\n";
92 std::cout << " --rom-path PATH Specify ROM path for testing\n";
93 std::cout << " --skip-rom-tests Skip tests requiring ROM files\n";
94 std::cout << " --enable-ui-tests Enable UI tests (requires display)\n";
95 std::cout << " --verbose Enable verbose output\n";
96 std::cout << " --help Show this help message\n\n";
97 std::cout << "Examples:\n";
98 std::cout << " yaze_test --unit --verbose\n";
99 std::cout << " yaze_test --e2e --rom-path my_rom.sfc\n";
100 std::cout << " yaze_test --zscustomoverworld --verbose\n";
101 std::cout << " yaze_test RomTest.*\n";
102 exit(0);
103 } else if (arg == "--unit") {
104 config.mode = TestMode::kUnit;
105 } else if (arg == "--integration") {
107 } else if (arg == "--e2e") {
108 config.mode = TestMode::kE2E;
109 } else if (arg == "--rom-dependent") {
111 } else if (arg == "--zscustomoverworld") {
113 } else if (arg == "--core") {
114 config.mode = TestMode::kCore;
115 } else if (arg == "--graphics") {
116 config.mode = TestMode::kGraphics;
117 } else if (arg == "--editor") {
118 config.mode = TestMode::kEditor;
119 } else if (arg == "--deprecated") {
121 } else if (arg == "--rom-path") {
122 if (i + 1 < argc) {
123 config.rom_path = argv[++i];
124 }
125 } else if (arg == "--skip-rom-tests") {
126 config.skip_rom_tests = true;
127 } else if (arg == "--enable-ui-tests") {
128 config.enable_ui_tests = true;
129 } else if (arg == "--verbose") {
130 config.verbose = true;
131 } else if (arg == "--show-gui") {
132 config.show_gui = true;
133 } else if (arg == "--fast") {
134 config.test_speed = ImGuiTestRunSpeed_Fast;
135 } else if (arg == "--normal") {
136 config.test_speed = ImGuiTestRunSpeed_Normal;
137 } else if (arg == "--cinematic") {
138 config.test_speed = ImGuiTestRunSpeed_Cinematic;
139 } else if (arg == "--ui") {
140 config.enable_ui_tests = true;
141 } else if (arg.find("--") != 0) {
142 // Test pattern (not a flag)
143 config.mode = TestMode::kSpecific;
144 config.test_pattern = arg;
145 }
146 }
147
148 return config;
149}
150
151// Set up test environment based on configuration
152void SetupTestEnvironment(const TestConfig& config) {
153 // Set environment variables for tests using SDL's cross-platform function
154 if (!config.rom_path.empty()) {
155 SDL_setenv("YAZE_TEST_ROM_PATH", config.rom_path.c_str(), 1);
156 }
157
158 if (config.skip_rom_tests) {
159 SDL_setenv("YAZE_SKIP_ROM_TESTS", "1", 1);
160 }
161
162 if (config.enable_ui_tests) {
163 SDL_setenv("YAZE_ENABLE_UI_TESTS", "1", 1);
164 }
165
166 if (config.verbose) {
167 SDL_setenv("YAZE_VERBOSE_TESTS", "1", 1);
168 }
169}
170
171// Configure Google Test filters based on test mode
172void ConfigureTestFilters(const TestConfig& config) {
173 std::vector<std::string> filters;
174
175 switch (config.mode) {
176 case TestMode::kUnit:
177 filters.push_back("UnitTest.*");
178 break;
180 filters.push_back("IntegrationTest.*");
181 break;
182 case TestMode::kE2E:
183 filters.push_back("E2ETest.*");
184 break;
186 filters.push_back("*RomDependent*");
187 break;
189 filters.push_back("*ZSCustomOverworld*");
190 break;
191 case TestMode::kCore:
192 filters.push_back("*Core*");
193 filters.push_back("*Asar*");
194 filters.push_back("*Rom*");
195 break;
197 filters.push_back("*Graphics*");
198 filters.push_back("*Gfx*");
199 filters.push_back("*Palette*");
200 filters.push_back("*Tile*");
201 break;
203 filters.push_back("*Editor*");
204 break;
206 filters.push_back("*Deprecated*");
207 break;
209 if (!config.test_pattern.empty()) {
210 filters.push_back(config.test_pattern);
211 }
212 break;
213 case TestMode::kAll:
214 default:
215 // No filters - run all tests
216 break;
217 }
218
219 if (!filters.empty()) {
220 std::string filter_string;
221 for (size_t i = 0; i < filters.size(); i++) {
222 if (i > 0) filter_string += ":";
223 filter_string += filters[i];
224 }
225
226 ::testing::GTEST_FLAG(filter) = filter_string;
227
228 if (config.verbose) {
229 std::cout << "Test filter: " << filter_string << std::endl;
230 }
231 }
232}
233
234} // namespace test
235} // namespace yaze
236
237int main(int argc, char* argv[]) {
238 absl::InitializeSymbolizer(argv[0]);
239
240 // Configure failure signal handler to be less aggressive for testing
241 absl::FailureSignalHandlerOptions options;
242 options.symbolize_stacktrace = true;
243 options.use_alternate_stack = false;
244 options.alarm_on_failure_secs = false;
245 options.call_previous_handler = true;
246 options.writerfn = nullptr;
247 absl::InstallFailureSignalHandler(options);
248
249 // Initialize SDL to prevent crashes in graphics components
250 if (SDL_Init(SDL_INIT_VIDEO) != 0) {
251 SDL_Log("Failed to initialize SDL: %s", SDL_GetError());
252 // Continue anyway for tests that don't need graphics
253 }
254
255 // Parse command line arguments
256 auto config = yaze::test::ParseArguments(argc, argv);
257
258 // Set up test environment
260
261 // Configure test filters
263
264 // Initialize Google Test
265 ::testing::InitGoogleTest(&argc, argv);
266
267 if (config.enable_ui_tests) {
268 // Create a window
269 yaze::core::Window window;
270 // Create renderer for test
271 auto test_renderer = std::make_unique<yaze::gfx::SDL2Renderer>();
272 yaze::core::CreateWindow(window, test_renderer.get(), SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
273
274 // Renderer is now owned by test
275
276 // Setup Dear ImGui context
277 IMGUI_CHECKVERSION();
278 ImGui::CreateContext();
279 ImGuiIO& io = ImGui::GetIO(); (void)io;
280 io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
281 io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking
282 io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; // Enable Multi-Viewport / Platform Windows
283
284 // Setup Dear ImGui style
285 ImGui::StyleColorsDark();
286
287 // When viewports are enabled we tweak WindowRounding/WindowBg so platform windows can look identical to regular ones.
288 ImGuiStyle& style = ImGui::GetStyle();
289 if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) {
290 style.WindowRounding = 0.0f;
291 style.Colors[ImGuiCol_WindowBg].w = 1.0f;
292 }
293
294 // Setup Platform/Renderer backends
295 SDL_Renderer* sdl_renderer = static_cast<SDL_Renderer*>(test_renderer->GetBackendRenderer());
296 ImGui_ImplSDL2_InitForSDLRenderer(window.window_.get(), sdl_renderer);
297 ImGui_ImplSDLRenderer2_Init(sdl_renderer);
298
299 yaze::core::Controller controller;
300
301 // Setup test engine
302 ImGuiTestEngine* engine = ImGuiTestEngine_CreateContext();
303 ImGuiTestEngineIO& test_io = ImGuiTestEngine_GetIO(engine);
304 test_io.ConfigRunSpeed = config.test_speed; // Use configured speed
305 test_io.ConfigVerboseLevel = ImGuiTestVerboseLevel_Info;
306 test_io.ConfigVerboseLevelOnError = ImGuiTestVerboseLevel_Debug;
307
308 // Log test speed mode
309 const char* speed_name = "Fast";
310 if (config.test_speed == ImGuiTestRunSpeed_Normal) speed_name = "Normal";
311 else if (config.test_speed == ImGuiTestRunSpeed_Cinematic) speed_name = "Cinematic";
312 std::cout << "Running tests in " << speed_name << " mode" << std::endl;
313
314 // Register E2E tests only for GUI test targets (they have the source files)
315#ifdef YAZE_GUI_TEST_TARGET
316 ImGuiTest* smoke_test = IM_REGISTER_TEST(engine, "E2ETest", "FrameworkSmokeTest");
317 smoke_test->TestFunc = E2ETest_FrameworkSmokeTest;
318
319 ImGuiTest* canvas_test = IM_REGISTER_TEST(engine, "E2ETest", "CanvasSelectionTest");
320 canvas_test->TestFunc = E2ETest_CanvasSelectionTest;
321 canvas_test->UserData = &controller;
322
323 ImGuiTest* dungeon_test = IM_REGISTER_TEST(engine, "E2ETest", "DungeonEditorSmokeTest");
324 dungeon_test->TestFunc = E2ETest_DungeonEditorV2SmokeTest;
325 dungeon_test->UserData = &controller;
326#endif
327
328 // Main loop
329 bool done = false;
330 while (!done) {
331 SDL_Event event;
332 while (SDL_PollEvent(&event)) {
333 ImGui_ImplSDL2_ProcessEvent(&event);
334 if (event.type == SDL_QUIT) {
335 done = true;
336 }
337 if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_CLOSE && event.window.windowID == SDL_GetWindowID(window.window_.get())) {
338 done = true;
339 }
340 }
341
342 // Start the Dear ImGui frame
343 ImGui_ImplSDLRenderer2_NewFrame();
344 ImGui_ImplSDL2_NewFrame();
345 ImGui::NewFrame();
346
347 // Render the UI
348 if (config.show_gui) {
349 ImGuiTestEngine_ShowTestEngineWindows(engine, &config.show_gui);
350 }
351 controller.DoRender();
352
353 // End the Dear ImGui frame
354 ImGui::Render();
355 test_renderer->Clear();
356 ImGui_ImplSDLRenderer2_RenderDrawData(ImGui::GetDrawData(), sdl_renderer);
357 test_renderer->Present();
358
359 // Update and Render additional Platform Windows
360 if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) {
361 SDL_Window* backup_current_window = SDL_GL_GetCurrentWindow();
362 SDL_GLContext backup_current_context = SDL_GL_GetCurrentContext();
363 ImGui::UpdatePlatformWindows();
364 ImGui::RenderPlatformWindowsDefault();
365 SDL_GL_MakeCurrent(backup_current_window, backup_current_context);
366 }
367
368 // Run test engine
369 ImGuiTestEngine_PostSwap(engine);
370 }
371
372 // Get test result
373 ImGuiTestEngineResultSummary summary;
374 ImGuiTestEngine_GetResultSummary(engine, &summary);
375 int result = (summary.CountSuccess == summary.CountTested) ? 0 : 1;
376
377 // Cleanup
378 controller.OnExit();
379 ImGuiTestEngine_DestroyContext(engine);
380 ImGui_ImplSDLRenderer2_Shutdown();
381 ImGui_ImplSDL2_Shutdown();
382 ImGui::DestroyContext();
383
385 SDL_Quit();
386
387 return result;
388 } else {
389 // Run tests
390 int result = RUN_ALL_TESTS();
391
392 // Cleanup SDL
393 SDL_Quit();
394
395 return result;
396 }
397}
void E2ETest_CanvasSelectionTest(ImGuiTestContext *ctx)
Main controller for the application.
Definition controller.h:24
void E2ETest_DungeonEditorV2SmokeTest(ImGuiTestContext *ctx)
Quick smoke test for DungeonEditorV2.
void E2ETest_FrameworkSmokeTest(ImGuiTestContext *ctx)
absl::Status ShutdownWindow(Window &window)
Definition window.cc:137
absl::Status CreateWindow(Window &window, gfx::IRenderer *renderer, int flags)
Definition window.cc:57
void ConfigureTestFilters(const TestConfig &config)
Definition yaze_test.cc:172
TestConfig ParseArguments(int argc, char *argv[])
Definition yaze_test.cc:62
void SetupTestEnvironment(const TestConfig &config)
Definition yaze_test.cc:152
Main namespace for the application.
std::shared_ptr< SDL_Window > window_
Definition window.h:18
ImGuiTestRunSpeed test_speed
Definition yaze_test.cc:58
std::string test_pattern
Definition yaze_test.cc:52