yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
e2e_test_suite.h
Go to the documentation of this file.
1#ifndef YAZE_APP_TEST_E2E_TEST_SUITE_H
2#define YAZE_APP_TEST_E2E_TEST_SUITE_H
3
4#include <chrono>
5#include <filesystem>
6
7#include "absl/strings/str_format.h"
9#include "app/rom.h"
10#include "app/transaction.h"
11#include "app/gui/icons.h"
12
13namespace yaze {
14namespace test {
15
25class E2ETestSuite : public TestSuite {
26 public:
27 E2ETestSuite() = default;
28 ~E2ETestSuite() override = default;
29
30 std::string GetName() const override { return "End-to-End ROM Tests"; }
32
33 absl::Status RunTests(TestResults& results) override {
34 Rom* current_rom = TestManager::Get().GetCurrentRom();
35
36 // Check ROM availability
37 if (!current_rom || !current_rom->is_loaded()) {
38 AddSkippedTest(results, "ROM_Availability_Check", "No ROM loaded");
39 return absl::OkStatus();
40 }
41
42 // Run E2E tests
44 RunRomLoadSaveTest(results, current_rom);
45 }
46
48 RunDataIntegrityTest(results, current_rom);
49 }
50
52 RunTransactionSystemTest(results, current_rom);
53 }
54
56 RunLargeScaleEditingTest(results, current_rom);
57 }
58
60 RunCorruptionDetectionTest(results, current_rom);
61 }
62
63 return absl::OkStatus();
64 }
65
66 void DrawConfiguration() override {
67 Rom* current_rom = TestManager::Get().GetCurrentRom();
68
69 ImGui::Text("%s E2E Test Configuration", ICON_MD_VERIFIED_USER);
70
71 if (current_rom && current_rom->is_loaded()) {
72 ImGui::TextColored(ImVec4(0.0F, 1.0F, 0.0F, 1.0F),
73 "%s Current ROM: %s", ICON_MD_CHECK_CIRCLE, current_rom->title().c_str());
74 ImGui::Text("Size: %.2F MB", current_rom->size() / 1048576.0F);
75 } else {
76 ImGui::TextColored(ImVec4(1.0F, 0.5F, 0.0F, 1.0F),
77 "%s No ROM currently loaded", ICON_MD_WARNING);
78 }
79
80 ImGui::Separator();
81 ImGui::Checkbox("Test ROM load/save", &test_rom_load_save_);
82 ImGui::Checkbox("Test data integrity", &test_data_integrity_);
83 ImGui::Checkbox("Test transaction system", &test_transaction_system_);
84 ImGui::Checkbox("Test large-scale editing", &test_large_scale_editing_);
85 ImGui::Checkbox("Test corruption detection", &test_corruption_detection_);
86
88 ImGui::Indent();
89 ImGui::InputInt("Number of edits", &num_edits_);
90 if (num_edits_ < 1) num_edits_ = 1;
91 if (num_edits_ > 100) num_edits_ = 100;
92 ImGui::Unindent();
93 }
94 }
95
96 private:
97 void AddSkippedTest(TestResults& results, const std::string& test_name, const std::string& reason) {
98 TestResult result;
99 result.name = test_name;
100 result.suite_name = GetName();
101 result.category = GetCategory();
103 result.error_message = reason;
104 result.duration = std::chrono::milliseconds{0};
105 result.timestamp = std::chrono::steady_clock::now();
106 results.AddResult(result);
107 }
108
109 void RunRomLoadSaveTest(TestResults& results, Rom* rom) {
110 auto start_time = std::chrono::steady_clock::now();
111
112 TestResult result;
113 result.name = "ROM_Load_Save_Test";
114 result.suite_name = GetName();
115 result.category = GetCategory();
116 result.timestamp = start_time;
117
118 try {
119 auto& test_manager = TestManager::Get();
120
121 auto test_status = test_manager.TestRomWithCopy(rom, [&](Rom* test_rom) -> absl::Status {
122 // Test basic ROM operations
123 if (test_rom->size() != rom->size()) {
124 return absl::InternalError("ROM copy size mismatch");
125 }
126
127 // Test save and reload
128 std::string test_filename = test_manager.GenerateTestRomFilename("e2e_test");
129 auto save_status = test_rom->SaveToFile(Rom::SaveSettings{.filename = test_filename});
130 if (!save_status.ok()) {
131 return save_status;
132 }
133
134 // Clean up test file
135 std::filesystem::remove(test_filename);
136
137 return absl::OkStatus();
138 });
139
140 if (test_status.ok()) {
142 result.error_message = "ROM load/save test completed successfully";
143 } else {
145 result.error_message = "ROM load/save test failed: " + test_status.ToString();
146 }
147
148 } catch (const std::exception& e) {
150 result.error_message = "ROM load/save test exception: " + std::string(e.what());
151 }
152
153 auto end_time = std::chrono::steady_clock::now();
154 result.duration = std::chrono::duration_cast<std::chrono::milliseconds>(
155 end_time - start_time);
156
157 results.AddResult(result);
158 }
159
160 void RunDataIntegrityTest(TestResults& results, Rom* rom) {
161 auto start_time = std::chrono::steady_clock::now();
162
163 TestResult result;
164 result.name = "Data_Integrity_Test";
165 result.suite_name = GetName();
166 result.category = GetCategory();
167 result.timestamp = start_time;
168
169 try {
170 auto& test_manager = TestManager::Get();
171
172 auto test_status = test_manager.TestRomWithCopy(rom, [&](Rom* test_rom) -> absl::Status {
173 // Test data integrity by comparing key areas
174 std::vector<uint32_t> test_addresses = {0x7FC0, 0x8000, 0x10000, 0x20000};
175
176 for (uint32_t addr : test_addresses) {
177 auto original_byte = rom->ReadByte(addr);
178 auto copy_byte = test_rom->ReadByte(addr);
179
180 if (!original_byte.ok() || !copy_byte.ok()) {
181 return absl::InternalError("Failed to read ROM data for comparison");
182 }
183
184 if (*original_byte != *copy_byte) {
185 return absl::InternalError(absl::StrFormat(
186 "Data integrity check failed at address 0x%X: original=0x%02X, copy=0x%02X",
187 addr, *original_byte, *copy_byte));
188 }
189 }
190
191 return absl::OkStatus();
192 });
193
194 if (test_status.ok()) {
196 result.error_message = "Data integrity test passed - all checked addresses match";
197 } else {
199 result.error_message = "Data integrity test failed: " + test_status.ToString();
200 }
201
202 } catch (const std::exception& e) {
204 result.error_message = "Data integrity test exception: " + std::string(e.what());
205 }
206
207 auto end_time = std::chrono::steady_clock::now();
208 result.duration = std::chrono::duration_cast<std::chrono::milliseconds>(
209 end_time - start_time);
210
211 results.AddResult(result);
212 }
213
215 auto start_time = std::chrono::steady_clock::now();
216
217 TestResult result;
218 result.name = "Transaction_System_Test";
219 result.suite_name = GetName();
220 result.category = GetCategory();
221 result.timestamp = start_time;
222
223 try {
224 auto& test_manager = TestManager::Get();
225
226 auto test_status = test_manager.TestRomWithCopy(rom, [&](Rom* test_rom) -> absl::Status {
227 // Test transaction system
228 Transaction transaction(*test_rom);
229
230 // Store original values
231 auto original_byte1 = test_rom->ReadByte(0x1000);
232 auto original_byte2 = test_rom->ReadByte(0x2000);
233 auto original_word = test_rom->ReadWord(0x3000);
234
235 if (!original_byte1.ok() || !original_byte2.ok() || !original_word.ok()) {
236 return absl::InternalError("Failed to read original ROM data");
237 }
238
239 // Make changes in transaction
240 transaction.WriteByte(0x1000, 0xAA)
241 .WriteByte(0x2000, 0xBB)
242 .WriteWord(0x3000, 0xCCDD);
243
244 // Commit transaction
245 RETURN_IF_ERROR(transaction.Commit());
246
247 // Verify changes
248 auto new_byte1 = test_rom->ReadByte(0x1000);
249 auto new_byte2 = test_rom->ReadByte(0x2000);
250 auto new_word = test_rom->ReadWord(0x3000);
251
252 if (!new_byte1.ok() || !new_byte2.ok() || !new_word.ok()) {
253 return absl::InternalError("Failed to read modified ROM data");
254 }
255
256 if (*new_byte1 != 0xAA || *new_byte2 != 0xBB || *new_word != 0xCCDD) {
257 return absl::InternalError("Transaction changes not applied correctly");
258 }
259
260 return absl::OkStatus();
261 });
262
263 if (test_status.ok()) {
265 result.error_message = "Transaction system test completed successfully";
266 } else {
268 result.error_message = "Transaction system test failed: " + test_status.ToString();
269 }
270
271 } catch (const std::exception& e) {
273 result.error_message = "Transaction system test exception: " + std::string(e.what());
274 }
275
276 auto end_time = std::chrono::steady_clock::now();
277 result.duration = std::chrono::duration_cast<std::chrono::milliseconds>(
278 end_time - start_time);
279
280 results.AddResult(result);
281 }
282
284 auto start_time = std::chrono::steady_clock::now();
285
286 TestResult result;
287 result.name = "Large_Scale_Editing_Test";
288 result.suite_name = GetName();
289 result.category = GetCategory();
290 result.timestamp = start_time;
291
292 try {
293 auto& test_manager = TestManager::Get();
294
295 auto test_status = test_manager.TestRomWithCopy(rom, [&](Rom* test_rom) -> absl::Status {
296 // Test large-scale editing
297 for (int i = 0; i < num_edits_; i++) {
298 uint32_t addr = 0x1000 + (i * 4);
299 uint8_t value = i % 256;
300
301 RETURN_IF_ERROR(test_rom->WriteByte(addr, value));
302 }
303
304 // Verify all changes
305 for (int i = 0; i < num_edits_; i++) {
306 uint32_t addr = 0x1000 + (i * 4);
307 uint8_t expected_value = i % 256;
308
309 auto actual_value = test_rom->ReadByte(addr);
310 if (!actual_value.ok()) {
311 return absl::InternalError(absl::StrFormat("Failed to read address 0x%X", addr));
312 }
313
314 if (*actual_value != expected_value) {
315 return absl::InternalError(absl::StrFormat(
316 "Value mismatch at 0x%X: expected=0x%02X, actual=0x%02X",
317 addr, expected_value, *actual_value));
318 }
319 }
320
321 return absl::OkStatus();
322 });
323
324 if (test_status.ok()) {
326 result.error_message = absl::StrFormat("Large-scale editing test passed: %d edits", num_edits_);
327 } else {
329 result.error_message = "Large-scale editing test failed: " + test_status.ToString();
330 }
331
332 } catch (const std::exception& e) {
334 result.error_message = "Large-scale editing test exception: " + std::string(e.what());
335 }
336
337 auto end_time = std::chrono::steady_clock::now();
338 result.duration = std::chrono::duration_cast<std::chrono::milliseconds>(
339 end_time - start_time);
340
341 results.AddResult(result);
342 }
343
345 auto start_time = std::chrono::steady_clock::now();
346
347 TestResult result;
348 result.name = "Corruption_Detection_Test";
349 result.suite_name = GetName();
350 result.category = GetCategory();
351 result.timestamp = start_time;
352
353 try {
354 auto& test_manager = TestManager::Get();
355
356 auto test_status = test_manager.TestRomWithCopy(rom, [&](Rom* test_rom) -> absl::Status {
357 // Intentionally corrupt some data
358 RETURN_IF_ERROR(test_rom->WriteByte(0x1000, 0xFF));
359 RETURN_IF_ERROR(test_rom->WriteByte(0x2000, 0xAA));
360
361 // Verify corruption is detected
362 auto corrupted_byte1 = test_rom->ReadByte(0x1000);
363 auto corrupted_byte2 = test_rom->ReadByte(0x2000);
364
365 if (!corrupted_byte1.ok() || !corrupted_byte2.ok()) {
366 return absl::InternalError("Failed to read corrupted data");
367 }
368
369 if (*corrupted_byte1 != 0xFF || *corrupted_byte2 != 0xAA) {
370 return absl::InternalError("Corruption not applied correctly");
371 }
372
373 // Verify original data is different
374 auto original_byte1 = rom->ReadByte(0x1000);
375 auto original_byte2 = rom->ReadByte(0x2000);
376
377 if (!original_byte1.ok() || !original_byte2.ok()) {
378 return absl::InternalError("Failed to read original data for comparison");
379 }
380
381 if (*corrupted_byte1 == *original_byte1 || *corrupted_byte2 == *original_byte2) {
382 return absl::InternalError("Corruption detection test failed - data not actually corrupted");
383 }
384
385 return absl::OkStatus();
386 });
387
388 if (test_status.ok()) {
390 result.error_message = "Corruption detection test passed - corruption successfully applied and detected";
391 } else {
393 result.error_message = "Corruption detection test failed: " + test_status.ToString();
394 }
395
396 } catch (const std::exception& e) {
398 result.error_message = "Corruption detection test exception: " + std::string(e.what());
399 }
400
401 auto end_time = std::chrono::steady_clock::now();
402 result.duration = std::chrono::duration_cast<std::chrono::milliseconds>(
403 end_time - start_time);
404
405 results.AddResult(result);
406 }
407
408 // Configuration
414 int num_edits_ = 10;
415};
416
417} // namespace test
418} // namespace yaze
419
420#endif // YAZE_APP_TEST_E2E_TEST_SUITE_H
The Rom class is used to load, save, and modify Rom data.
Definition rom.h:71
absl::Status WriteByte(int addr, uint8_t value)
Definition rom.cc:725
absl::StatusOr< uint16_t > ReadWord(int offset)
Definition rom.cc:665
absl::Status SaveToFile(const SaveSettings &settings)
Definition rom.cc:536
auto size() const
Definition rom.h:202
absl::StatusOr< uint8_t > ReadByte(int offset)
Definition rom.cc:658
bool is_loaded() const
Definition rom.h:197
auto title() const
Definition rom.h:201
Transaction & WriteWord(int address, uint16_t value)
Definition transaction.h:39
absl::Status Commit()
Definition transaction.h:96
Transaction & WriteByte(int address, uint8_t value)
Definition transaction.h:25
End-to-End test suite for comprehensive ROM testing.
TestCategory GetCategory() const override
void DrawConfiguration() override
void RunDataIntegrityTest(TestResults &results, Rom *rom)
void RunLargeScaleEditingTest(TestResults &results, Rom *rom)
~E2ETestSuite() override=default
std::string GetName() const override
void RunCorruptionDetectionTest(TestResults &results, Rom *rom)
void RunTransactionSystemTest(TestResults &results, Rom *rom)
absl::Status RunTests(TestResults &results) override
void RunRomLoadSaveTest(TestResults &results, Rom *rom)
void AddSkippedTest(TestResults &results, const std::string &test_name, const std::string &reason)
Rom * GetCurrentRom() const
static TestManager & Get()
#define ICON_MD_WARNING
Definition icons.h:2121
#define ICON_MD_CHECK_CIRCLE
Definition icons.h:398
#define ICON_MD_VERIFIED_USER
Definition icons.h:2054
#define RETURN_IF_ERROR(expression)
Definition macro.h:53
Main namespace for the application.
std::string filename
Definition rom.h:77
std::chrono::milliseconds duration
std::string error_message
std::chrono::time_point< std::chrono::steady_clock > timestamp
void AddResult(const TestResult &result)