yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
unit_test_suite.h
Go to the documentation of this file.
1#ifndef YAZE_APP_TEST_UNIT_TEST_SUITE_H
2#define YAZE_APP_TEST_UNIT_TEST_SUITE_H
3
4#include <chrono>
5#include <memory>
6
7#include "app/gfx/arena.h"
9
10#ifdef YAZE_ENABLE_GTEST
11#include <gtest/gtest.h>
12#endif
13
14// Note: ImGui Test Engine is handled through YAZE_ENABLE_IMGUI_TEST_ENGINE in
15// TestManager
16
17namespace yaze {
18namespace test {
19
20#ifdef YAZE_ENABLE_GTEST
21// Custom test listener to capture Google Test results
22class TestResultCapture : public ::testing::TestEventListener {
23 public:
24 explicit TestResultCapture(TestResults* results) : results_(results) {}
25
26 void OnTestStart(const ::testing::TestInfo& test_info) override {
27 current_test_start_ = std::chrono::steady_clock::now();
28 current_test_name_ =
29 std::string(test_info.test_case_name()) + "." + test_info.name();
30 }
31
32 void OnTestEnd(const ::testing::TestInfo& test_info) override {
33 auto end_time = std::chrono::steady_clock::now();
34 auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(
35 end_time - current_test_start_);
36
37 TestResult result;
38 result.name = test_info.name();
39 result.suite_name = test_info.test_case_name();
40 result.category = TestCategory::kUnit;
41 result.duration = duration;
42 result.timestamp = current_test_start_;
43
44 if (test_info.result()->Passed()) {
45 result.status = TestStatus::kPassed;
46 } else if (test_info.result()->Skipped()) {
47 result.status = TestStatus::kSkipped;
48 } else {
49 result.status = TestStatus::kFailed;
50
51 // Capture failure message
52 std::stringstream error_stream;
53 for (int i = 0; i < test_info.result()->total_part_count(); ++i) {
54 const auto& part = test_info.result()->GetTestPartResult(i);
55 if (part.failed()) {
56 error_stream << part.file_name() << ":" << part.line_number() << " "
57 << part.message() << "\n";
58 }
59 }
60 result.error_message = error_stream.str();
61 }
62
63 if (results_) {
64 results_->AddResult(result);
65 }
66 }
67
68 // Required overrides (can be empty)
69 void OnTestProgramStart(const ::testing::UnitTest&) override {}
70 void OnTestIterationStart(const ::testing::UnitTest&, int) override {}
71 void OnEnvironmentsSetUpStart(const ::testing::UnitTest&) override {}
72 void OnEnvironmentsSetUpEnd(const ::testing::UnitTest&) override {}
73 void OnTestCaseStart(const ::testing::TestCase&) override {}
74 void OnTestCaseEnd(const ::testing::TestCase&) override {}
75 void OnTestPartResult(
76 const ::testing::TestPartResult& test_part_result) override {
77 // Handle individual test part results (can be empty for our use case)
78 }
79 void OnEnvironmentsTearDownStart(const ::testing::UnitTest&) override {}
80 void OnEnvironmentsTearDownEnd(const ::testing::UnitTest&) override {}
81 void OnTestIterationEnd(const ::testing::UnitTest&, int) override {}
82 void OnTestProgramEnd(const ::testing::UnitTest&) override {}
83
84 private:
85 TestResults* results_;
86 std::chrono::time_point<std::chrono::steady_clock> current_test_start_;
87 std::string current_test_name_;
88};
89#endif // YAZE_ENABLE_GTEST
90
91// Unit test suite that runs Google Test cases
92class UnitTestSuite : public TestSuite {
93 public:
94 UnitTestSuite() = default;
95 ~UnitTestSuite() override = default;
96
97 std::string GetName() const override { return "Google Test Unit Tests"; }
98 TestCategory GetCategory() const override { return TestCategory::kUnit; }
99
100 absl::Status RunTests(TestResults& results) override {
101#ifdef YAZE_ENABLE_GTEST
102 // Set up Google Test to capture results
103 auto& listeners = ::testing::UnitTest::GetInstance()->listeners();
104
105 // Remove default console output (we'll capture it ourselves)
106 delete listeners.Release(listeners.default_result_printer());
107
108 // Add our custom listener
109 auto capture_listener = new TestResultCapture(&results);
110 listeners.Append(capture_listener);
111
112 // Configure test execution
113 int argc = 1;
114 const char* argv[] = {"yaze_tests"};
115 ::testing::InitGoogleTest(&argc, const_cast<char**>(argv));
116
117 // Run the tests
118 int result = RUN_ALL_TESTS();
119
120 // Clean up
121 listeners.Release(capture_listener);
122 delete capture_listener;
123
124 return result == 0 ? absl::OkStatus()
125 : absl::InternalError("Some unit tests failed");
126#else
127 // Google Test not available - add a placeholder test
128 TestResult result;
129 result.name = "Placeholder Test";
130 result.suite_name = GetName();
131 result.category = GetCategory();
132 result.status = TestStatus::kSkipped;
133 result.error_message = "Google Test not available in this build";
134 result.duration = std::chrono::milliseconds{0};
135 result.timestamp = std::chrono::steady_clock::now();
136 results.AddResult(result);
137
138 return absl::OkStatus();
139#endif
140 }
141
142 void DrawConfiguration() override {
143 ImGui::Text("Google Test Configuration");
144 ImGui::Checkbox("Run disabled tests", &run_disabled_tests_);
145 ImGui::Checkbox("Shuffle tests", &shuffle_tests_);
146 ImGui::InputInt("Repeat count", &repeat_count_);
147 if (repeat_count_ < 1)
148 repeat_count_ = 1;
149
150 ImGui::InputText("Test filter", test_filter_, sizeof(test_filter_));
151 ImGui::SameLine();
152 if (ImGui::Button("Clear")) {
153 test_filter_[0] = '\0';
154 }
155 }
156
157 private:
159 bool shuffle_tests_ = false;
161 char test_filter_[256] = "";
162};
163
164// Arena-specific test suite for memory management
165class ArenaTestSuite : public TestSuite {
166 public:
167 ArenaTestSuite() = default;
168 ~ArenaTestSuite() override = default;
169
170 std::string GetName() const override { return "Arena Memory Tests"; }
171 TestCategory GetCategory() const override { return TestCategory::kMemory; }
172
173 absl::Status RunTests(TestResults& results) override {
174 // Test Arena resource management
175 RunArenaAllocationTest(results);
176 RunArenaCleanupTest(results);
178
179 return absl::OkStatus();
180 }
181
182 void DrawConfiguration() override {
183 ImGui::Text("Arena Test Configuration");
184 ImGui::InputInt("Test allocations", &test_allocation_count_);
185 ImGui::InputInt("Test texture size", &test_texture_size_);
186 ImGui::Checkbox("Test cleanup order", &test_cleanup_order_);
187 }
188
189 private:
191 auto start_time = std::chrono::steady_clock::now();
192
193 TestResult result;
194 result.name = "Arena_Allocation_Test";
195 result.suite_name = GetName();
196 result.category = GetCategory();
197 result.timestamp = start_time;
198
199 try {
200 auto& arena = gfx::Arena::Get();
201 size_t initial_texture_count = arena.GetTextureCount();
202 size_t initial_surface_count = arena.GetSurfaceCount();
203
204 // Test texture allocation (would need a valid renderer)
205 // This is a simplified test - in real implementation we'd mock the
206 // renderer
207
208 size_t final_texture_count = arena.GetTextureCount();
209 size_t final_surface_count = arena.GetSurfaceCount();
210
211 // For now, just verify the Arena can be accessed
213
214 } catch (const std::exception& e) {
216 result.error_message =
217 "Arena allocation test failed: " + std::string(e.what());
218 }
219
220 auto end_time = std::chrono::steady_clock::now();
221 result.duration = std::chrono::duration_cast<std::chrono::milliseconds>(
222 end_time - start_time);
223
224 results.AddResult(result);
225 }
226
228 auto start_time = std::chrono::steady_clock::now();
229
230 TestResult result;
231 result.name = "Arena_Cleanup_Test";
232 result.suite_name = GetName();
233 result.category = GetCategory();
234 result.timestamp = start_time;
235
236 try {
237 auto& arena = gfx::Arena::Get();
238
239 // Test that shutdown doesn't crash
240 // Note: We can't actually call Shutdown() here as it would affect the
241 // running app This test verifies the methods exist and are callable
242 size_t texture_count = arena.GetTextureCount();
243 size_t surface_count = arena.GetSurfaceCount();
244
246
247 } catch (const std::exception& e) {
249 result.error_message =
250 "Arena cleanup test failed: " + std::string(e.what());
251 }
252
253 auto end_time = std::chrono::steady_clock::now();
254 result.duration = std::chrono::duration_cast<std::chrono::milliseconds>(
255 end_time - start_time);
256
257 results.AddResult(result);
258 }
259
261 auto start_time = std::chrono::steady_clock::now();
262
263 TestResult result;
264 result.name = "Arena_Resource_Tracking_Test";
265 result.suite_name = GetName();
266 result.category = GetCategory();
267 result.timestamp = start_time;
268
269 try {
270 auto& arena = gfx::Arena::Get();
271
272 // Test resource tracking methods
273 size_t texture_count = arena.GetTextureCount();
274 size_t surface_count = arena.GetSurfaceCount();
275
276 // Verify tracking methods work
277 if (texture_count >= 0 && surface_count >= 0) {
279 } else {
281 result.error_message = "Invalid resource counts returned";
282 }
283
284 } catch (const std::exception& e) {
286 result.error_message =
287 "Resource tracking test failed: " + std::string(e.what());
288 }
289
290 auto end_time = std::chrono::steady_clock::now();
291 result.duration = std::chrono::duration_cast<std::chrono::milliseconds>(
292 end_time - start_time);
293
294 results.AddResult(result);
295 }
296
300};
301
302} // namespace test
303} // namespace yaze
304
305#endif // YAZE_APP_TEST_UNIT_TEST_SUITE_H
static Arena & Get()
Definition arena.cc:19
void DrawConfiguration() override
void RunArenaCleanupTest(TestResults &results)
~ArenaTestSuite() override=default
TestCategory GetCategory() const override
absl::Status RunTests(TestResults &results) override
void RunArenaResourceTrackingTest(TestResults &results)
std::string GetName() const override
void RunArenaAllocationTest(TestResults &results)
absl::Status RunTests(TestResults &results) override
TestCategory GetCategory() const override
std::string GetName() const override
void DrawConfiguration() override
~UnitTestSuite() override=default
std::chrono::milliseconds duration
std::string error_message
std::chrono::time_point< std::chrono::steady_clock > timestamp
void AddResult(const TestResult &result)