test(wasm-actor): cycle 71 — f32 ops, nested blocks, mixed guest response fuzz (314 tests)

Added 5 tests: same payload to echo+double verified, f32 store/load, 50 silent
actors clean shutdown, 5-deep nested blocks, property test mixed guest response
counts. No new bugs found.

Authored by Claude, lovingly guided by Zachery Aaron Shores-Chmielewski
This commit is contained in:
Claude 2026-02-13 10:31:26 +00:00
parent 2fa72be283
commit 90c048d053

View file

@ -10362,3 +10362,144 @@ fn guest_xor_payload_with_key() {
let resp = inbox.try_recv().expect("XOR response"); let resp = inbox.try_recv().expect("XOR response");
assert_eq!(resp.0, vec![0xFF, 0x00, 0x55], "each byte XORed with 0xFF"); 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}");
}
}