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"; }
50 return absl::OkStatus();
81 auto start_time = std::chrono::steady_clock::now();
83 result.
name =
"APU_Handshake_Protocol";
91 std::vector<uint8_t> rom_data(0x8000, 0);
94 auto& apu = snes.
apu();
103 for (
int i = 0; i < 10000; ++i) {
104 apu.RunCycles(i * 24);
105 if (tracker.GetPhase() ==
112 if (tracker.GetPhase() !=
114 throw std::runtime_error(
115 "APU did not signal ready ($BBAA). Current phase: " +
116 tracker.GetPhaseString());
120 snes.
Write(0x2140, 0xCC);
126 if (tracker.IsHandshakeComplete()) {
129 "APU handshake successful. Ready signal and CPU ack verified.";
131 throw std::runtime_error(
132 "CPU handshake ($CC) was not acknowledged by APU.");
135 }
catch (
const std::exception& e) {
138 std::string(
"APU handshake test exception: ") + e.what();
141 result.
duration = std::chrono::duration_cast<std::chrono::milliseconds>(
142 std::chrono::steady_clock::now() - start_time);
157 auto start_time = std::chrono::steady_clock::now();
159 result.
name =
"SPC700_Cycle_Accuracy";
167 callbacks.
read = [](uint16_t) {
170 callbacks.
write = [](uint16_t, uint8_t) {
172 callbacks.
idle = [](bool) {
185 throw std::runtime_error(
186 absl::StrFormat(
"NOP (0x00) should be 2 cycles, was %d",
199 result.
error_message =
"Basic SPC700 cycle counts appear correct.";
201 }
catch (
const std::exception& e) {
204 std::string(
"SPC700 cycle test exception: ") + e.what();
207 result.
duration = std::chrono::duration_cast<std::chrono::milliseconds>(
208 std::chrono::steady_clock::now() - start_time);
221 auto start_time = std::chrono::steady_clock::now();
223 result.
name =
"BreakpointManager_Core";
236 throw std::runtime_error(
"Failed to add breakpoint.");
242 throw std::runtime_error(
"Execution breakpoint was not hit.");
246 throw std::runtime_error(
"Breakpoint hit at incorrect address.");
252 throw std::runtime_error(
"Failed to remove breakpoint.");
256 throw std::runtime_error(
"Breakpoint was hit after being removed.");
261 "BreakpointManager add, hit, and remove tests passed.";
263 }
catch (
const std::exception& e) {
266 std::string(
"BreakpointManager test exception: ") + e.what();
269 result.
duration = std::chrono::duration_cast<std::chrono::milliseconds>(
270 std::chrono::steady_clock::now() - start_time);
282 auto start_time = std::chrono::steady_clock::now();
284 result.
name =
"WatchpointManager_Core";
294 wpm.
AddWatchpoint(0x7E0010, 0x7E0010,
false,
true,
true,
"Link HP");
300 throw std::runtime_error(
"Write watchpoint did not trigger a break.");
307 throw std::runtime_error(
308 "Read access incorrectly triggered a write-only watchpoint.");
313 if (history.size() != 1) {
314 throw std::runtime_error(
315 "Memory access was not logged to watchpoint history.");
317 if (history[0].new_value != 0x06 || !history[0].is_write) {
318 throw std::runtime_error(
"Logged access data is incorrect.");
323 "WatchpointManager logging and break-on-write tests passed.";
325 }
catch (
const std::exception& e) {
328 std::string(
"WatchpointManager test exception: ") + e.what();
331 result.
duration = std::chrono::duration_cast<std::chrono::milliseconds>(
332 std::chrono::steady_clock::now() - start_time);
344 auto start_time = std::chrono::steady_clock::now();
346 result.
name =
"Audio_Backend_Initialization";
357 if (!backend->Initialize(config)) {
358 throw std::runtime_error(
"Audio backend failed to initialize.");
360 if (!backend->IsInitialized()) {
361 throw std::runtime_error(
362 "IsInitialized() returned false after successful initialization.");
367 if (!backend->GetStatus().is_playing) {
368 throw std::runtime_error(
369 "Backend is not playing after Play() was called.");
373 if (backend->GetStatus().is_playing) {
374 throw std::runtime_error(
375 "Backend is still playing after Pause() was called.");
380 if (backend->IsInitialized()) {
381 throw std::runtime_error(
382 "IsInitialized() returned true after Shutdown().");
387 "Audio backend Initialize, Play, Pause, and Shutdown states work "
390 }
catch (
const std::exception& e) {
393 std::string(
"Audio backend test exception: ") + e.what();
396 result.
duration = std::chrono::duration_cast<std::chrono::milliseconds>(
397 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(const 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.
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)