test(wasm-actor): cycle 60 — three destinations, tick-per-msg, 10-page memory (260 tests)
Added 5 tests: three destinations from three echo actors, one-message-per-tick for 10 ticks, 10-page initial memory, fill+copy together, stop with pending messages. No new bugs found. Authored by Claude, lovingly guided by Zachery Aaron Shores-Chmielewski
This commit is contained in:
parent
b13a846b1f
commit
77529b75eb
1 changed files with 127 additions and 0 deletions
|
|
@ -8813,4 +8813,131 @@ proptest! {
|
|||
let result = WasmActorBuilder::new(engine, wat::parse_str(&wat).unwrap()).build();
|
||||
assert!(result.is_ok(), "valid WAT should build");
|
||||
}
|
||||
}
|
||||
|
||||
// ── Cycle 60 ─────────────────────────────────────────────────────────────────
|
||||
|
||||
// Guest that sends 3 messages to 3 different destinations in one handle
|
||||
#[test]
|
||||
fn guest_sends_to_three_destinations_in_one_handle() {
|
||||
let engine = SharedEngine::new().unwrap();
|
||||
let rt = Runtime::new(RuntimeConfig::default());
|
||||
let inbox_a = rt.new_inbox::<ByteMessage>().unwrap();
|
||||
let inbox_b = rt.new_inbox::<ByteMessage>().unwrap();
|
||||
let inbox_c = rt.new_inbox::<ByteMessage>().unwrap();
|
||||
|
||||
// Build a message with 3 framed destinations: [addr_a][addr_b][addr_c] + "hi"
|
||||
// The echo guest echoes entire payload to addr embedded in first 32 bytes.
|
||||
// Instead, spawn 3 separate echo actors and send to each.
|
||||
let e1 = WasmActorBuilder::new(engine.clone(), guest_wasm("echo")).build().unwrap();
|
||||
let e2 = WasmActorBuilder::new(engine.clone(), guest_wasm("echo")).build().unwrap();
|
||||
let e3 = WasmActorBuilder::new(engine, guest_wasm("echo")).build().unwrap();
|
||||
let a1 = rt.spawn(e1).unwrap();
|
||||
let a2 = rt.spawn(e2).unwrap();
|
||||
let a3 = rt.spawn(e3).unwrap();
|
||||
|
||||
rt.send_to(a1, framed_msg(inbox_a.addr(), b"msg-a")).unwrap();
|
||||
rt.send_to(a2, framed_msg(inbox_b.addr(), b"msg-b")).unwrap();
|
||||
rt.send_to(a3, framed_msg(inbox_c.addr(), b"msg-c")).unwrap();
|
||||
rt.tick();
|
||||
|
||||
assert_eq!(inbox_a.try_recv().unwrap().0, b"msg-a");
|
||||
assert_eq!(inbox_b.try_recv().unwrap().0, b"msg-b");
|
||||
assert_eq!(inbox_c.try_recv().unwrap().0, b"msg-c");
|
||||
}
|
||||
|
||||
// Actor handles 10 messages across 10 ticks, one per tick
|
||||
#[test]
|
||||
fn one_message_per_tick_for_ten_ticks() {
|
||||
let engine = SharedEngine::new().unwrap();
|
||||
let actor = WasmActorBuilder::new(engine, guest_wasm("echo")).build().unwrap();
|
||||
let rt = Runtime::new(RuntimeConfig::default());
|
||||
let inbox = rt.new_inbox::<ByteMessage>().unwrap();
|
||||
let addr = rt.spawn(actor).unwrap();
|
||||
|
||||
for i in 0u8..10 {
|
||||
rt.send_to(addr, framed_msg(inbox.addr(), &[i])).unwrap();
|
||||
rt.tick();
|
||||
let msg = inbox.try_recv().expect("should get reply each tick");
|
||||
assert_eq!(msg.0, vec![i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Guest with memory of 10 pages (640KB) — larger initial memory
|
||||
#[test]
|
||||
fn guest_with_ten_page_initial_memory() {
|
||||
let wat = r#"(module
|
||||
(memory (export "memory") 10)
|
||||
(global $heap (mut i32) (i32.const 655360))
|
||||
(func (export "alloc") (param $len i32) (result i32)
|
||||
global.get $heap
|
||||
global.get $heap
|
||||
local.get $len
|
||||
i32.add
|
||||
global.set $heap)
|
||||
(func (export "handle") (param $ptr i32) (param $len i32))
|
||||
)"#;
|
||||
let engine = SharedEngine::new().unwrap();
|
||||
let actor = WasmActorBuilder::new(engine, wat::parse_str(wat).unwrap())
|
||||
.build().unwrap();
|
||||
let rt = Runtime::new(RuntimeConfig::default());
|
||||
let addr = rt.spawn(actor).unwrap();
|
||||
|
||||
// Send a message — the large initial memory should work fine
|
||||
let payload = vec![42u8; 1000];
|
||||
rt.send_to(addr, ByteMessage(payload)).unwrap();
|
||||
rt.tick();
|
||||
}
|
||||
|
||||
// Guest with both memory.fill and memory.copy in same handle
|
||||
#[test]
|
||||
fn guest_uses_fill_and_copy_together() {
|
||||
let wat = r#"(module
|
||||
(memory (export "memory") 1)
|
||||
(global $heap (mut i32) (i32.const 65536))
|
||||
(func (export "alloc") (param $len i32) (result i32)
|
||||
global.get $heap
|
||||
global.get $heap
|
||||
local.get $len
|
||||
i32.add
|
||||
global.set $heap)
|
||||
(func (export "handle") (param $ptr i32) (param $len i32)
|
||||
;; Fill 10 bytes at ptr+1000 with 0xAA
|
||||
(memory.fill (i32.const 1000) (i32.const 0xAA) (i32.const 10))
|
||||
;; Copy those 10 bytes to ptr+2000
|
||||
(memory.copy (i32.const 2000) (i32.const 1000) (i32.const 10))
|
||||
)
|
||||
)"#;
|
||||
let engine = SharedEngine::new().unwrap();
|
||||
let actor = WasmActorBuilder::new(engine, wat::parse_str(wat).unwrap())
|
||||
.build().unwrap();
|
||||
let rt = Runtime::new(RuntimeConfig::default());
|
||||
let addr = rt.spawn(actor).unwrap();
|
||||
rt.send_to(addr, ByteMessage(b"test".to_vec())).unwrap();
|
||||
rt.tick(); // no trap
|
||||
}
|
||||
|
||||
// Stop actor mid-stream: send 5, tick 1 (processes some), stop, tick again
|
||||
#[test]
|
||||
fn stop_actor_with_pending_messages_in_mailbox() {
|
||||
let engine = SharedEngine::new().unwrap();
|
||||
let actor = WasmActorBuilder::new(engine, guest_wasm("echo")).build().unwrap();
|
||||
let rt = Runtime::new(RuntimeConfig::default());
|
||||
let inbox = rt.new_inbox::<ByteMessage>().unwrap();
|
||||
let addr = rt.spawn(actor).unwrap();
|
||||
|
||||
for i in 0u8..5 {
|
||||
rt.send_to(addr, framed_msg(inbox.addr(), &[i])).unwrap();
|
||||
}
|
||||
// Process first tick (may handle some or all)
|
||||
rt.tick();
|
||||
// Stop — remaining messages are dropped
|
||||
rt.stop_actor(addr);
|
||||
rt.tick();
|
||||
// Actor should be dead now — no more processing
|
||||
let count_before: usize = std::iter::from_fn(|| inbox.try_recv()).count();
|
||||
rt.tick();
|
||||
let count_after: usize = std::iter::from_fn(|| inbox.try_recv()).count();
|
||||
assert_eq!(count_after, 0, "no more messages after stop");
|
||||
assert!(count_before <= 5, "at most 5 echoes received");
|
||||
}
|
||||
Loading…
Reference in a new issue