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 <memory>
6#include <vector>
7#include <filesystem>
8
9#include "absl/strings/str_format.h"
11#include "app/gfx/arena.h"
12#include "app/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 = absl::StrFormat(
77 "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 = "Arena integrity test failed: " + std::string(e.what());
87 }
88
89 auto end_time = std::chrono::steady_clock::now();
90 result.duration = std::chrono::duration_cast<std::chrono::milliseconds>(
91 end_time - start_time);
92
93 results.AddResult(result);
94 }
95
97 auto start_time = std::chrono::steady_clock::now();
98
99 TestResult result;
100 result.name = "Arena_Resource_Management_Test";
101 result.suite_name = GetName();
102 result.category = GetCategory();
103 result.timestamp = start_time;
104
105 try {
106 auto& arena = gfx::Arena::Get();
107
108 size_t before_textures = arena.GetTextureCount();
109 size_t before_surfaces = arena.GetSurfaceCount();
110
111 // Test surface allocation (without renderer for now)
112 // In a real test environment, we'd create a test renderer
113
114 size_t after_textures = arena.GetTextureCount();
115 size_t after_surfaces = arena.GetSurfaceCount();
116
117 // Verify resource tracking works
118 if (after_textures >= before_textures && after_surfaces >= before_surfaces) {
120 result.error_message = absl::StrFormat(
121 "Resource tracking working: %zu→%zu textures, %zu→%zu surfaces",
122 before_textures, after_textures, before_surfaces, after_surfaces);
123 } else {
125 result.error_message = "Resource counting inconsistent";
126 }
127
128 } catch (const std::exception& e) {
130 result.error_message = "Resource management test failed: " + std::string(e.what());
131 }
132
133 auto end_time = std::chrono::steady_clock::now();
134 result.duration = std::chrono::duration_cast<std::chrono::milliseconds>(
135 end_time - start_time);
136
137 results.AddResult(result);
138 }
139
141 auto start_time = std::chrono::steady_clock::now();
142
143 TestResult result;
144 result.name = "ROM_Basic_Operations_Test";
145 result.suite_name = GetName();
146 result.category = GetCategory();
147 result.timestamp = start_time;
148
149 if (!test_rom_) {
151 result.error_message = "ROM testing disabled in configuration";
152 } else {
153 try {
154 // First try to use currently loaded ROM from editor
155 Rom* current_rom = TestManager::Get().GetCurrentRom();
156
157 if (current_rom && current_rom->is_loaded()) {
158 // Test with currently loaded ROM
160 result.error_message = absl::StrFormat(
161 "Current ROM validated: %s (%zu bytes)",
162 current_rom->title().c_str(), current_rom->size());
163 } else {
164 // Fallback to loading ROM file
165 Rom test_rom;
166 std::string rom_path = test_rom_path_;
167 if (rom_path.empty()) {
168 rom_path = "zelda3.sfc";
169 }
170
171 if (std::filesystem::exists(rom_path)) {
172 auto status = test_rom.LoadFromFile(rom_path);
173 if (status.ok()) {
175 result.error_message = absl::StrFormat(
176 "ROM loaded from file: %s (%zu bytes)",
177 test_rom.title().c_str(), test_rom.size());
178 } else {
180 result.error_message = "ROM loading failed: " + std::string(status.message());
181 }
182 } else if (skip_missing_rom_) {
184 result.error_message = "No current ROM and file not found: " + rom_path;
185 } else {
187 result.error_message = "No current ROM and required file not found: " + rom_path;
188 }
189 }
190
191 } catch (const std::exception& e) {
193 result.error_message = "ROM test failed: " + std::string(e.what());
194 }
195 }
196
197 auto end_time = std::chrono::steady_clock::now();
198 result.duration = std::chrono::duration_cast<std::chrono::milliseconds>(
199 end_time - start_time);
200
201 results.AddResult(result);
202 }
203
205 auto start_time = std::chrono::steady_clock::now();
206
207 TestResult result;
208 result.name = "Graphics_Pipeline_Validation_Test";
209 result.suite_name = GetName();
210 result.category = GetCategory();
211 result.timestamp = start_time;
212
213 if (!test_graphics_) {
215 result.error_message = "Graphics testing disabled in configuration";
216 } else {
217 try {
218 // Test basic graphics pipeline components
219 auto& arena = gfx::Arena::Get();
220
221 // Test that graphics sheets can be accessed
222 auto& gfx_sheets = arena.gfx_sheets();
223
224 // Basic validation
225 if (gfx_sheets.size() == 223) {
227 result.error_message = absl::StrFormat(
228 "Graphics pipeline validated: %zu sheets available",
229 gfx_sheets.size());
230 } else {
232 result.error_message = absl::StrFormat(
233 "Graphics sheets count mismatch: expected 223, got %zu",
234 gfx_sheets.size());
235 }
236
237 } catch (const std::exception& e) {
239 result.error_message = "Graphics validation failed: " + std::string(e.what());
240 }
241 }
242
243 auto end_time = std::chrono::steady_clock::now();
244 result.duration = std::chrono::duration_cast<std::chrono::milliseconds>(
245 end_time - start_time);
246
247 results.AddResult(result);
248 }
249
250 // Configuration
251 bool test_arena_ = true;
252 bool test_rom_ = true;
253 bool test_graphics_ = true;
254 char test_rom_path_[256] = "zelda3.sfc";
255 bool skip_missing_rom_ = true;
256};
257
258// Performance test suite for monitoring system performance
260 public:
262 ~PerformanceTestSuite() override = default;
263
264 std::string GetName() const override { return "Performance Tests"; }
266
267 absl::Status RunTests(TestResults& results) override {
268 RunFrameRateTest(results);
269 RunMemoryUsageTest(results);
270 RunResourceLeakTest(results);
271
272 return absl::OkStatus();
273 }
274
275 void DrawConfiguration() override {
276 ImGui::Text("Performance Test Configuration");
277 ImGui::InputInt("Sample duration (seconds)", &sample_duration_secs_);
278 ImGui::InputFloat("Target FPS", &target_fps_);
279 ImGui::InputInt("Max memory MB", &max_memory_mb_);
280 }
281
282 private:
284 auto start_time = std::chrono::steady_clock::now();
285
286 TestResult result;
287 result.name = "Frame_Rate_Test";
288 result.suite_name = GetName();
289 result.category = GetCategory();
290 result.timestamp = start_time;
291
292 try {
293 // Sample current frame rate
294 float current_fps = ImGui::GetIO().Framerate;
295
296 if (current_fps >= target_fps_) {
298 result.error_message = absl::StrFormat(
299 "Frame rate acceptable: %.1f FPS (target: %.1f)",
300 current_fps, target_fps_);
301 } else {
303 result.error_message = absl::StrFormat(
304 "Frame rate below target: %.1f FPS (target: %.1f)",
305 current_fps, target_fps_);
306 }
307
308 } catch (const std::exception& e) {
310 result.error_message = "Frame rate test failed: " + std::string(e.what());
311 }
312
313 auto end_time = std::chrono::steady_clock::now();
314 result.duration = std::chrono::duration_cast<std::chrono::milliseconds>(
315 end_time - start_time);
316
317 results.AddResult(result);
318 }
319
321 auto start_time = std::chrono::steady_clock::now();
322
323 TestResult result;
324 result.name = "Memory_Usage_Test";
325 result.suite_name = GetName();
326 result.category = GetCategory();
327 result.timestamp = start_time;
328
329 try {
330 auto& arena = gfx::Arena::Get();
331
332 // Estimate memory usage based on resource counts
333 size_t texture_count = arena.GetTextureCount();
334 size_t surface_count = arena.GetSurfaceCount();
335
336 // Rough estimation: each texture/surface ~1KB average
337 size_t estimated_memory_kb = (texture_count + surface_count);
338 size_t estimated_memory_mb = estimated_memory_kb / 1024;
339
340 if (static_cast<int>(estimated_memory_mb) <= max_memory_mb_) {
342 result.error_message = absl::StrFormat(
343 "Memory usage acceptable: ~%zu MB (%zu textures, %zu surfaces)",
344 estimated_memory_mb, texture_count, surface_count);
345 } else {
347 result.error_message = absl::StrFormat(
348 "Memory usage high: ~%zu MB (limit: %d MB)",
349 estimated_memory_mb, max_memory_mb_);
350 }
351
352 } catch (const std::exception& e) {
354 result.error_message = "Memory usage test failed: " + std::string(e.what());
355 }
356
357 auto end_time = std::chrono::steady_clock::now();
358 result.duration = std::chrono::duration_cast<std::chrono::milliseconds>(
359 end_time - start_time);
360
361 results.AddResult(result);
362 }
363
365 auto start_time = std::chrono::steady_clock::now();
366
367 TestResult result;
368 result.name = "Resource_Leak_Test";
369 result.suite_name = GetName();
370 result.category = GetCategory();
371 result.timestamp = start_time;
372
373 try {
374 auto& arena = gfx::Arena::Get();
375
376 // Get baseline resource counts
377 size_t baseline_textures = arena.GetTextureCount();
378 size_t baseline_surfaces = arena.GetSurfaceCount();
379
380 // Simulate some operations (this would be more comprehensive with actual workload)
381 // For now, just verify resource counts remain stable
382
383 size_t final_textures = arena.GetTextureCount();
384 size_t final_surfaces = arena.GetSurfaceCount();
385
386 // Check for unexpected resource growth
387 size_t texture_diff = final_textures > baseline_textures ?
388 final_textures - baseline_textures : 0;
389 size_t surface_diff = final_surfaces > baseline_surfaces ?
390 final_surfaces - baseline_surfaces : 0;
391
392 if (texture_diff == 0 && surface_diff == 0) {
394 result.error_message = "No resource leaks detected";
395 } else if (texture_diff < 10 && surface_diff < 10) {
397 result.error_message = absl::StrFormat(
398 "Minor resource growth: +%zu textures, +%zu surfaces (acceptable)",
399 texture_diff, surface_diff);
400 } else {
402 result.error_message = absl::StrFormat(
403 "Potential resource leak: +%zu textures, +%zu surfaces",
404 texture_diff, surface_diff);
405 }
406
407 } catch (const std::exception& e) {
409 result.error_message = "Resource leak test failed: " + std::string(e.what());
410 }
411
412 auto end_time = std::chrono::steady_clock::now();
413 result.duration = std::chrono::duration_cast<std::chrono::milliseconds>(
414 end_time - start_time);
415
416 results.AddResult(result);
417 }
418
419 // Configuration
420 bool test_arena_ = true;
421 bool test_rom_ = true;
422 bool test_graphics_ = true;
424 float target_fps_ = 30.0f;
425 int max_memory_mb_ = 100;
426 char test_rom_path_[256] = "zelda3.sfc";
427 bool skip_missing_rom_ = true;
428};
429
430// UI Testing suite that integrates with ImGui Test Engine
431class UITestSuite : public TestSuite {
432 public:
433 UITestSuite() = default;
434 ~UITestSuite() override = default;
435
436 std::string GetName() const override { return "UI Interaction Tests"; }
437 TestCategory GetCategory() const override { return TestCategory::kUI; }
438
439 absl::Status RunTests(TestResults& results) override {
440#ifdef YAZE_ENABLE_IMGUI_TEST_ENGINE
441 RunMenuInteractionTest(results);
442 RunDialogTest(results);
443 RunTestDashboardTest(results);
444#else
445 TestResult result;
446 result.name = "UI_Tests_Disabled";
447 result.suite_name = GetName();
448 result.category = GetCategory();
450 result.error_message = "ImGui Test Engine not available in this build";
451 result.duration = std::chrono::milliseconds{0};
452 result.timestamp = std::chrono::steady_clock::now();
453 results.AddResult(result);
454#endif
455
456 return absl::OkStatus();
457 }
458
459 void DrawConfiguration() override {
460 ImGui::Text("UI Test Configuration");
461#ifdef YAZE_ENABLE_IMGUI_TEST_ENGINE
462 ImGui::Checkbox("Test menu interactions", &test_menus_);
463 ImGui::Checkbox("Test dialog workflows", &test_dialogs_);
464 ImGui::Checkbox("Test dashboard UI", &test_dashboard_);
465 ImGui::InputFloat("UI interaction delay (ms)", &interaction_delay_ms_);
466#else
467 ImGui::TextColored(ImVec4(1.0f, 0.5f, 0.0f, 1.0f),
468 "UI tests not available - ImGui Test Engine disabled");
469#endif
470 }
471
472 private:
473#ifdef YAZE_ENABLE_IMGUI_TEST_ENGINE
474 void RunMenuInteractionTest(TestResults& results) {
475 auto start_time = std::chrono::steady_clock::now();
476
477 TestResult result;
478 result.name = "Menu_Interaction_Test";
479 result.suite_name = GetName();
480 result.category = GetCategory();
481 result.timestamp = start_time;
482
483 try {
484 auto* engine = TestManager::Get().GetUITestEngine();
485 if (engine) {
486 // This would register and run actual UI tests
487 // For now, just verify the test engine is available
489 result.error_message = "UI test engine available for menu testing";
490 } else {
492 result.error_message = "UI test engine not available";
493 }
494 } catch (const std::exception& e) {
496 result.error_message = "Menu interaction test failed: " + std::string(e.what());
497 }
498
499 auto end_time = std::chrono::steady_clock::now();
500 result.duration = std::chrono::duration_cast<std::chrono::milliseconds>(
501 end_time - start_time);
502
503 results.AddResult(result);
504 }
505
506 void RunDialogTest(TestResults& results) {
507 auto start_time = std::chrono::steady_clock::now();
508
509 TestResult result;
510 result.name = "Dialog_Workflow_Test";
511 result.suite_name = GetName();
512 result.category = GetCategory();
513 result.timestamp = start_time;
514
515 // Placeholder for dialog testing
516 result.status = TestStatus::kSkipped;
517 result.error_message = "Dialog testing not yet implemented";
518
519 auto end_time = std::chrono::steady_clock::now();
520 result.duration = std::chrono::duration_cast<std::chrono::milliseconds>(
521 end_time - start_time);
522
523 results.AddResult(result);
524 }
525
526 void RunTestDashboardTest(TestResults& results) {
527 auto start_time = std::chrono::steady_clock::now();
528
529 TestResult result;
530 result.name = "Test_Dashboard_UI_Test";
531 result.suite_name = GetName();
532 result.category = GetCategory();
533 result.timestamp = start_time;
534
535 // Test that the dashboard can be accessed and drawn
536 try {
537 // The fact that we're running this test means the dashboard is working
538 result.status = TestStatus::kPassed;
539 result.error_message = "Test dashboard UI functioning correctly";
540 } catch (const std::exception& e) {
541 result.status = TestStatus::kFailed;
542 result.error_message = "Dashboard test failed: " + std::string(e.what());
543 }
544
545 auto end_time = std::chrono::steady_clock::now();
546 result.duration = std::chrono::duration_cast<std::chrono::milliseconds>(
547 end_time - start_time);
548
549 results.AddResult(result);
550 }
551
552 bool test_menus_ = true;
553 bool test_dialogs_ = true;
554 bool test_dashboard_ = true;
555 float interaction_delay_ms_ = 100.0f;
556#endif
557};
558
559} // namespace test
560} // namespace yaze
561
562#endif // YAZE_APP_TEST_INTEGRATED_TEST_SUITE_H
The Rom class is used to load, save, and modify Rom data.
Definition rom.h:71
absl::Status LoadFromFile(const std::string &filename, bool z3_load=true)
Definition rom.cc:289
auto size() const
Definition rom.h:202
bool is_loaded() const
Definition rom.h:197
auto title() const
Definition rom.h:201
static Arena & Get()
Definition arena.cc:15
~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
Main namespace for the application.
std::chrono::milliseconds duration
std::string error_message
std::chrono::time_point< std::chrono::steady_clock > timestamp
void AddResult(const TestResult &result)