yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
integrated_test_suite.h
Go to the documentation of this file.
1#ifndef YAZE_APP_TEST_INTEGRATED_TEST_SUITE_H
2#define YAZE_APP_TEST_INTEGRATED_TEST_SUITE_H
3
4#include <chrono>
5#include <filesystem>
6#include <memory>
7#include <vector>
8
9#include "absl/strings/str_format.h"
10#include "app/gfx/arena.h"
11#include "rom/rom.h"
13
14#ifdef YAZE_ENABLE_GTEST
15#include <gtest/gtest.h>
16#endif
17
18namespace yaze {
19namespace test {
20
21// Integrated test suite that runs actual unit tests within the main application
23 public:
25 ~IntegratedTestSuite() override = default;
26
27 std::string GetName() const override { return "Integrated Unit Tests"; }
28 TestCategory GetCategory() const override { return TestCategory::kUnit; }
29
30 absl::Status RunTests(TestResults& results) override {
31 // Run Arena tests
32 RunArenaIntegrityTest(results);
34
35 // Run ROM tests
36 RunRomBasicTest(results);
37
38 // Run Graphics tests
40
41 return absl::OkStatus();
42 }
43
44 void DrawConfiguration() override {
45 ImGui::Text("Integrated Test Configuration");
46 ImGui::Checkbox("Test Arena operations", &test_arena_);
47 ImGui::Checkbox("Test ROM loading", &test_rom_);
48 ImGui::Checkbox("Test graphics pipeline", &test_graphics_);
49
50 if (ImGui::CollapsingHeader("ROM Test Settings")) {
51 ImGui::InputText("Test ROM Path", test_rom_path_, sizeof(test_rom_path_));
52 ImGui::Checkbox("Skip ROM tests if file missing", &skip_missing_rom_);
53 }
54 }
55
56 private:
58 auto start_time = std::chrono::steady_clock::now();
59
60 TestResult result;
61 result.name = "Arena_Integrity_Test";
62 result.suite_name = GetName();
63 result.category = GetCategory();
64 result.timestamp = start_time;
65
66 try {
67 auto& arena = gfx::Arena::Get();
68
69 // Test basic Arena functionality
70 size_t initial_textures = arena.GetTextureCount();
71 size_t initial_surfaces = arena.GetSurfaceCount();
72
73 // Verify Arena is properly initialized
74 if (initial_textures >= 0 && initial_surfaces >= 0) {
76 result.error_message =
77 absl::StrFormat("Arena initialized: %zu textures, %zu surfaces",
78 initial_textures, initial_surfaces);
79 } else {
81 result.error_message = "Arena returned invalid resource counts";
82 }
83
84 } catch (const std::exception& e) {
86 result.error_message =
87 "Arena integrity test failed: " + std::string(e.what());
88 }
89
90 auto end_time = std::chrono::steady_clock::now();
91 result.duration = std::chrono::duration_cast<std::chrono::milliseconds>(
92 end_time - start_time);
93
94 results.AddResult(result);
95 }
96
98 auto start_time = std::chrono::steady_clock::now();
99
100 TestResult result;
101 result.name = "Arena_Resource_Management_Test";
102 result.suite_name = GetName();
103 result.category = GetCategory();
104 result.timestamp = start_time;
105
106 try {
107 auto& arena = gfx::Arena::Get();
108
109 size_t before_textures = arena.GetTextureCount();
110 size_t before_surfaces = arena.GetSurfaceCount();
111
112 // Test surface allocation (without renderer for now)
113 // In a real test environment, we'd create a test renderer
114
115 size_t after_textures = arena.GetTextureCount();
116 size_t after_surfaces = arena.GetSurfaceCount();
117
118 // Verify resource tracking works
119 if (after_textures >= before_textures &&
120 after_surfaces >= before_surfaces) {
122 result.error_message = absl::StrFormat(
123 "Resource tracking working: %zu→%zu textures, %zu→%zu surfaces",
124 before_textures, after_textures, before_surfaces, after_surfaces);
125 } else {
127 result.error_message = "Resource counting inconsistent";
128 }
129
130 } catch (const std::exception& e) {
132 result.error_message =
133 "Resource management test failed: " + std::string(e.what());
134 }
135
136 auto end_time = std::chrono::steady_clock::now();
137 result.duration = std::chrono::duration_cast<std::chrono::milliseconds>(
138 end_time - start_time);
139
140 results.AddResult(result);
141 }
142
144 auto start_time = std::chrono::steady_clock::now();
145
146 TestResult result;
147 result.name = "ROM_Basic_Operations_Test";
148 result.suite_name = GetName();
149 result.category = GetCategory();
150 result.timestamp = start_time;
151
152 if (!test_rom_) {
154 result.error_message = "ROM testing disabled in configuration";
155 } else {
156 try {
157 // First try to use currently loaded ROM from editor
158 Rom* current_rom = TestManager::Get().GetCurrentRom();
159
160 if (current_rom && current_rom->is_loaded()) {
161 // Test with currently loaded ROM
163 result.error_message = absl::StrFormat(
164 "Current ROM validated: %s (%zu bytes)",
165 current_rom->title().c_str(), current_rom->size());
166 } else {
167 // Fallback to loading ROM file
168 Rom test_rom;
169 std::string rom_path = test_rom_path_;
170 if (rom_path.empty()) {
171 rom_path = "zelda3.sfc";
172 }
173
174 if (std::filesystem::exists(rom_path)) {
175 auto status = test_rom.LoadFromFile(rom_path);
176 if (status.ok()) {
178 result.error_message =
179 absl::StrFormat("ROM loaded from file: %s (%zu bytes)",
180 test_rom.title().c_str(), test_rom.size());
181 } else {
183 result.error_message =
184 "ROM loading failed: " + std::string(status.message());
185 }
186 } else if (skip_missing_rom_) {
188 result.error_message =
189 "No current ROM and file not found: " + rom_path;
190 } else {
192 result.error_message =
193 "No current ROM and required file not found: " + rom_path;
194 }
195 }
196
197 } catch (const std::exception& e) {
199 result.error_message = "ROM test failed: " + std::string(e.what());
200 }
201 }
202
203 auto end_time = std::chrono::steady_clock::now();
204 result.duration = std::chrono::duration_cast<std::chrono::milliseconds>(
205 end_time - start_time);
206
207 results.AddResult(result);
208 }
209
211 auto start_time = std::chrono::steady_clock::now();
212
213 TestResult result;
214 result.name = "Graphics_Pipeline_Validation_Test";
215 result.suite_name = GetName();
216 result.category = GetCategory();
217 result.timestamp = start_time;
218
219 if (!test_graphics_) {
221 result.error_message = "Graphics testing disabled in configuration";
222 } else {
223 try {
224 // Test basic graphics pipeline components
225 auto& arena = gfx::Arena::Get();
226
227 // Test that graphics sheets can be accessed
228 auto& gfx_sheets = arena.gfx_sheets();
229
230 // Basic validation
231 if (gfx_sheets.size() == 223) {
233 result.error_message = absl::StrFormat(
234 "Graphics pipeline validated: %zu sheets available",
235 gfx_sheets.size());
236 } else {
238 result.error_message = absl::StrFormat(
239 "Graphics sheets count mismatch: expected 223, got %zu",
240 gfx_sheets.size());
241 }
242
243 } catch (const std::exception& e) {
245 result.error_message =
246 "Graphics validation failed: " + std::string(e.what());
247 }
248 }
249
250 auto end_time = std::chrono::steady_clock::now();
251 result.duration = std::chrono::duration_cast<std::chrono::milliseconds>(
252 end_time - start_time);
253
254 results.AddResult(result);
255 }
256
257 // Configuration
258 bool test_arena_ = true;
259 bool test_rom_ = true;
260 bool test_graphics_ = true;
261 char test_rom_path_[256] = "zelda3.sfc";
262 bool skip_missing_rom_ = true;
263};
264
265// Performance test suite for monitoring system performance
267 public:
269 ~PerformanceTestSuite() override = default;
270
271 std::string GetName() const override { return "Performance Tests"; }
272 TestCategory GetCategory() const override {
274 }
275
276 absl::Status RunTests(TestResults& results) override {
277 RunFrameRateTest(results);
278 RunMemoryUsageTest(results);
279 RunResourceLeakTest(results);
280
281 return absl::OkStatus();
282 }
283
284 void DrawConfiguration() override {
285 ImGui::Text("Performance Test Configuration");
286 ImGui::InputInt("Sample duration (seconds)", &sample_duration_secs_);
287 ImGui::InputFloat("Target FPS", &target_fps_);
288 ImGui::InputInt("Max memory MB", &max_memory_mb_);
289 }
290
291 private:
293 auto start_time = std::chrono::steady_clock::now();
294
295 TestResult result;
296 result.name = "Frame_Rate_Test";
297 result.suite_name = GetName();
298 result.category = GetCategory();
299 result.timestamp = start_time;
300
301 try {
302 // Sample current frame rate
303 float current_fps = ImGui::GetIO().Framerate;
304
305 if (current_fps >= target_fps_) {
307 result.error_message =
308 absl::StrFormat("Frame rate acceptable: %.1f FPS (target: %.1f)",
309 current_fps, target_fps_);
310 } else {
312 result.error_message =
313 absl::StrFormat("Frame rate below target: %.1f FPS (target: %.1f)",
314 current_fps, target_fps_);
315 }
316
317 } catch (const std::exception& e) {
319 result.error_message = "Frame rate test failed: " + std::string(e.what());
320 }
321
322 auto end_time = std::chrono::steady_clock::now();
323 result.duration = std::chrono::duration_cast<std::chrono::milliseconds>(
324 end_time - start_time);
325
326 results.AddResult(result);
327 }
328
330 auto start_time = std::chrono::steady_clock::now();
331
332 TestResult result;
333 result.name = "Memory_Usage_Test";
334 result.suite_name = GetName();
335 result.category = GetCategory();
336 result.timestamp = start_time;
337
338 try {
339 auto& arena = gfx::Arena::Get();
340
341 // Estimate memory usage based on resource counts
342 size_t texture_count = arena.GetTextureCount();
343 size_t surface_count = arena.GetSurfaceCount();
344
345 // Rough estimation: each texture/surface ~1KB average
346 size_t estimated_memory_kb = (texture_count + surface_count);
347 size_t estimated_memory_mb = estimated_memory_kb / 1024;
348
349 if (static_cast<int>(estimated_memory_mb) <= max_memory_mb_) {
351 result.error_message = absl::StrFormat(
352 "Memory usage acceptable: ~%zu MB (%zu textures, %zu surfaces)",
353 estimated_memory_mb, texture_count, surface_count);
354 } else {
356 result.error_message =
357 absl::StrFormat("Memory usage high: ~%zu MB (limit: %d MB)",
358 estimated_memory_mb, max_memory_mb_);
359 }
360
361 } catch (const std::exception& e) {
363 result.error_message =
364 "Memory usage test failed: " + std::string(e.what());
365 }
366
367 auto end_time = std::chrono::steady_clock::now();
368 result.duration = std::chrono::duration_cast<std::chrono::milliseconds>(
369 end_time - start_time);
370
371 results.AddResult(result);
372 }
373
375 auto start_time = std::chrono::steady_clock::now();
376
377 TestResult result;
378 result.name = "Resource_Leak_Test";
379 result.suite_name = GetName();
380 result.category = GetCategory();
381 result.timestamp = start_time;
382
383 try {
384 auto& arena = gfx::Arena::Get();
385
386 // Get baseline resource counts
387 size_t baseline_textures = arena.GetTextureCount();
388 size_t baseline_surfaces = arena.GetSurfaceCount();
389
390 // Simulate some operations (this would be more comprehensive with actual
391 // workload) For now, just verify resource counts remain stable
392
393 size_t final_textures = arena.GetTextureCount();
394 size_t final_surfaces = arena.GetSurfaceCount();
395
396 // Check for unexpected resource growth
397 size_t texture_diff = final_textures > baseline_textures
398 ? final_textures - baseline_textures
399 : 0;
400 size_t surface_diff = final_surfaces > baseline_surfaces
401 ? final_surfaces - baseline_surfaces
402 : 0;
403
404 if (texture_diff == 0 && surface_diff == 0) {
406 result.error_message = "No resource leaks detected";
407 } else if (texture_diff < 10 && surface_diff < 10) {
409 result.error_message = absl::StrFormat(
410 "Minor resource growth: +%zu textures, +%zu surfaces (acceptable)",
411 texture_diff, surface_diff);
412 } else {
414 result.error_message = absl::StrFormat(
415 "Potential resource leak: +%zu textures, +%zu surfaces",
416 texture_diff, surface_diff);
417 }
418
419 } catch (const std::exception& e) {
421 result.error_message =
422 "Resource leak test failed: " + std::string(e.what());
423 }
424
425 auto end_time = std::chrono::steady_clock::now();
426 result.duration = std::chrono::duration_cast<std::chrono::milliseconds>(
427 end_time - start_time);
428
429 results.AddResult(result);
430 }
431
432 // Configuration
433 bool test_arena_ = true;
434 bool test_rom_ = true;
435 bool test_graphics_ = true;
437 float target_fps_ = 30.0f;
438 int max_memory_mb_ = 100;
439 char test_rom_path_[256] = "zelda3.sfc";
440 bool skip_missing_rom_ = true;
441};
442
443// UI Testing suite that integrates with ImGui Test Engine
444class UITestSuite : public TestSuite {
445 public:
446 UITestSuite() = default;
447 ~UITestSuite() override = default;
448
449 std::string GetName() const override { return "UI Interaction Tests"; }
450 TestCategory GetCategory() const override { return TestCategory::kUI; }
451
452 absl::Status RunTests(TestResults& results) override {
453#ifdef YAZE_ENABLE_IMGUI_TEST_ENGINE
454 RunMenuInteractionTest(results);
455 RunDialogTest(results);
456 RunTestDashboardTest(results);
457#else
458 TestResult result;
459 result.name = "UI_Tests_Disabled";
460 result.suite_name = GetName();
461 result.category = GetCategory();
463 result.error_message = "ImGui Test Engine not available in this build";
464 result.duration = std::chrono::milliseconds{0};
465 result.timestamp = std::chrono::steady_clock::now();
466 results.AddResult(result);
467#endif
468
469 return absl::OkStatus();
470 }
471
472 void DrawConfiguration() override {
473 ImGui::Text("UI Test Configuration");
474#ifdef YAZE_ENABLE_IMGUI_TEST_ENGINE
475 ImGui::Checkbox("Test menu interactions", &test_menus_);
476 ImGui::Checkbox("Test dialog workflows", &test_dialogs_);
477 ImGui::Checkbox("Test dashboard UI", &test_dashboard_);
478 ImGui::InputFloat("UI interaction delay (ms)", &interaction_delay_ms_);
479#else
480 ImGui::TextColored(ImVec4(1.0f, 0.5f, 0.0f, 1.0f),
481 "UI tests not available - ImGui Test Engine disabled");
482#endif
483 }
484
485 private:
486#ifdef YAZE_ENABLE_IMGUI_TEST_ENGINE
487 void RunMenuInteractionTest(TestResults& results) {
488 auto start_time = std::chrono::steady_clock::now();
489
490 TestResult result;
491 result.name = "Menu_Interaction_Test";
492 result.suite_name = GetName();
493 result.category = GetCategory();
494 result.timestamp = start_time;
495
496 try {
497 auto* engine = TestManager::Get().GetUITestEngine();
498 if (engine) {
499 // This would register and run actual UI tests
500 // For now, just verify the test engine is available
502 result.error_message = "UI test engine available for menu testing";
503 } else {
505 result.error_message = "UI test engine not available";
506 }
507 } catch (const std::exception& e) {
509 result.error_message =
510 "Menu interaction test failed: " + std::string(e.what());
511 }
512
513 auto end_time = std::chrono::steady_clock::now();
514 result.duration = std::chrono::duration_cast<std::chrono::milliseconds>(
515 end_time - start_time);
516
517 results.AddResult(result);
518 }
519
520 void RunDialogTest(TestResults& results) {
521 auto start_time = std::chrono::steady_clock::now();
522
523 TestResult result;
524 result.name = "Dialog_Workflow_Test";
525 result.suite_name = GetName();
526 result.category = GetCategory();
527 result.timestamp = start_time;
528
529 // Placeholder for dialog testing
530 result.status = TestStatus::kSkipped;
531 result.error_message = "Dialog testing not yet implemented";
532
533 auto end_time = std::chrono::steady_clock::now();
534 result.duration = std::chrono::duration_cast<std::chrono::milliseconds>(
535 end_time - start_time);
536
537 results.AddResult(result);
538 }
539
540 void RunTestDashboardTest(TestResults& results) {
541 auto start_time = std::chrono::steady_clock::now();
542
543 TestResult result;
544 result.name = "Test_Dashboard_UI_Test";
545 result.suite_name = GetName();
546 result.category = GetCategory();
547 result.timestamp = start_time;
548
549 // Test that the dashboard can be accessed and drawn
550 try {
551 // The fact that we're running this test means the dashboard is working
552 result.status = TestStatus::kPassed;
553 result.error_message = "Test dashboard UI functioning correctly";
554 } catch (const std::exception& e) {
555 result.status = TestStatus::kFailed;
556 result.error_message = "Dashboard test failed: " + std::string(e.what());
557 }
558
559 auto end_time = std::chrono::steady_clock::now();
560 result.duration = std::chrono::duration_cast<std::chrono::milliseconds>(
561 end_time - start_time);
562
563 results.AddResult(result);
564 }
565
566 bool test_menus_ = true;
567 bool test_dialogs_ = true;
568 bool test_dashboard_ = true;
569 float interaction_delay_ms_ = 100.0f;
570#endif
571};
572
573} // namespace test
574} // namespace yaze
575
576#endif // YAZE_APP_TEST_INTEGRATED_TEST_SUITE_H
The Rom class is used to load, save, and modify Rom data. This is a generic SNES ROM container and do...
Definition rom.h:24
absl::Status LoadFromFile(const std::string &filename, const LoadOptions &options=LoadOptions::Defaults())
Definition rom.cc:74
auto size() const
Definition rom.h:134
bool is_loaded() const
Definition rom.h:128
auto title() const
Definition rom.h:133
static Arena & Get()
Definition arena.cc:19
~IntegratedTestSuite() override=default
void RunGraphicsValidationTest(TestResults &results)
void RunArenaIntegrityTest(TestResults &results)
void RunArenaResourceManagementTest(TestResults &results)
TestCategory GetCategory() const override
void RunRomBasicTest(TestResults &results)
std::string GetName() const override
absl::Status RunTests(TestResults &results) override
void RunFrameRateTest(TestResults &results)
void RunMemoryUsageTest(TestResults &results)
void RunResourceLeakTest(TestResults &results)
absl::Status RunTests(TestResults &results) override
std::string GetName() const override
TestCategory GetCategory() const override
~PerformanceTestSuite() override=default
Rom * GetCurrentRom() const
static TestManager & Get()
std::string GetName() const override
TestCategory GetCategory() const override
~UITestSuite() override=default
absl::Status RunTests(TestResults &results) override
std::chrono::milliseconds duration
std::string error_message
std::chrono::time_point< std::chrono::steady_clock > timestamp
void AddResult(const TestResult &result)