yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
test_utils.h
Go to the documentation of this file.
1#ifndef YAZE_TEST_TEST_UTILS_H
2#define YAZE_TEST_TEST_UTILS_H
3
4#ifndef IMGUI_DEFINE_MATH_OPERATORS
5#define IMGUI_DEFINE_MATH_OPERATORS
6#endif
7
8#include <string>
9#include <vector>
10#include <filesystem>
11#include <fstream>
12#include <iostream>
13
14#include <gtest/gtest.h>
15#include <gmock/gmock.h>
16
17#include "absl/strings/str_format.h"
18#include "imgui_test_engine/imgui_te_context.h"
19#include "app/rom.h"
20
21namespace yaze {
22namespace test {
23
28 public:
29 class BoundRomTest;
30
35 static bool IsRomTestingEnabled() {
36#ifdef YAZE_ENABLE_ROM_TESTS
37 return std::filesystem::exists(GetTestRomPath());
38#else
39 return false;
40#endif
41 }
42
47 static std::string GetTestRomPath() {
48#ifdef YAZE_TEST_ROM_PATH
49 return YAZE_TEST_ROM_PATH;
50#else
51 return "zelda3.sfc";
52#endif
53 }
54
59 static std::vector<uint8_t> LoadTestRom() {
60 if (!IsRomTestingEnabled()) {
61 return {};
62 }
63
64 std::string rom_path = GetTestRomPath();
65 std::ifstream file(rom_path, std::ios::binary);
66 if (!file) {
67 std::cerr << "Failed to open test ROM: " << rom_path << std::endl;
68 return {};
69 }
70
71 // Get file size
72 file.seekg(0, std::ios::end);
73 size_t file_size = file.tellg();
74 file.seekg(0, std::ios::beg);
75
76 // Read file
77 std::vector<uint8_t> rom_data(file_size);
78 file.read(reinterpret_cast<char*>(rom_data.data()), file_size);
79
80 if (!file) {
81 std::cerr << "Failed to read test ROM: " << rom_path << std::endl;
82 return {};
83 }
84
85 return rom_data;
86 }
87
93 static std::vector<uint8_t> CreateMinimalTestRom(size_t size = 1024 * 1024) {
94 std::vector<uint8_t> rom_data(size, 0);
95
96 // Add minimal SNES header at 0x7FC0 (LoROM)
97 const size_t header_offset = 0x7FC0;
98 if (size > header_offset + 32) {
99 // ROM title
100 std::string title = "YAZE TEST ROM ";
101 std::copy(title.begin(), title.end(), rom_data.begin() + header_offset);
102
103 // Map mode (LoROM)
104 rom_data[header_offset + 21] = 0x20;
105
106 // ROM size (1MB)
107 rom_data[header_offset + 23] = 0x0A;
108
109 // Calculate and set checksum
110 uint16_t checksum = 0;
111 for (size_t i = 0; i < size; ++i) {
112 if (i < header_offset + 28 || i > header_offset + 31) {
113 checksum += rom_data[i];
114 }
115 }
116
117 uint16_t checksum_complement = checksum ^ 0xFFFF;
118 rom_data[header_offset + 28] = checksum_complement & 0xFF;
119 rom_data[header_offset + 29] = (checksum_complement >> 8) & 0xFF;
120 rom_data[header_offset + 30] = checksum & 0xFF;
121 rom_data[header_offset + 31] = (checksum >> 8) & 0xFF;
122 }
123
124 return rom_data;
125 }
126
131 static void SkipIfRomTestingDisabled(const std::string& test_name) {
132 if (!IsRomTestingEnabled()) {
133 GTEST_SKIP() << "ROM testing disabled or ROM file not found. "
134 << "Test: " << test_name << " requires: " << GetTestRomPath();
135 }
136 }
137};
138
139class TestRomManager::BoundRomTest : public ::testing::Test {
140 protected:
141 void SetUp() override {
142 rom_instance_ = std::make_unique<Rom>();
143 }
144
145 void TearDown() override {
146 rom_instance_.reset();
147 rom_loaded_ = false;
148 }
149
150 Rom* rom() { EnsureRomLoaded(); return rom_instance_.get(); }
151 const Rom* rom() const { return rom_instance_.get(); }
152
153 std::string GetBoundRomPath() const { return TestRomManager::GetTestRomPath(); }
154
155 private:
156 std::unique_ptr<Rom> rom_instance_;
157 bool rom_loaded_ = false;
158
160 if (rom_loaded_) {
161 return;
162 }
163 const std::string rom_path = TestRomManager::GetTestRomPath();
164 ASSERT_TRUE(rom_instance_->LoadFromFile(rom_path).ok())
165 << "Failed to load test ROM from " << rom_path;
166 rom_loaded_ = true;
167 }
168};
169
173#define YAZE_ROM_TEST(test_case_name, test_name) \
174 TEST(test_case_name, test_name) { \
175 yaze::test::TestRomManager::SkipIfRomTestingDisabled(#test_case_name "." #test_name); \
176 YAZE_ROM_TEST_BODY_##test_case_name##_##test_name(); \
177 } \
178 void YAZE_ROM_TEST_BODY_##test_case_name##_##test_name()
179
183class RomDependentTest : public ::testing::Test {
184 protected:
185 void SetUp() override {
188 ASSERT_FALSE(test_rom_.empty()) << "Failed to load test ROM";
189 }
190
191 std::vector<uint8_t> test_rom_;
192};
193
194namespace gui {
195
196void LoadRomInTest(ImGuiTestContext* ctx, const std::string& rom_path);
197void OpenEditorInTest(ImGuiTestContext* ctx, const std::string& editor_name);
198
199} // namespace gui
200
201} // namespace test
202} // namespace yaze
203
204#endif // YAZE_TEST_TEST_UTILS_H
The Rom class is used to load, save, and modify Rom data.
Definition rom.h:71
Test fixture for ROM-dependent tests.
Definition test_utils.h:183
std::vector< uint8_t > test_rom_
Definition test_utils.h:191
Utility class for handling test ROM files.
Definition test_utils.h:27
static std::vector< uint8_t > CreateMinimalTestRom(size_t size=1024 *1024)
Create a minimal test ROM for unit testing.
Definition test_utils.h:93
static std::string GetTestRomPath()
Get the path to the test ROM file.
Definition test_utils.h:47
static void SkipIfRomTestingDisabled(const std::string &test_name)
Skip test if ROM testing is not enabled.
Definition test_utils.h:131
static bool IsRomTestingEnabled()
Check if ROM testing is enabled and ROM file exists.
Definition test_utils.h:35
static std::vector< uint8_t > LoadTestRom()
Load the test ROM file into memory.
Definition test_utils.h:59
void LoadRomInTest(ImGuiTestContext *ctx, const std::string &rom_path)
Definition test_utils.cc:8
void OpenEditorInTest(ImGuiTestContext *ctx, const std::string &editor_name)
Definition test_utils.cc:13
Main namespace for the application.