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