bin-runner #36
1 changed files with 141 additions and 0 deletions
|
|
@ -10361,4 +10361,145 @@ fn guest_xor_payload_with_key() {
|
|||
|
||||
let resp = inbox.try_recv().expect("XOR response");
|
||||
assert_eq!(resp.0, vec![0xFF, 0x00, 0x55], "each byte XORed with 0xFF");
|
||||
}
|
||||
|
||||
// ── Cycle 71 ─────────────────────────────────────────────────────────────────
|
||||
|
||||
// Same payload sent to echo and double — both produce correct results
|
||||
#[test]
|
||||
fn same_payload_to_echo_and_double_verified() {
|
||||
let engine = SharedEngine::new().unwrap();
|
||||
let echo = WasmActorBuilder::new(engine.clone(), guest_wasm("echo")).build().unwrap();
|
||||
let double = WasmActorBuilder::new(engine, guest_wasm("double")).build().unwrap();
|
||||
let rt = Runtime::new(RuntimeConfig::default());
|
||||
let inbox_e = rt.new_inbox::<ByteMessage>().unwrap();
|
||||
let inbox_d = rt.new_inbox::<ByteMessage>().unwrap();
|
||||
let e_addr = rt.spawn(echo).unwrap();
|
||||
let d_addr = rt.spawn(double).unwrap();
|
||||
|
||||
let payload = b"shared-payload";
|
||||
rt.send_to(e_addr, framed_msg(inbox_e.addr(), payload)).unwrap();
|
||||
rt.send_to(d_addr, framed_msg(inbox_d.addr(), payload)).unwrap();
|
||||
rt.tick();
|
||||
|
||||
let e_msgs: Vec<_> = std::iter::from_fn(|| inbox_e.try_recv().map(|m| m.0)).collect();
|
||||
let d_msgs: Vec<_> = std::iter::from_fn(|| inbox_d.try_recv().map(|m| m.0)).collect();
|
||||
assert_eq!(e_msgs.len(), 1);
|
||||
assert_eq!(d_msgs.len(), 2);
|
||||
assert_eq!(e_msgs[0], payload);
|
||||
assert!(d_msgs.iter().all(|m| m == payload));
|
||||
}
|
||||
|
||||
// Guest stores and reloads a f32 value
|
||||
#[test]
|
||||
fn guest_f32_store_and_load() {
|
||||
let wat = r#"(module
|
||||
(memory (export "memory") 1)
|
||||
(func (export "alloc") (param $len i32) (result i32) i32.const 1024)
|
||||
(func (export "handle") (param $ptr i32) (param $len i32)
|
||||
;; Store f32 at ptr, load it back, add 1.0, store again
|
||||
(f32.store (local.get $ptr) (f32.const 3.14))
|
||||
(f32.store (local.get $ptr)
|
||||
(f32.add (f32.load (local.get $ptr)) (f32.const 1.0))
|
||||
)
|
||||
)
|
||||
)"#;
|
||||
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(vec![0u8; 4])).unwrap();
|
||||
rt.tick();
|
||||
}
|
||||
|
||||
// Spawn 50 silent actors, tick, stop all — clean shutdown
|
||||
#[test]
|
||||
fn fifty_silent_actors_clean_shutdown() {
|
||||
let engine = SharedEngine::new().unwrap();
|
||||
let rt = Runtime::new(RuntimeConfig::default());
|
||||
let addrs: Vec<_> = (0..50)
|
||||
.map(|_| {
|
||||
let actor = WasmActorBuilder::new(engine.clone(), guest_wasm("silent"))
|
||||
.build().unwrap();
|
||||
rt.spawn(actor).unwrap()
|
||||
})
|
||||
.collect();
|
||||
|
||||
for addr in &addrs {
|
||||
rt.send_to(*addr, ByteMessage(vec![0])).unwrap();
|
||||
}
|
||||
rt.tick();
|
||||
|
||||
for addr in &addrs {
|
||||
rt.stop_actor(*addr);
|
||||
}
|
||||
rt.tick();
|
||||
rt.tick();
|
||||
}
|
||||
|
||||
// Guest with deeply nested blocks (5 levels)
|
||||
#[test]
|
||||
fn guest_deeply_nested_blocks() {
|
||||
let wat = r#"(module
|
||||
(memory (export "memory") 1)
|
||||
(func (export "alloc") (param $len i32) (result i32) i32.const 1024)
|
||||
(func (export "handle") (param $ptr i32) (param $len i32)
|
||||
(block $b0
|
||||
(block $b1
|
||||
(block $b2
|
||||
(block $b3
|
||||
(block $b4
|
||||
;; Store nesting depth at ptr
|
||||
(i32.store (local.get $ptr) (i32.const 5))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)"#;
|
||||
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(vec![0u8; 4])).unwrap();
|
||||
rt.tick();
|
||||
}
|
||||
|
||||
// Property: mixed guest types always produce expected response counts
|
||||
proptest! {
|
||||
#[test]
|
||||
fn prop_mixed_guest_response_counts(
|
||||
echo_count in 0usize..5,
|
||||
double_count in 0usize..5,
|
||||
silent_count in 0usize..5,
|
||||
) {
|
||||
let engine = SharedEngine::new().unwrap();
|
||||
let rt = Runtime::new(RuntimeConfig::default());
|
||||
let inbox = rt.new_inbox::<ByteMessage>().unwrap();
|
||||
|
||||
for _ in 0..echo_count {
|
||||
let actor = WasmActorBuilder::new(engine.clone(), guest_wasm("echo")).build().unwrap();
|
||||
let addr = rt.spawn(actor).unwrap();
|
||||
rt.send_to(addr, framed_msg(inbox.addr(), b"x")).unwrap();
|
||||
}
|
||||
for _ in 0..double_count {
|
||||
let actor = WasmActorBuilder::new(engine.clone(), guest_wasm("double")).build().unwrap();
|
||||
let addr = rt.spawn(actor).unwrap();
|
||||
rt.send_to(addr, framed_msg(inbox.addr(), b"x")).unwrap();
|
||||
}
|
||||
for _ in 0..silent_count {
|
||||
let actor = WasmActorBuilder::new(engine.clone(), guest_wasm("silent")).build().unwrap();
|
||||
let addr = rt.spawn(actor).unwrap();
|
||||
rt.send_to(addr, ByteMessage(b"x".to_vec())).unwrap();
|
||||
}
|
||||
rt.tick();
|
||||
|
||||
let msg_count = std::iter::from_fn(|| inbox.try_recv()).count();
|
||||
let expected = echo_count + double_count * 2;
|
||||
assert_eq!(msg_count, expected,
|
||||
"echo({echo_count})+double({double_count}*2)+silent({silent_count}*0)={expected}, got {msg_count}");
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue