test(wasm-actor): cycle 84 — i32 invert, native spawns WASM, factorial, determinism (374 tests)

Added 4 tests: i32 bit pattern inversion, native handler spawns WASM and sends,
factorial loop, echo determinism across 10 independent runs.
No new bugs found.

Authored by Claude, lovingly guided by Zachery Aaron Shores-Chmielewski
This commit is contained in:
Claude 2026-02-13 10:53:37 +00:00
parent 21c6f58907
commit 099005aa67

View file

@ -11988,4 +11988,130 @@ fn heterogeneous_wat_actors_on_same_runtime() {
// One is "hello", other is [0x42]
assert!(msgs.iter().any(|m| m == b"hello"));
assert!(msgs.iter().any(|m| m == &[0x42]));
}
// ── Cycle 84 ─────────────────────────────────────────────────────────────────
// Guest inverts bit pattern: i32.xor with 0xFFFFFFFF on 4-byte chunks
#[test]
fn guest_inverts_i32_pattern() {
let wat = r#"(module
(import "swactor" "send" (func $send (param i32 i32 i32)))
(memory (export "memory") 1)
(func (export "alloc") (param $len i32) (result i32) i32.const 1024)
(func (export "handle") (param $ptr i32) (param $len i32)
(local $i i32)
;; Need at least 36 bytes (32 addr + 4 payload)
(if (i32.lt_u (local.get $len) (i32.const 36)) (then return))
;; XOR 4 bytes at ptr+32 with 0xFFFFFFFF
(i32.store (i32.add (local.get $ptr) (i32.const 32))
(i32.xor
(i32.load (i32.add (local.get $ptr) (i32.const 32)))
(i32.const -1)))
(call $send
(local.get $ptr)
(i32.add (local.get $ptr) (i32.const 32))
(i32.const 4))
)
)"#;
let engine = SharedEngine::new().unwrap();
let actor = WasmActorBuilder::new(engine, wat::parse_str(wat).unwrap())
.build().unwrap();
let rt = Runtime::new(RuntimeConfig::default());
let inbox = rt.new_inbox::<ByteMessage>().unwrap();
let addr = rt.spawn(actor).unwrap();
rt.send_to(addr, framed_msg(inbox.addr(), &[0x12, 0x34, 0x56, 0x78])).unwrap();
rt.tick();
let resp = inbox.try_recv().expect("inverted pattern");
assert_eq!(resp.0, vec![0xED, 0xCB, 0xA9, 0x87]);
}
// Native actor that spawns WASM and sends to it
struct NativeWasmSpawner2 {
engine: SharedEngine,
inbox_addr: ActorAddress,
}
impl ActorInterface for NativeWasmSpawner2 {
type Incoming = ByteMessage;
type Response = ();
fn handle(&mut self, ctx: &Ctx, _msg: ByteMessage) {
let actor = WasmActorBuilder::new(self.engine.clone(), guest_wasm("echo"))
.build().unwrap();
let wasm_addr = ctx.spawn(actor).unwrap();
let _ = ctx.send(wasm_addr, framed_msg(&self.inbox_addr, b"spawned-inline"));
}
}
#[test]
fn native_spawns_wasm_and_sends_in_handler() {
let engine = SharedEngine::new().unwrap();
let rt = Runtime::new(RuntimeConfig::default());
let inbox = rt.new_inbox::<ByteMessage>().unwrap();
let spawner = NativeWasmSpawner2 {
engine,
inbox_addr: *inbox.addr(),
};
let s_addr = rt.spawn(spawner).unwrap();
rt.send_to(s_addr, ByteMessage(vec![])).unwrap();
rt.tick(); // spawner spawns WASM + sends to it
rt.tick(); // WASM echo processes message
rt.tick(); // ensure delivery
let resp = inbox.try_recv().expect("spawned WASM should echo");
assert_eq!(resp.0, b"spawned-inline");
}
// Guest with nested loop computing factorial(5) = 120
#[test]
fn guest_factorial_loop() {
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)
(local $result i32)
(local $n i32)
(local.set $result (i32.const 1))
(local.set $n (i32.const 5))
(block $exit
(loop $loop
(br_if $exit (i32.le_u (local.get $n) (i32.const 1)))
(local.set $result (i32.mul (local.get $result) (local.get $n)))
(local.set $n (i32.sub (local.get $n) (i32.const 1)))
(br $loop)
)
)
(i32.store (local.get $ptr) (local.get $result))
)
)"#;
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();
}
// Verify echo determinism: same input always produces same output
#[test]
fn echo_determinism_ten_runs() {
let engine = SharedEngine::new().unwrap();
let payload = b"deterministic-test-payload";
let mut outputs = Vec::new();
for _ in 0..10 {
let actor = WasmActorBuilder::new(engine.clone(), guest_wasm("echo")).build().unwrap();
let rt = Runtime::new(RuntimeConfig::default());
let inbox = rt.new_inbox::<ByteMessage>().unwrap();
let addr = rt.spawn(actor).unwrap();
rt.send_to(addr, framed_msg(inbox.addr(), payload)).unwrap();
rt.tick();
outputs.push(inbox.try_recv().unwrap().0);
}
assert!(outputs.iter().all(|o| o == &outputs[0]),
"all 10 runs should produce identical output");
}