yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
test_manager.h
Go to the documentation of this file.
1#ifndef YAZE_APP_TEST_TEST_MANAGER_H
2#define YAZE_APP_TEST_TEST_MANAGER_H
3
4#include <chrono>
5#include <deque>
6#include <functional>
7#include <map>
8#include <memory>
9#include <string>
10#include <unordered_map>
11#include <vector>
12
13#include "absl/status/status.h"
14#include "absl/status/statusor.h"
15#include "absl/strings/string_view.h"
16#include "absl/synchronization/mutex.h"
17#include "absl/time/time.h"
18#include "rom/rom.h"
19
20#define IMGUI_DEFINE_MATH_OPERATORS
21#include "imgui.h"
22#include "util/log.h"
23
24// Forward declarations
25namespace yaze {
26namespace editor {
27class EditorManager;
28}
29} // namespace yaze
30
31#if defined(YAZE_ENABLE_IMGUI_TEST_ENGINE) && YAZE_ENABLE_IMGUI_TEST_ENGINE
32#include "imgui_test_engine/imgui_te_engine.h"
33#else
34// Forward declaration when ImGui Test Engine is not available
35struct ImGuiTestEngine;
36#endif
37
38namespace yaze {
39namespace test {
40
41// Test execution status
43
44// Test categories for organization
46
47// Individual test result
48struct TestResult {
49 std::string name;
50 std::string suite_name;
53 std::string error_message;
54 std::chrono::milliseconds duration;
55 std::chrono::time_point<std::chrono::steady_clock> timestamp;
56};
57
58// Overall test results summary
60 std::vector<TestResult> individual_results;
61 size_t total_tests = 0;
62 size_t passed_tests = 0;
63 size_t failed_tests = 0;
64 size_t skipped_tests = 0;
65 std::chrono::milliseconds total_duration{0};
66
67 void AddResult(const TestResult& result) {
68 individual_results.push_back(result);
70 switch (result.status) {
73 break;
76 break;
79 break;
80 default:
81 break;
82 }
83 total_duration += result.duration;
84 }
85
86 void Clear() {
87 individual_results.clear();
89 total_duration = std::chrono::milliseconds{0};
90 }
91
92 float GetPassRate() const {
93 return total_tests > 0 ? static_cast<float>(passed_tests) / total_tests
94 : 0.0f;
95 }
96};
97
98// Base class for test suites
99class TestSuite {
100 public:
101 virtual ~TestSuite() = default;
102 virtual std::string GetName() const = 0;
103 virtual TestCategory GetCategory() const = 0;
104 virtual absl::Status RunTests(TestResults& results) = 0;
105 virtual void DrawConfiguration() {}
106 virtual bool IsEnabled() const { return enabled_; }
107 virtual void SetEnabled(bool enabled) { enabled_ = enabled; }
108
109 protected:
110 bool enabled_ = true;
111};
112
113// Resource monitoring for performance and memory tests
115 size_t texture_count = 0;
116 size_t surface_count = 0;
117 size_t memory_usage_mb = 0;
118 float frame_rate = 0.0f;
119 std::chrono::time_point<std::chrono::steady_clock> timestamp;
120};
121
122// Test harness execution tracking for gRPC automation (IT-05)
123#if defined(YAZE_WITH_GRPC)
124enum class HarnessTestStatus {
125 kUnspecified,
126 kQueued,
127 kRunning,
128 kPassed,
129 kFailed,
130 kTimeout,
131};
132
133const char* HarnessStatusToString(HarnessTestStatus status);
134HarnessTestStatus HarnessStatusFromString(absl::string_view status);
135
136struct HarnessTestExecution {
137 std::string test_id;
138 std::string name;
139 std::string category;
140 HarnessTestStatus status = HarnessTestStatus::kUnspecified;
141 absl::Time queued_at;
142 absl::Time started_at;
143 absl::Time completed_at;
144 absl::Duration duration = absl::ZeroDuration();
145 std::string error_message;
146 std::vector<std::string> assertion_failures;
147 std::vector<std::string> logs;
148 std::map<std::string, int32_t> metrics;
149
150 // IT-08b: Failure diagnostics
151 std::string screenshot_path;
152 int64_t screenshot_size_bytes = 0;
153 std::string failure_context;
154 std::string widget_state; // IT-08c (future)
155};
156
157struct HarnessTestSummary {
158 HarnessTestExecution latest_execution;
159 int total_runs = 0;
160 int pass_count = 0;
161 int fail_count = 0;
162 absl::Duration total_duration = absl::ZeroDuration();
163};
164
165class HarnessListener {
166 public:
167 virtual ~HarnessListener() = default;
168 virtual void OnHarnessTestUpdated(const HarnessTestExecution& execution) = 0;
169 virtual void OnHarnessPlanSummary(const std::string& summary) = 0;
170};
171#endif // defined(YAZE_WITH_GRPC)
172
173// Main test manager - singleton
175 public:
176 static TestManager& Get();
177
178 // Core test execution
179 absl::Status RunAllTests();
180 absl::Status RunTestsByCategory(TestCategory category);
181 absl::Status RunTestSuite(const std::string& suite_name);
182
183 // Test suite management
184 void RegisterTestSuite(std::unique_ptr<TestSuite> suite);
185 std::vector<std::string> GetTestSuiteNames() const;
186 TestSuite* GetTestSuite(const std::string& name);
187
188 // Results access
189 const TestResults& GetLastResults() const { return last_results_; }
191
192 // Configuration
193 void SetMaxConcurrentTests(size_t max_concurrent) {
194 max_concurrent_tests_ = max_concurrent;
195 }
196 void SetTestTimeout(std::chrono::seconds timeout) { test_timeout_ = timeout; }
197
198 // Resource monitoring
199 void UpdateResourceStats();
200 const std::vector<ResourceStats>& GetResourceHistory() const {
201 return resource_history_;
202 }
203
204 // UI Testing (ImGui Test Engine integration)
205#if defined(YAZE_ENABLE_IMGUI_TEST_ENGINE) && YAZE_ENABLE_IMGUI_TEST_ENGINE
206 ImGuiTestEngine* GetUITestEngine() { return ui_test_engine_; }
207 void InitializeUITesting();
208 void StopUITesting(); // Stop test engine while ImGui context is valid
209 void DestroyUITestingContext(); // Destroy test engine after ImGui context is
210 // destroyed
211 void ShutdownUITesting(); // Complete shutdown (calls both Stop and Destroy)
212#else
213 void* GetUITestEngine() { return nullptr; }
218#endif
219
220 // Status queries
221 bool IsTestRunning() const { return is_running_; }
222 const std::string& GetCurrentTestName() const { return current_test_name_; }
223 float GetProgress() const { return progress_; }
224
225 // UI Interface
226 void DrawTestDashboard(bool* show_dashboard = nullptr);
227
228 // ROM-dependent testing
229 void SetCurrentRom(Rom* rom) {
230 LOG_INFO("TestManager", "SetCurrentRom called with ROM: %p", (void*)rom);
231 if (rom) {
232 LOG_INFO("TestManager", "ROM title: '%s', loaded: %s",
233 rom->title().c_str(), rom->is_loaded() ? "true" : "false");
234 }
235 current_rom_ = rom;
236 }
237 Rom* GetCurrentRom() const { return current_rom_; }
238 void RefreshCurrentRom(); // Refresh ROM pointer from editor manager
239 // Remove EditorManager dependency to avoid circular includes
240
241 // Enhanced ROM testing
242 absl::Status LoadRomForTesting(const std::string& filename);
243 void ShowRomComparisonResults(const Rom& before, const Rom& after);
244
245 // Test ROM management
246 absl::Status CreateTestRomCopy(Rom* source_rom,
247 std::unique_ptr<Rom>& test_rom);
248 std::string GenerateTestRomFilename(const std::string& base_name);
249 void OfferTestSessionCreation(const std::string& test_rom_path);
250
251 public:
252 // ROM testing methods (work on copies, not originals)
253 absl::Status TestRomSaveLoad(Rom* rom);
254 absl::Status TestRomDataIntegrity(Rom* rom);
255 absl::Status TestRomWithCopy(Rom* source_rom,
256 std::function<absl::Status(Rom*)> test_function);
257
258 // Test configuration management
259 void DisableTest(const std::string& test_name) {
260 disabled_tests_[test_name] = true;
261 }
262 void EnableTest(const std::string& test_name) {
263 disabled_tests_[test_name] = false;
264 }
265 bool IsTestEnabled(const std::string& test_name) const {
266 auto it = disabled_tests_.find(test_name);
267 return it == disabled_tests_.end() || !it->second;
268 }
269 // File dialog mode now uses global feature flags
270
271 // Harness test introspection (IT-05)
272#if defined(YAZE_WITH_GRPC)
273 std::string RegisterHarnessTest(const std::string& name,
274 const std::string& category)
275 ABSL_LOCKS_EXCLUDED(harness_history_mutex_);
276 void MarkHarnessTestRunning(const std::string& test_id)
277 ABSL_LOCKS_EXCLUDED(harness_history_mutex_);
278 void MarkHarnessTestCompleted(
279 const std::string& test_id, HarnessTestStatus status,
280 const std::string& error_message = "",
281 const std::vector<std::string>& assertion_failures = {},
282 const std::vector<std::string>& logs = {},
283 const std::map<std::string, int32_t>& metrics = {})
284 ABSL_LOCKS_EXCLUDED(harness_history_mutex_);
285 void AppendHarnessTestLog(const std::string& test_id,
286 const std::string& log_entry)
287 ABSL_LOCKS_EXCLUDED(harness_history_mutex_);
288 absl::StatusOr<HarnessTestExecution> GetHarnessTestExecution(
289 const std::string& test_id) const
290 ABSL_LOCKS_EXCLUDED(harness_history_mutex_);
291 std::vector<HarnessTestSummary> ListHarnessTestSummaries(
292 const std::string& category_filter = "") const
293 ABSL_LOCKS_EXCLUDED(harness_history_mutex_);
294
295 // IT-08b: Capture failure diagnostics
296 void CaptureFailureContext(const std::string& test_id)
297 ABSL_LOCKS_EXCLUDED(harness_history_mutex_);
298
299 void SetHarnessListener(HarnessListener* listener);
300
301 absl::Status ReplayLastPlan();
302#else
303 // Stub implementations when GRPC is not available
304 std::string RegisterHarnessTest(const std::string& name,
305 const std::string& category);
306 void CaptureFailureContext(const std::string& test_id);
307 absl::Status ReplayLastPlan();
308#endif
309
310 // These methods are always available
311 absl::Status ShowHarnessDashboard();
312 absl::Status ShowHarnessActiveTests();
313 void RecordPlanSummary(const std::string& summary);
314
315 private:
316 TestManager();
317 ~TestManager();
318
319 // Test execution helpers
320 absl::Status ExecuteTestSuite(TestSuite* suite);
321 void UpdateProgress();
322
323 // Resource monitoring helpers
325 void TrimResourceHistory();
326
327 // Member variables
328 std::vector<std::unique_ptr<TestSuite>> test_suites_;
329 std::unordered_map<std::string, TestSuite*> suite_lookup_;
330
332 bool is_running_ = false;
334 float progress_ = 0.0f;
335
336 // Configuration
338 std::chrono::seconds test_timeout_{30};
339
340 // Resource monitoring
341 std::vector<ResourceStats> resource_history_;
342 static constexpr size_t kMaxResourceHistorySize = 1000;
343
344 // UI Testing
345#ifdef YAZE_ENABLE_IMGUI_TEST_ENGINE
346 ImGuiTestEngine* ui_test_engine_ = nullptr;
347#endif
348
349 // UI State
350 bool show_dashboard_ = false;
352 std::string test_filter_;
354
355 // ROM-dependent testing
356 Rom* current_rom_ = nullptr;
357 // Removed editor_manager_ to avoid circular dependency
358
359 // UI state
360 bool show_google_tests_ = false;
366
367 // Test selection and configuration
368 std::unordered_map<std::string, bool> disabled_tests_;
369
370 // Harness test tracking
371#if defined(YAZE_WITH_GRPC)
372 struct HarnessAggregate {
373 int total_runs = 0;
374 int pass_count = 0;
375 int fail_count = 0;
376 absl::Duration total_duration = absl::ZeroDuration();
377 std::string category;
378 absl::Time last_run;
379 HarnessTestExecution latest_execution;
380 };
381
382 std::unordered_map<std::string, HarnessTestExecution> harness_history_
383 ABSL_GUARDED_BY(harness_history_mutex_);
384 std::unordered_map<std::string, HarnessAggregate> harness_aggregates_
385 ABSL_GUARDED_BY(harness_history_mutex_);
386 std::deque<std::string> harness_history_order_;
387 size_t harness_history_limit_ = 200;
388 mutable absl::Mutex harness_history_mutex_;
389#if defined(YAZE_WITH_GRPC)
390 HarnessListener* harness_listener_ ABSL_GUARDED_BY(mutex_) = nullptr;
391#endif
392#endif // defined(YAZE_WITH_GRPC)
393
394#if defined(YAZE_WITH_GRPC)
395 std::string GenerateHarnessTestIdLocked(absl::string_view prefix)
396 ABSL_EXCLUSIVE_LOCKS_REQUIRED(harness_history_mutex_);
397 void TrimHarnessHistoryLocked()
398 ABSL_EXCLUSIVE_LOCKS_REQUIRED(harness_history_mutex_);
399#endif
400
401 absl::Mutex mutex_;
402};
403
404// Utility functions for test result formatting
405const char* TestStatusToString(TestStatus status);
406const char* TestCategoryToString(TestCategory category);
407ImVec4 GetTestStatusColor(TestStatus status);
408
409} // namespace test
410} // namespace yaze
411
412#endif // YAZE_APP_TEST_TEST_MANAGER_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
bool is_loaded() const
Definition rom.h:128
auto title() const
Definition rom.h:133
std::string GenerateTestRomFilename(const std::string &base_name)
void CaptureFailureContext(const std::string &test_id)
std::string current_test_name_
Rom * GetCurrentRom() const
const TestResults & GetLastResults() const
absl::Status ShowHarnessActiveTests()
TestCategory category_filter_
absl::Status ShowHarnessDashboard()
std::vector< ResourceStats > resource_history_
void RegisterTestSuite(std::unique_ptr< TestSuite > suite)
void RecordPlanSummary(const std::string &summary)
absl::Status TestRomWithCopy(Rom *source_rom, std::function< absl::Status(Rom *)> test_function)
std::unordered_map< std::string, TestSuite * > suite_lookup_
absl::Status CreateTestRomCopy(Rom *source_rom, std::unique_ptr< Rom > &test_rom)
bool IsTestEnabled(const std::string &test_name) const
absl::Status RunTestSuite(const std::string &suite_name)
std::string RegisterHarnessTest(const std::string &name, const std::string &category)
absl::Status ExecuteTestSuite(TestSuite *suite)
void SetCurrentRom(Rom *rom)
std::string test_rom_path_for_session_
absl::Status TestRomDataIntegrity(Rom *rom)
static constexpr size_t kMaxResourceHistorySize
float GetProgress() const
void DrawTestDashboard(bool *show_dashboard=nullptr)
TestSuite * GetTestSuite(const std::string &name)
absl::Status RunAllTests()
static TestManager & Get()
void OfferTestSessionCreation(const std::string &test_rom_path)
void EnableTest(const std::string &test_name)
const std::vector< ResourceStats > & GetResourceHistory() const
void DisableTest(const std::string &test_name)
void SetTestTimeout(std::chrono::seconds timeout)
std::vector< std::unique_ptr< TestSuite > > test_suites_
absl::Status TestRomSaveLoad(Rom *rom)
void SetMaxConcurrentTests(size_t max_concurrent)
std::chrono::seconds test_timeout_
absl::Status RunTestsByCategory(TestCategory category)
void ShowRomComparisonResults(const Rom &before, const Rom &after)
std::unordered_map< std::string, bool > disabled_tests_
const std::string & GetCurrentTestName() const
absl::Status ReplayLastPlan()
std::vector< std::string > GetTestSuiteNames() const
absl::Status LoadRomForTesting(const std::string &filename)
virtual void DrawConfiguration()
virtual ~TestSuite()=default
virtual void SetEnabled(bool enabled)
virtual std::string GetName() const =0
virtual bool IsEnabled() const
virtual TestCategory GetCategory() const =0
virtual absl::Status RunTests(TestResults &results)=0
#define LOG_INFO(category, format,...)
Definition log.h:105
const char * TestStatusToString(TestStatus status)
const char * TestCategoryToString(TestCategory category)
ImVec4 GetTestStatusColor(TestStatus status)
std::chrono::time_point< std::chrono::steady_clock > timestamp
std::chrono::milliseconds duration
std::string error_message
std::chrono::time_point< std::chrono::steady_clock > timestamp
std::vector< TestResult > individual_results
std::chrono::milliseconds total_duration
void AddResult(const TestResult &result)
float GetPassRate() const