twoapple-reboot/test/test_func.d

105 lines
2.6 KiB
D

module test.test_func;
import std.string;
import test.base, test.cpu, test.opcodes;
alias void delegate(ubyte, ref Expected, CpuInfo, const ref TestMemory, string)
testreport;
/*
* Runs one opcode. Calls expect for the expected values of the cpu
* registers and memory. Calls report with the expected and actual
* values.
*/
auto run_opcode_test(T)(testexpect expect, testreport report)
{
auto setup(ubyte opcode, CpuInfo cpu, Block[] data, OpInfo info,
string msg, TestSetup* next)
{
mixin testCallNext;
auto testcpu = makeCpu!T(cpu);
auto mem = TestMemory(data);
auto expected = Expected(cpu, mem);
expect(expected, info);
connectMem(testcpu, mem);
runOneOpcode(testcpu);
auto cpuResult = CpuInfo.fromCpu(testcpu);
report(opcode, expected, cpuResult, mem, T.stringof ~ " | " ~ msg);
callNext();
}
return TestSetup(&setup);
}
// Dummy function. Reports nothing.
auto report_none()
{
void report(ubyte opcode, ref Expected expected, CpuInfo cpu,
const ref TestMemory mem, string msg)
{
}
return &report;
}
// Prints the differences between expected and actual cpu/memory.
auto report_debug()
{
void report(ubyte opcode, ref Expected expected, CpuInfo cpu,
const ref TestMemory mem, string msg)
{
import std.stdio;
bool badCpu = (expected.cpu != cpu);
bool badMem = (expected.mem != mem);
if (badCpu || badMem)
writeln(format("[%0.2X] %s", opcode, msg));
if (badCpu)
{
writeln(" expect ", expected.cpu);
writeln(" actual ", cpu);
}
if (badMem)
{
foreach (h; MemDiff(expected.mem, mem))
{
writeln(format(" %0.4X | %s", h.base, formatMemory(h.a, 8)));
writeln(format(" | %s", formatMemory(h.b, 8)));
}
}
if (badCpu || badMem) throw new Exception("BAD");
}
return &report;
}
void test_one_opcode(T)(ubyte opcode, testreport report)
{
TestSetup setup_addr;
TestSetup setup_test;
testexpect expect;
mixin(getMemSetup!T());
auto setup = connect(setup_mask_flags(), setup_addr, setup_test);
auto run = connect(setup, run_opcode_test!T(expect, report));
run.run(opcode);
}
unittest
{
auto report = report_debug();
alias CPU!("65C02", false, false) T1;
foreach (opcode; 0..255)
test_one_opcode!T1(cast(ubyte)opcode, report);
alias CPU!("6502", false, false) T2;
foreach (opcode; 0..255)
test_one_opcode!T2(cast(ubyte)opcode, report);
}