pr5.6
This commit is contained in:
parent
155be962b7
commit
b57e186490
55
crates/console/prometeu-vm/tests/syscall_multi_return.rs
Normal file
55
crates/console/prometeu-vm/tests/syscall_multi_return.rs
Normal file
@ -0,0 +1,55 @@
|
||||
//! Deterministic tests for multi-return syscalls with the slot-based ABI.
|
||||
use prometeu_bytecode::isa::core::CoreOpCode as OpCode;
|
||||
use prometeu_bytecode::{FunctionMeta, Value};
|
||||
use prometeu_vm::{HostContext, HostReturn, NativeInterface, VirtualMachine};
|
||||
use prometeu_hal::vm_fault::VmFault;
|
||||
|
||||
fn enc_op(op: OpCode) -> [u8; 2] { (op as u16).to_le_bytes() }
|
||||
|
||||
#[test]
|
||||
fn vm_syscall_multi_return_stack_contents() {
|
||||
// Use a real multi-return syscall id with ret_slots = 4: PadGetUp (0x2200)
|
||||
// ROM: SYSCALL 0x2200; HALT
|
||||
let mut rom = Vec::new();
|
||||
rom.extend_from_slice(&enc_op(OpCode::Syscall));
|
||||
rom.extend_from_slice(&0x2200u32.to_le_bytes());
|
||||
rom.extend_from_slice(&enc_op(OpCode::Halt));
|
||||
|
||||
struct TestNative;
|
||||
impl NativeInterface for TestNative {
|
||||
fn syscall(
|
||||
&mut self,
|
||||
id: u32,
|
||||
_args: &[Value],
|
||||
ret: &mut HostReturn,
|
||||
_ctx: &mut HostContext,
|
||||
) -> Result<(), VmFault> {
|
||||
assert_eq!(id, 0x2200);
|
||||
// Push exactly 4 results in a known order.
|
||||
ret.push_int(11);
|
||||
ret.push_int(22);
|
||||
ret.push_bool(true);
|
||||
ret.push_bounded(7)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
let mut vm = VirtualMachine::new(rom.clone(), vec![]);
|
||||
vm.program.functions = std::sync::Arc::from(vec![FunctionMeta {
|
||||
code_offset: 0,
|
||||
code_len: rom.len() as u32,
|
||||
..Default::default()
|
||||
}]);
|
||||
|
||||
let mut native = TestNative;
|
||||
let mut ctx = HostContext::new(None);
|
||||
vm.prepare_call("0");
|
||||
let _ = vm.run_budget(100, &mut native, &mut ctx).expect("VM run failed");
|
||||
|
||||
// Verify stack order: last pushed is on top
|
||||
assert_eq!(vm.pop().unwrap(), Value::Bounded(7));
|
||||
assert_eq!(vm.pop().unwrap(), Value::Boolean(true));
|
||||
assert_eq!(vm.pop().unwrap(), Value::Int64(22));
|
||||
assert_eq!(vm.pop().unwrap(), Value::Int64(11));
|
||||
assert!(vm.operand_stack.is_empty());
|
||||
}
|
||||
@ -269,6 +269,35 @@ fn golden_ok_syscall_args_and_returns() {
|
||||
assert!(res_b[0] >= 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn golden_ok_syscall_multi_returns() {
|
||||
// Syscall with 0 args and 4 returns: PadGetUp (0x2200)
|
||||
// Program: SYSCALL 0x2200; RET (ret_slots = 4)
|
||||
let mut code = Vec::new();
|
||||
code.extend_from_slice(&enc_op(OpCode::Syscall));
|
||||
code.extend_from_slice(&0x2200u32.to_le_bytes()); // PadGetUp: 0 args, 4 returns
|
||||
code.extend_from_slice(&enc_op(OpCode::Ret));
|
||||
|
||||
let functions = func(FunctionMeta { code_offset: 0, code_len: code.len() as u32, return_slots: 4, ..Default::default() });
|
||||
let res = Verifier::verify(&code, &functions).unwrap();
|
||||
// Max stack height should reach at least 4 due to the syscall's return values
|
||||
assert!(res[0] >= 4);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn golden_err_syscall_multi_returns_mismatch() {
|
||||
// Same syscall (PadGetUp: returns 4), but function declares only 3 return slots.
|
||||
// Program: SYSCALL 0x2200; RET (ret_slots = 3) → verifier must reject due to BadRetStackHeight.
|
||||
let mut code = Vec::new();
|
||||
code.extend_from_slice(&enc_op(OpCode::Syscall));
|
||||
code.extend_from_slice(&0x2200u32.to_le_bytes());
|
||||
code.extend_from_slice(&enc_op(OpCode::Ret));
|
||||
|
||||
let functions = func(FunctionMeta { code_offset: 0, code_len: code.len() as u32, return_slots: 3, ..Default::default() });
|
||||
let res = Verifier::verify(&code, &functions);
|
||||
assert_eq!(res, Err(VerifierError::BadRetStackHeight { pc: 6, height: 4, expected: 3 }));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn golden_err_invalid_func_id() {
|
||||
// Encode a Call with invalid function id (beyond functions.len())
|
||||
|
||||
@ -1,45 +0,0 @@
|
||||
# PR-5.6 — Syscall Multi-Return Tests
|
||||
|
||||
### Briefing
|
||||
|
||||
We must ensure multi-return syscalls behave correctly with the slot-based ABI.
|
||||
|
||||
### Target
|
||||
|
||||
* Add deterministic tests covering multi-return behavior.
|
||||
|
||||
### Work items
|
||||
|
||||
* Create or adapt at least one syscall with `ret_slots > 1`.
|
||||
* Add tests:
|
||||
|
||||
* Verify correct stack results after syscall.
|
||||
* Verify incorrect caller expectations fail verification.
|
||||
|
||||
### Acceptance checklist
|
||||
|
||||
* [ ] Multi-return syscalls behave correctly.
|
||||
* [ ] Verifier catches mismatches.
|
||||
* [ ] `cargo test` passes.
|
||||
|
||||
### Tests
|
||||
|
||||
* New multi-return syscall tests.
|
||||
|
||||
### Junie instructions
|
||||
|
||||
**You MAY:**
|
||||
|
||||
* Add deterministic tests.
|
||||
* Use existing syscalls or create a simple test-only syscall.
|
||||
|
||||
**You MUST NOT:**
|
||||
|
||||
* Modify syscall semantics to satisfy tests.
|
||||
* Add nondeterministic behavior.
|
||||
|
||||
**If unclear:**
|
||||
|
||||
* Ask before introducing new test syscalls.
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user