bin-runner #36
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.tick();
|
||||
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