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