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:
parent
21c6f58907
commit
099005aa67
1 changed files with 126 additions and 0 deletions
|
|
@ -11989,3 +11989,129 @@ fn heterogeneous_wat_actors_on_same_runtime() {
|
||||||
assert!(msgs.iter().any(|m| m == b"hello"));
|
assert!(msgs.iter().any(|m| m == b"hello"));
|
||||||
assert!(msgs.iter().any(|m| m == &[0x42]));
|
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");
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue