bin-runner #36
2 changed files with 74 additions and 0 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
|
@ -2747,6 +2747,7 @@ dependencies = [
|
|||
name = "swactor-wasm-actor"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"proptest",
|
||||
"swactor",
|
||||
"wasmtime",
|
||||
"wat",
|
||||
|
|
|
|||
|
|
@ -1202,6 +1202,79 @@ fn native_handler_spawns_wasm_actor_and_forwards_message() {
|
|||
assert_eq!(received.0, b"spawned-echo");
|
||||
}
|
||||
|
||||
// ── Bounded mailbox: WASM actor with backpressure ────────────────────────────
|
||||
|
||||
#[test]
|
||||
fn bounded_mailbox_applies_to_wasm_actor() {
|
||||
// With a bounded mailbox of capacity 3, sending 10 messages should
|
||||
// result in only 3 being processed (DropNewest policy).
|
||||
use swactor::runtime::MailboxOverflow;
|
||||
|
||||
let engine = SharedEngine::new().unwrap();
|
||||
let actor = WasmActorBuilder::new(engine, guest_wasm("echo"))
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
let config = RuntimeConfig {
|
||||
default_mailbox_capacity: 3,
|
||||
mailbox_overflow: MailboxOverflow::DropNewest,
|
||||
..RuntimeConfig::default()
|
||||
};
|
||||
let rt = Runtime::new(config);
|
||||
let inbox = rt.new_inbox::<ByteMessage>().unwrap();
|
||||
let addr = rt.spawn(actor).unwrap();
|
||||
|
||||
// Send 10 messages before any tick — only first 3 should be kept
|
||||
for i in 0u8..10 {
|
||||
rt.send_to(addr, framed_msg(inbox.addr(), &[i])).unwrap();
|
||||
}
|
||||
rt.tick();
|
||||
|
||||
let mut received = Vec::new();
|
||||
while let Some(msg) = inbox.try_recv() {
|
||||
received.push(msg.0[0]);
|
||||
}
|
||||
|
||||
assert_eq!(received.len(), 3, "bounded mailbox should limit to 3 messages");
|
||||
// DropNewest keeps the first 3 sent
|
||||
assert_eq!(received, vec![0, 1, 2]);
|
||||
}
|
||||
|
||||
// ── Property: alloc failures never kill the actor ────────────────────────────
|
||||
|
||||
proptest! {
|
||||
#[test]
|
||||
fn prop_any_alloc_return_value_never_kills_actor(alloc_val in -100i32..70000) {
|
||||
// Regardless of what alloc returns (negative, zero, OOB, valid),
|
||||
// sending a message should never kill the actor.
|
||||
let alloc_const = format!("i32.const {alloc_val}");
|
||||
let wat = format!(r#"
|
||||
(module
|
||||
(import "swactor" "send" (func $send (param i32 i32 i32)))
|
||||
(memory (export "memory") 1)
|
||||
(func (export "alloc") (param i32) (result i32)
|
||||
{alloc_const}
|
||||
)
|
||||
(func (export "handle") (param i32 i32))
|
||||
)
|
||||
"#);
|
||||
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 addr = rt.spawn(actor).unwrap();
|
||||
|
||||
// Send a message — should never panic or poison
|
||||
rt.send_to(addr, ByteMessage(vec![0u8; 100])).unwrap();
|
||||
rt.tick();
|
||||
|
||||
// Actor should still accept messages (not poisoned)
|
||||
let result = rt.send_to(addr, ByteMessage(vec![1]));
|
||||
prop_assert!(result.is_ok(), "actor should survive any alloc return value: {alloc_val}");
|
||||
}
|
||||
}
|
||||
|
||||
// ── Multi-worker: WASM actors across threads ─────────────────────────────────
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
Loading…
Reference in a new issue