bin-runner #36

Merged
zacheryasc merged 103 commits from bin-runner into master 2026-02-13 14:11:40 +00:00
Showing only changes of commit 099005aa67 - Show all commits

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");
}