bin-runner #36
1 changed files with 134 additions and 0 deletions
|
|
@ -3452,3 +3452,137 @@ fn hot_swap_wasm_actor_works() {
|
|||
assert_eq!(second.0, b"double-phase");
|
||||
assert!(inbox.try_recv().is_none());
|
||||
}
|
||||
|
||||
// ── Guest uses memory.copy: bulk copy within linear memory ──────────────────
|
||||
|
||||
#[test]
|
||||
fn guest_using_memory_copy_works() {
|
||||
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 256)
|
||||
(func (export "handle") (param $ptr i32) (param $len i32)
|
||||
(i32.store8 (i32.const 500) (i32.const 72))
|
||||
(i32.store8 (i32.const 501) (i32.const 73))
|
||||
(memory.copy (i32.const 600) (i32.const 500) (i32.const 2))
|
||||
local.get $ptr
|
||||
i32.const 600
|
||||
i32.const 2
|
||||
call $send
|
||||
)
|
||||
)
|
||||
"#;
|
||||
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();
|
||||
|
||||
rt.send_to(addr, framed_msg(inbox.addr(), b"copy-test")).unwrap();
|
||||
rt.tick();
|
||||
|
||||
let received = inbox.try_recv().expect("memory.copy should work");
|
||||
assert_eq!(received.0, b"HI");
|
||||
}
|
||||
|
||||
// ── Engine clone stress: 50 actors from same engine ─────────────────────────
|
||||
|
||||
#[test]
|
||||
fn fifty_actors_from_same_engine() {
|
||||
let engine = SharedEngine::new().unwrap();
|
||||
let wasm_bytes = guest_wasm("echo");
|
||||
let rt = Runtime::new(RuntimeConfig::default());
|
||||
let inbox = rt.new_inbox::<ByteMessage>().unwrap();
|
||||
|
||||
let mut addrs = Vec::new();
|
||||
for _ in 0..50 {
|
||||
let actor = WasmActorBuilder::new(engine.clone(), wasm_bytes.clone())
|
||||
.build()
|
||||
.unwrap();
|
||||
addrs.push(rt.spawn(actor).unwrap());
|
||||
}
|
||||
|
||||
rt.send_to(addrs[0], framed_msg(inbox.addr(), b"first")).unwrap();
|
||||
rt.send_to(addrs[49], framed_msg(inbox.addr(), b"last")).unwrap();
|
||||
rt.tick();
|
||||
|
||||
let mut received = Vec::new();
|
||||
while let Some(msg) = inbox.try_recv() {
|
||||
received.push(msg.0.clone());
|
||||
}
|
||||
assert_eq!(received.len(), 2);
|
||||
assert!(received.contains(&b"first".to_vec()));
|
||||
assert!(received.contains(&b"last".to_vec()));
|
||||
}
|
||||
|
||||
// ── Payload integrity: pattern check for copy correctness ───────────────────
|
||||
|
||||
#[test]
|
||||
fn payload_pattern_integrity_check() {
|
||||
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();
|
||||
|
||||
let payload: Vec<u8> = (0..500).map(|i| ((i * 7 + 13) % 256) as u8).collect();
|
||||
rt.send_to(addr, framed_msg(inbox.addr(), &payload)).unwrap();
|
||||
rt.tick();
|
||||
|
||||
let received = inbox.try_recv().expect("pattern payload should echo");
|
||||
assert_eq!(received.0, payload, "payload integrity check");
|
||||
}
|
||||
|
||||
// ── Lifecycle fuzz: echo with random stopping ───────────────────────────────
|
||||
|
||||
proptest! {
|
||||
#[test]
|
||||
fn prop_echo_lifecycle_fuzz(
|
||||
num_messages in 1usize..30,
|
||||
payload_sizes in proptest::collection::vec(1usize..200, 1..30),
|
||||
stop_at in proptest::option::of(0usize..30),
|
||||
) {
|
||||
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();
|
||||
|
||||
let msg_count = num_messages.min(payload_sizes.len());
|
||||
let mut echoed = 0;
|
||||
|
||||
for i in 0..msg_count {
|
||||
if stop_at == Some(i) {
|
||||
let _ = rt.stop_actor(addr);
|
||||
rt.tick();
|
||||
rt.tick();
|
||||
break;
|
||||
}
|
||||
|
||||
let payload: Vec<u8> = (0..payload_sizes[i]).map(|j| (j % 256) as u8).collect();
|
||||
let send_result = rt.send_to(addr, framed_msg(inbox.addr(), &payload));
|
||||
if send_result.is_err() {
|
||||
break;
|
||||
}
|
||||
rt.tick();
|
||||
|
||||
if let Some(received) = inbox.try_recv() {
|
||||
prop_assert_eq!(received.0, payload);
|
||||
echoed += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if stop_at.is_none() || stop_at.unwrap_or(0) > 0 {
|
||||
prop_assert!(echoed > 0 || stop_at == Some(0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue