74 lines
2.8 KiB
Rust
74 lines
2.8 KiB
Rust
use prometeu_core::hardware::HardwareBridge;
|
|
use prometeu_core::virtual_machine::HostReturn;
|
|
use prometeu_core::virtual_machine::NativeInterface;
|
|
use prometeu_core::virtual_machine::Value;
|
|
use prometeu_core::virtual_machine::{LogicalFrameEndingReason, VirtualMachine};
|
|
use prometeu_core::Hardware;
|
|
use std::fs;
|
|
use std::path::Path;
|
|
|
|
struct MockNative;
|
|
impl NativeInterface for MockNative {
|
|
fn syscall(&mut self, id: u32, _args: &[Value], ret: &mut HostReturn, _hw: &mut dyn HardwareBridge) -> Result<(), prometeu_core::virtual_machine::VmFault> {
|
|
if id == 0x2010 { // InputPadSnapshot
|
|
for _ in 0..48 {
|
|
ret.push_bool(false);
|
|
}
|
|
} else if id == 0x2011 { // InputTouchSnapshot
|
|
for _ in 0..6 {
|
|
ret.push_int(0);
|
|
}
|
|
} else {
|
|
// Push one result for others that might expect it
|
|
// Based on results_count() in syscalls.rs, most return 1 except GfxClear565 (0)
|
|
if id != 0x1010 {
|
|
ret.push_null();
|
|
}
|
|
}
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn test_canonical_cartridge_heartbeat() {
|
|
let mut pbc_path = Path::new("../../test-cartridges/canonical/golden/program.pbc").to_path_buf();
|
|
if !pbc_path.exists() {
|
|
pbc_path = Path::new("test-cartridges/canonical/golden/program.pbc").to_path_buf();
|
|
}
|
|
|
|
let pbc_bytes = fs::read(pbc_path).expect("Failed to read canonical PBC. Did you run the generation test?");
|
|
|
|
let mut vm = VirtualMachine::new(vec![], vec![]);
|
|
vm.initialize(pbc_bytes, "frame").expect("Failed to initialize VM with canonical cartridge");
|
|
vm.prepare_call("frame");
|
|
|
|
let mut native = MockNative;
|
|
let mut hw = Hardware::new();
|
|
|
|
// Run for a reasonable budget
|
|
let report = vm.run_budget(1000, &mut native, &mut hw).expect("VM failed to run");
|
|
|
|
// Acceptance criteria:
|
|
// 1. No traps
|
|
match report.reason {
|
|
LogicalFrameEndingReason::Trap(trap) => panic!("VM trapped: {:?}", trap),
|
|
LogicalFrameEndingReason::Panic(msg) => panic!("VM panicked: {}", msg),
|
|
LogicalFrameEndingReason::Halted => {},
|
|
LogicalFrameEndingReason::EndOfRom => {},
|
|
LogicalFrameEndingReason::FrameSync => {},
|
|
LogicalFrameEndingReason::BudgetExhausted => {},
|
|
LogicalFrameEndingReason::Breakpoint => {},
|
|
}
|
|
|
|
// 2. Deterministic output state (if any)
|
|
// In our frame(), z should be 30.
|
|
// Local 2 in frame() should be 30.
|
|
// Let's check the stack or locals if possible.
|
|
|
|
// The VM should have finished 'frame'.
|
|
// Since 'frame' returns void, the stack should be empty (or have the return value if any, but it's void).
|
|
assert_eq!(vm.operand_stack.len(), 0, "Stack should be empty after frame() execution");
|
|
|
|
println!("Heartbeat test passed!");
|
|
}
|