1#ifndef YAZE_APP_TEST_EMULATOR_TEST_SUITE_H
2#define YAZE_APP_TEST_EMULATOR_TEST_SUITE_H
35 std::string
GetName()
const override {
return "Emulator Core Tests"; }
45 return absl::OkStatus();
75 auto start_time = std::chrono::steady_clock::now();
77 result.
name =
"APU_Handshake_Protocol";
85 std::vector<uint8_t> rom_data(0x8000, 0);
88 auto& apu = snes.
apu();
97 for (
int i = 0; i < 10000; ++i) {
98 apu.RunCycles(i * 24);
106 throw std::runtime_error(
"APU did not signal ready ($BBAA). Current phase: " + tracker.GetPhaseString());
110 snes.
Write(0x2140, 0xCC);
116 if (tracker.IsHandshakeComplete()) {
118 result.
error_message =
"APU handshake successful. Ready signal and CPU ack verified.";
120 throw std::runtime_error(
"CPU handshake ($CC) was not acknowledged by APU.");
123 }
catch (
const std::exception& e) {
125 result.
error_message = std::string(
"APU handshake test exception: ") + e.what();
128 result.
duration = std::chrono::duration_cast<std::chrono::milliseconds>(
129 std::chrono::steady_clock::now() - start_time);
143 auto start_time = std::chrono::steady_clock::now();
145 result.
name =
"SPC700_Cycle_Accuracy";
153 callbacks.
read = [](uint16_t) {
return 0; };
154 callbacks.
write = [](uint16_t, uint8_t) {};
155 callbacks.
idle = [](bool) {};
167 throw std::runtime_error(absl::StrFormat(
"NOP (0x00) should be 2 cycles, was %d", spc.
GetLastOpcodeCycles()));
179 result.
error_message =
"Basic SPC700 cycle counts appear correct.";
181 }
catch (
const std::exception& e) {
183 result.
error_message = std::string(
"SPC700 cycle test exception: ") + e.what();
186 result.
duration = std::chrono::duration_cast<std::chrono::milliseconds>(
187 std::chrono::steady_clock::now() - start_time);
199 auto start_time = std::chrono::steady_clock::now();
201 result.
name =
"BreakpointManager_Core";
212 throw std::runtime_error(
"Failed to add breakpoint.");
217 throw std::runtime_error(
"Execution breakpoint was not hit.");
220 throw std::runtime_error(
"Breakpoint hit at incorrect address.");
226 throw std::runtime_error(
"Failed to remove breakpoint.");
229 throw std::runtime_error(
"Breakpoint was hit after being removed.");
233 result.
error_message =
"BreakpointManager add, hit, and remove tests passed.";
235 }
catch (
const std::exception& e) {
237 result.
error_message = std::string(
"BreakpointManager test exception: ") + e.what();
240 result.
duration = std::chrono::duration_cast<std::chrono::milliseconds>(
241 std::chrono::steady_clock::now() - start_time);
253 auto start_time = std::chrono::steady_clock::now();
255 result.
name =
"WatchpointManager_Core";
264 uint32_t wp_id = wpm.
AddWatchpoint(0x7E0010, 0x7E0010,
false,
true,
true,
"Link HP");
267 bool should_break = wpm.
OnMemoryAccess(0x8000, 0x7E0010,
true, 0x05, 0x06, 12345);
269 throw std::runtime_error(
"Write watchpoint did not trigger a break.");
273 should_break = wpm.
OnMemoryAccess(0x8001, 0x7E0010,
false, 0x06, 0x06, 12350);
275 throw std::runtime_error(
"Read access incorrectly triggered a write-only watchpoint.");
280 if (history.size() != 1) {
281 throw std::runtime_error(
"Memory access was not logged to watchpoint history.");
283 if (history[0].new_value != 0x06 || !history[0].is_write) {
284 throw std::runtime_error(
"Logged access data is incorrect.");
288 result.
error_message =
"WatchpointManager logging and break-on-write tests passed.";
290 }
catch (
const std::exception& e) {
292 result.
error_message = std::string(
"WatchpointManager test exception: ") + e.what();
295 result.
duration = std::chrono::duration_cast<std::chrono::milliseconds>(
296 std::chrono::steady_clock::now() - start_time);
308 auto start_time = std::chrono::steady_clock::now();
310 result.
name =
"Audio_Backend_Initialization";
320 if (!backend->Initialize(config)) {
321 throw std::runtime_error(
"Audio backend failed to initialize.");
323 if (!backend->IsInitialized()) {
324 throw std::runtime_error(
"IsInitialized() returned false after successful initialization.");
329 if (!backend->GetStatus().is_playing) {
330 throw std::runtime_error(
"Backend is not playing after Play() was called.");
334 if (backend->GetStatus().is_playing) {
335 throw std::runtime_error(
"Backend is still playing after Pause() was called.");
340 if (backend->IsInitialized()) {
341 throw std::runtime_error(
"IsInitialized() returned true after Shutdown().");
345 result.
error_message =
"Audio backend Initialize, Play, Pause, and Shutdown states work correctly.";
347 }
catch (
const std::exception& e) {
349 result.
error_message = std::string(
"Audio backend test exception: ") + e.what();
352 result.
duration = std::chrono::duration_cast<std::chrono::milliseconds>(
353 std::chrono::steady_clock::now() - start_time);
Manages CPU and SPC700 breakpoints for debugging.
bool ShouldBreakOnExecute(uint32_t pc, CpuType cpu)
Check if execution should break at this address.
void RemoveBreakpoint(uint32_t id)
Remove a breakpoint by ID.
std::vector< Breakpoint > GetAllBreakpoints() const
Get all breakpoints.
uint32_t AddBreakpoint(uint32_t address, Type type, CpuType cpu, const std::string &condition="", const std::string &description="")
Add a new breakpoint.
auto mutable_cycles() -> uint64_t &
auto apu_handshake_tracker() -> debug::ApuHandshakeTracker &
void Write(uint32_t adr, uint8_t val)
void Init(std::vector< uint8_t > &rom_data)
The Spc700 class represents the SPC700 processor.
void Reset(bool hard=false)
int GetLastOpcodeCycles() const
Manages memory watchpoints for debugging.
uint32_t AddWatchpoint(uint32_t start_address, uint32_t end_address, bool track_reads, bool track_writes, bool break_on_access=false, const std::string &description="")
Add a memory watchpoint.
std::vector< AccessLog > GetHistory(uint32_t address, int max_entries=100) const
Get access history for a specific address.
bool OnMemoryAccess(uint32_t pc, uint32_t address, bool is_write, uint8_t old_value, uint8_t new_value, uint64_t cycle_count)
Check if memory access should break/log.
static std::unique_ptr< IAudioBackend > Create(BackendType type)
Test suite for core emulator components.
absl::Status RunTests(TestResults &results) override
void RunBreakpointManagerTest(TestResults &results)
Tests the core functionality of the BreakpointManager.
void RunApuHandshakeTest(TestResults &results)
Verifies the CPU-APU handshake protocol.
void DrawConfiguration() override
bool test_breakpoint_manager_
bool test_watchpoint_manager_
~EmulatorTestSuite() override=default
std::string GetName() const override
void RunAudioBackendTest(TestResults &results)
Tests the audio backend abstraction layer.
TestCategory GetCategory() const override
void RunWatchpointManagerTest(TestResults &results)
Tests the memory WatchpointManager.
EmulatorTestSuite()=default
void RunSpc700CycleAccuracyTest(TestResults &results)
Validates the cycle counting for SPC700 opcodes.
Main namespace for the application.
std::function< void(uint16_t, uint8_t)> write
std::function< void(bool)> idle
std::function< uint8_t(uint16_t)> read
std::chrono::milliseconds duration
std::string error_message
std::chrono::time_point< std::chrono::steady_clock > timestamp
void AddResult(const TestResult &result)