diff --git a/crates/wasm-actor/tests/wasm_actor.rs b/crates/wasm-actor/tests/wasm_actor.rs index 7f0230d..afa613f 100644 --- a/crates/wasm-actor/tests/wasm_actor.rs +++ b/crates/wasm-actor/tests/wasm_actor.rs @@ -1,6 +1,6 @@ use swactor::actor::{ActorAddress, ActorInterface}; use swactor::runtime::{Ctx, Runtime, RuntimeConfig}; -use swactor_wasm_actor::{ByteMessage, SharedEngine, WasmActorBuilder, WasmActorError}; +use swactor_wasm_actor::{ByteMessage, SharedEngine, WasmActor, WasmActorBuilder, WasmActorError}; use proptest::prelude::*; @@ -3912,3 +3912,71 @@ fn echo_processes_500_sequential_messages() { // all 500 messages should fit. Verify all echoed correctly. assert_eq!(received_count, 500, "all 500 messages should echo"); } + +// ── Mass spawn and stop: 100 WASM actors ──────────────────────────────────── + +#[test] +fn mass_spawn_and_stop_100_actors() { + let engine = SharedEngine::new().unwrap(); + let wasm_bytes = guest_wasm("silent"); + let rt = Runtime::new(RuntimeConfig::default()); + + let mut addrs = Vec::new(); + for _ in 0..100 { + let actor = WasmActorBuilder::new(engine.clone(), wasm_bytes.clone()) + .build().unwrap(); + addrs.push(rt.spawn(actor).unwrap()); + } + rt.tick(); + + for addr in &addrs { + rt.stop_actor(*addr).unwrap(); + } + rt.tick(); + rt.tick(); + + for addr in &addrs { + assert!(rt.send_to(*addr, ByteMessage(vec![1])).is_err()); + } +} + +// ── Echo to stopping actor: send silently fails ───────────────────────────── + +#[test] +fn echo_to_stopping_actor_silently_fails() { + let engine = SharedEngine::new().unwrap(); + let wasm_bytes = guest_wasm("echo"); + + let actor_a = WasmActorBuilder::new(engine.clone(), wasm_bytes.clone()).build().unwrap(); + let actor_b = WasmActorBuilder::new(engine, wasm_bytes).build().unwrap(); + + let rt = Runtime::new(RuntimeConfig::default()); + let addr_a = rt.spawn(actor_a).unwrap(); + let addr_b = rt.spawn(actor_b).unwrap(); + rt.tick(); + + rt.send_to(addr_a, framed_msg(&addr_b, b"to-dying-b")).unwrap(); + rt.stop_actor(addr_b).unwrap(); + rt.tick(); // A echoes to B (stopping) — silently fails + rt.tick(); + + // A should still be alive + let inbox = rt.new_inbox::().unwrap(); + rt.send_to(addr_a, framed_msg(inbox.addr(), b"still-alive")).unwrap(); + rt.tick(); + assert!(inbox.try_recv().is_some(), "actor A should survive"); +} + +// ── Compile-time trait checks ─────────────────────────────────────────────── + +#[test] +fn shared_engine_is_send_and_sync() { + fn assert_send_sync() {} + assert_send_sync::(); +} + +#[test] +fn wasm_actor_is_send() { + fn assert_send() {} + assert_send::(); +}