test: Cycle 47 — page boundary exact/OOB, multiple runtimes, full message mirror
- alloc_at_page_boundary_works: alloc + msg = exactly 65536, in bounds - alloc_one_past_page_boundary_drops: alloc + msg = 65537, OOB drops gracefully - multiple_runtimes_with_wasm_actors: two separate runtimes with WASM actors - guest_mirrors_full_message: sends full message (addr+payload) as payload All 204 tests pass. No new bugs found. Authored by Claude, lovingly guided by Zachery Aaron Shores-Chmielewski
This commit is contained in:
parent
5e925a9fc1
commit
6aeb289df0
1 changed files with 133 additions and 0 deletions
|
|
@ -7145,4 +7145,137 @@ fn comprehensive_lifecycle_all_guest_types_200th() {
|
||||||
rt.send_to(echo_addr, framed_msg(inbox.addr(), b"gone")).ok();
|
rt.send_to(echo_addr, framed_msg(inbox.addr(), b"gone")).ok();
|
||||||
rt.tick();
|
rt.tick();
|
||||||
assert!(inbox.try_recv().is_none(), "stopped actors should not deliver");
|
assert!(inbox.try_recv().is_none(), "stopped actors should not deliver");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Guest alloc returns pointer at exact page boundary ──────────────────────
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn alloc_at_page_boundary_works() {
|
||||||
|
// Guest alloc returns 65536 - 64 = 65472. With a 64-byte message,
|
||||||
|
// end = 65472 + 64 = 65536 = memory size. Exactly in bounds.
|
||||||
|
let wat = r#"
|
||||||
|
(module
|
||||||
|
(import "swactor" "send" (func $send (param i32 i32 i32)))
|
||||||
|
(memory (export "memory") 1)
|
||||||
|
(func (export "alloc") (param i32) (result i32) i32.const 65472)
|
||||||
|
(func (export "handle") (param $ptr i32) (param $len i32)
|
||||||
|
(call $send
|
||||||
|
(local.get $ptr)
|
||||||
|
(i32.add (local.get $ptr) (i32.const 32))
|
||||||
|
(i32.sub (local.get $len) (i32.const 32))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
"#;
|
||||||
|
let wasm = wat::parse_str(wat).unwrap();
|
||||||
|
let engine = SharedEngine::new().unwrap();
|
||||||
|
let actor = WasmActorBuilder::new(engine, wasm).build().unwrap();
|
||||||
|
|
||||||
|
let rt = Runtime::new(RuntimeConfig::default());
|
||||||
|
let inbox = rt.new_inbox::<ByteMessage>().unwrap();
|
||||||
|
let addr = rt.spawn(actor).unwrap();
|
||||||
|
|
||||||
|
// 32 (addr) + 32 (payload) = 64 bytes → fits exactly at 65472..65536
|
||||||
|
let payload = vec![0xAB; 32];
|
||||||
|
rt.send_to(addr, framed_msg(inbox.addr(), &payload)).unwrap();
|
||||||
|
rt.tick();
|
||||||
|
|
||||||
|
let msg = inbox.try_recv().expect("exact page boundary should work");
|
||||||
|
assert_eq!(msg.0, payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Guest alloc returns pointer 1 byte past page boundary — drops ───────────
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn alloc_one_past_page_boundary_drops() {
|
||||||
|
// Guest alloc returns 65473. With 64-byte message:
|
||||||
|
// end = 65473 + 64 = 65537 > 65536. OOB, message dropped.
|
||||||
|
let wat = r#"
|
||||||
|
(module
|
||||||
|
(import "swactor" "send" (func $send (param i32 i32 i32)))
|
||||||
|
(memory (export "memory") 1)
|
||||||
|
(func (export "alloc") (param i32) (result i32) i32.const 65473)
|
||||||
|
(func (export "handle") (param i32 i32)
|
||||||
|
unreachable
|
||||||
|
)
|
||||||
|
)
|
||||||
|
"#;
|
||||||
|
let wasm = wat::parse_str(wat).unwrap();
|
||||||
|
let engine = SharedEngine::new().unwrap();
|
||||||
|
let actor = WasmActorBuilder::new(engine, wasm).build().unwrap();
|
||||||
|
|
||||||
|
let rt = Runtime::new(RuntimeConfig::default());
|
||||||
|
let inbox = rt.new_inbox::<ByteMessage>().unwrap();
|
||||||
|
let addr = rt.spawn(actor).unwrap();
|
||||||
|
|
||||||
|
let payload = vec![0xAB; 32]; // total msg = 64 bytes
|
||||||
|
rt.send_to(addr, framed_msg(inbox.addr(), &payload)).unwrap();
|
||||||
|
rt.tick();
|
||||||
|
|
||||||
|
assert!(inbox.try_recv().is_none(), "OOB alloc should drop message");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Multiple runtimes with WASM actors independently ────────────────────────
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn multiple_runtimes_with_wasm_actors() {
|
||||||
|
let engine = SharedEngine::new().unwrap();
|
||||||
|
|
||||||
|
// Runtime 1
|
||||||
|
let rt1 = Runtime::new(RuntimeConfig::default());
|
||||||
|
let inbox1 = rt1.new_inbox::<ByteMessage>().unwrap();
|
||||||
|
let actor1 = WasmActorBuilder::new(engine.clone(), guest_wasm("echo")).build().unwrap();
|
||||||
|
let addr1 = rt1.spawn(actor1).unwrap();
|
||||||
|
|
||||||
|
// Runtime 2
|
||||||
|
let rt2 = Runtime::new(RuntimeConfig::default());
|
||||||
|
let inbox2 = rt2.new_inbox::<ByteMessage>().unwrap();
|
||||||
|
let actor2 = WasmActorBuilder::new(engine, guest_wasm("double")).build().unwrap();
|
||||||
|
let addr2 = rt2.spawn(actor2).unwrap();
|
||||||
|
|
||||||
|
rt1.send_to(addr1, framed_msg(inbox1.addr(), b"rt1")).unwrap();
|
||||||
|
rt2.send_to(addr2, framed_msg(inbox2.addr(), b"rt2")).unwrap();
|
||||||
|
rt1.tick();
|
||||||
|
rt2.tick();
|
||||||
|
|
||||||
|
let msg1 = inbox1.try_recv().unwrap();
|
||||||
|
assert_eq!(msg1.0, b"rt1");
|
||||||
|
|
||||||
|
let d1 = inbox2.try_recv().unwrap();
|
||||||
|
let d2 = inbox2.try_recv().unwrap();
|
||||||
|
assert_eq!(d1.0, b"rt2");
|
||||||
|
assert_eq!(d2.0, b"rt2");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Guest sends back exact copy of the full message (including address) ─────
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn guest_mirrors_full_message() {
|
||||||
|
// Guest sends back the entire message (address + payload) to the dest.
|
||||||
|
let wat = r#"
|
||||||
|
(module
|
||||||
|
(import "swactor" "send" (func $send (param i32 i32 i32)))
|
||||||
|
(memory (export "memory") 1)
|
||||||
|
(func (export "alloc") (param i32) (result i32) i32.const 4096)
|
||||||
|
(func (export "handle") (param $ptr i32) (param $len i32)
|
||||||
|
;; Send the full message (including address header) as payload
|
||||||
|
(call $send (local.get $ptr) (local.get $ptr) (local.get $len))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
"#;
|
||||||
|
let wasm = wat::parse_str(wat).unwrap();
|
||||||
|
let engine = SharedEngine::new().unwrap();
|
||||||
|
let actor = WasmActorBuilder::new(engine, wasm).build().unwrap();
|
||||||
|
|
||||||
|
let rt = Runtime::new(RuntimeConfig::default());
|
||||||
|
let inbox = rt.new_inbox::<ByteMessage>().unwrap();
|
||||||
|
let addr = rt.spawn(actor).unwrap();
|
||||||
|
|
||||||
|
let original_msg = framed_msg(inbox.addr(), b"mirror");
|
||||||
|
rt.send_to(addr, original_msg.clone()).unwrap();
|
||||||
|
rt.tick();
|
||||||
|
|
||||||
|
let msg = inbox.try_recv().expect("should receive mirrored full message");
|
||||||
|
// Payload = full original message (address + payload)
|
||||||
|
assert_eq!(msg.0, original_msg.0, "should receive exact copy of full message");
|
||||||
}
|
}
|
||||||
Loading…
Reference in a new issue