test(wasm-actor): cycle 78 — fibonacci recursion, 5-actor inbox, block result (346 tests)

Added 5 tests: fibonacci via recursion, single inbox from five actors, minimal
lifecycle no messages, reuse message bytes, block with result value.
No new bugs found.

Authored by Claude, lovingly guided by Zachery Aaron Shores-Chmielewski
This commit is contained in:
Claude 2026-02-13 10:44:09 +00:00
parent 00051f85d8
commit e96891ae89

View file

@ -11258,4 +11258,123 @@ fn actor_replacement_cycle() {
rt.stop_actor(addr); rt.stop_actor(addr);
rt.tick(); rt.tick();
} }
}
// ── Cycle 78 ─────────────────────────────────────────────────────────────────
// Guest with recursive helper that computes fibonacci (bounded)
#[test]
fn guest_fibonacci_via_recursion() {
let wat = r#"(module
(memory (export "memory") 1)
(func $fib (param $n i32) (result i32)
(if (result i32) (i32.le_u (local.get $n) (i32.const 1))
(then (local.get $n))
(else
(i32.add
(call $fib (i32.sub (local.get $n) (i32.const 1)))
(call $fib (i32.sub (local.get $n) (i32.const 2)))
)
)
)
)
(func (export "alloc") (param $len i32) (result i32) i32.const 1024)
(func (export "handle") (param $ptr i32) (param $len i32)
;; Compute fib(10) = 55, store at ptr
(i32.store (local.get $ptr) (call $fib (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(vec![0u8; 4])).unwrap();
rt.tick();
}
// Inbox receives messages from multiple WASM actors simultaneously
#[test]
fn single_inbox_receives_from_five_actors() {
let engine = SharedEngine::new().unwrap();
let rt = Runtime::new(RuntimeConfig::default());
let inbox = rt.new_inbox::<ByteMessage>().unwrap();
for i in 0..5u8 {
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(), &[i])).unwrap();
}
rt.tick();
let mut msgs: Vec<Vec<u8>> = std::iter::from_fn(|| inbox.try_recv().map(|m| m.0)).collect();
msgs.sort();
assert_eq!(msgs.len(), 5);
for i in 0..5u8 {
assert_eq!(msgs[i as usize], vec![i]);
}
}
// Guest that does nothing at all — purely exercises spawn+tick+stop lifecycle
#[test]
fn minimal_lifecycle_no_messages() {
let wat = r#"(module
(memory (export "memory") 1)
(func (export "alloc") (param $len i32) (result i32) i32.const 0)
(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();
rt.tick();
rt.tick();
rt.stop_actor(addr);
rt.tick();
}
// Same message bytes reused for multiple sends — no aliasing issues
#[test]
fn reuse_message_bytes_for_multiple_sends() {
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 = framed_msg(inbox.addr(), b"reuse");
for _ in 0..5 {
// Clone the same message each time
rt.send_to(addr, msg.clone()).unwrap();
}
rt.tick();
let msgs: Vec<Vec<u8>> = std::iter::from_fn(|| inbox.try_recv().map(|m| m.0)).collect();
assert_eq!(msgs.len(), 5);
assert!(msgs.iter().all(|m| m == b"reuse"));
}
// Guest uses block with result value
#[test]
fn guest_block_with_result_value() {
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 that produces a value
(i32.store (local.get $ptr)
(block (result i32)
(i32.add (local.get $len) (i32.const 42))
)
)
)
)"#;
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();
} }