// use std::fs; // use std::path::Path; // use prometeu_core::{Value, VmFault}; // use prometeu_drivers::hardware::Hardware; // use prometeu_hal::{HostContext, HostReturn, NativeInterface}; // use prometeu_vm::{LogicalFrameEndingReason, VirtualMachine}; // // struct MockNative; // impl NativeInterface for MockNative { // fn syscall(&mut self, id: u32, _args: &[Value], ret: &mut HostReturn, _ctx: &mut HostContext) -> Result<(), 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?"); // // // Determine entrypoint from the compiled module exports // let entry_symbol = "src/main/modules:frame"; // // let mut vm = VirtualMachine::new(vec![], vec![]); // vm.initialize(pbc_bytes, entry_symbol).expect("Failed to initialize VM with canonical cartridge"); // vm.prepare_call(entry_symbol); // // let mut native = MockNative; // let mut hw = Hardware::new(); // let mut ctx = HostContext::new(Some(&mut hw)); // // // Run for a reasonable budget // let report = vm.run_budget(1000, &mut native, &mut ctx).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) // // Observação: a PVM agora sinaliza FRAME_SYNC imediatamente antes do RET do entry point. // // Quando o motivo é FRAME_SYNC, não exigimos pilha vazia (a limpeza final ocorre após o RET). // // Para os demais motivos (RET/Halted/EndOfRom), a pilha deve estar vazia para frame(): void. // if !matches!(report.reason, LogicalFrameEndingReason::FrameSync) { // assert_eq!(vm.operand_stack.len(), 0, "Stack should be empty after frame() execution"); // } // // println!("Heartbeat test passed!"); // }