test: Cycle 48 — self-send, bit rotation, bit counting, selective stop
- guest_sends_to_self_via_framed_address: self-send bounces through, reaches inbox - guest_uses_bit_rotation: i32.rotl instruction - guest_uses_bit_counting: i32.clz, i32.ctz, i32.popcnt instructions - stop_every_other_actor_remaining_work: stop 5 of 10, other 5 still respond All 208 tests pass. No new bugs found. Authored by Claude, lovingly guided by Zachery Aaron Shores-Chmielewski
This commit is contained in:
parent
6aeb289df0
commit
d4961978ec
1 changed files with 130 additions and 0 deletions
|
|
@ -7279,3 +7279,133 @@ fn guest_mirrors_full_message() {
|
|||
// Payload = full original message (address + payload)
|
||||
assert_eq!(msg.0, original_msg.0, "should receive exact copy of full message");
|
||||
}
|
||||
|
||||
// ── Guest sends to self (WASM actor address from host) ──────────────────────
|
||||
|
||||
#[test]
|
||||
fn guest_sends_to_self_via_framed_address() {
|
||||
// The payload contains the WASM actor's own address as the dest.
|
||||
// This creates a self-send that should be delivered next tick.
|
||||
let engine = SharedEngine::new().unwrap();
|
||||
let actor = WasmActorBuilder::new(engine, guest_wasm("echo")).build().unwrap();
|
||||
|
||||
let rt = Runtime::new(RuntimeConfig::default());
|
||||
let inbox = rt.new_inbox::<ByteMessage>().unwrap();
|
||||
let wasm_addr = rt.spawn(actor).unwrap();
|
||||
|
||||
// Frame with wasm_addr as dest, payload is a framed msg for inbox
|
||||
let inner = framed_msg(inbox.addr(), b"self-bounce");
|
||||
rt.send_to(wasm_addr, framed_msg(&wasm_addr, &inner.0)).unwrap();
|
||||
rt.tick(); // echo sends inner to itself
|
||||
rt.tick(); // processes inner, echoes payload to inbox
|
||||
|
||||
let msg = inbox.try_recv().expect("self-send should eventually reach inbox");
|
||||
assert_eq!(msg.0, b"self-bounce");
|
||||
}
|
||||
|
||||
// ── Guest with i32.rotr/rotl bit rotation ───────────────────────────────────
|
||||
|
||||
#[test]
|
||||
fn guest_uses_bit_rotation() {
|
||||
let wat = r#"
|
||||
(module
|
||||
(import "swactor" "send" (func $send (param i32 i32 i32)))
|
||||
(memory (export "memory") 1)
|
||||
(func (export "alloc") (param i32) (result i32) i32.const 4096)
|
||||
(func (export "handle") (param $ptr i32) (param $len i32)
|
||||
;; Rotate left: 1 << 4 = 16 (i32.rotl(1, 4) = 16)
|
||||
(i32.store8 (i32.const 200)
|
||||
(i32.rotl (i32.const 1) (i32.const 4))
|
||||
)
|
||||
(call $send (local.get $ptr) (i32.const 200) (i32.const 1))
|
||||
)
|
||||
)
|
||||
"#;
|
||||
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 inbox = rt.new_inbox::<ByteMessage>().unwrap();
|
||||
let addr = rt.spawn(actor).unwrap();
|
||||
|
||||
rt.send_to(addr, framed_msg(inbox.addr(), b"rot")).unwrap();
|
||||
rt.tick();
|
||||
|
||||
let msg = inbox.try_recv().unwrap();
|
||||
assert_eq!(msg.0[0], 16, "rotl(1, 4) = 16");
|
||||
}
|
||||
|
||||
// ── Guest with i32.clz/ctz/popcnt ──────────────────────────────────────────
|
||||
|
||||
#[test]
|
||||
fn guest_uses_bit_counting() {
|
||||
let wat = r#"
|
||||
(module
|
||||
(import "swactor" "send" (func $send (param i32 i32 i32)))
|
||||
(memory (export "memory") 1)
|
||||
(func (export "alloc") (param i32) (result i32) i32.const 4096)
|
||||
(func (export "handle") (param $ptr i32) (param $len i32)
|
||||
;; clz(256) = 23 (256 = 0x100, 23 leading zeros in 32-bit)
|
||||
(i32.store8 (i32.const 200) (i32.clz (i32.const 256)))
|
||||
;; ctz(256) = 8 (256 = 0x100, 8 trailing zeros)
|
||||
(i32.store8 (i32.const 201) (i32.ctz (i32.const 256)))
|
||||
;; popcnt(0xFF) = 8 (8 bits set)
|
||||
(i32.store8 (i32.const 202) (i32.popcnt (i32.const 255)))
|
||||
(call $send (local.get $ptr) (i32.const 200) (i32.const 3))
|
||||
)
|
||||
)
|
||||
"#;
|
||||
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 inbox = rt.new_inbox::<ByteMessage>().unwrap();
|
||||
let addr = rt.spawn(actor).unwrap();
|
||||
|
||||
rt.send_to(addr, framed_msg(inbox.addr(), b"bits")).unwrap();
|
||||
rt.tick();
|
||||
|
||||
let msg = inbox.try_recv().unwrap();
|
||||
assert_eq!(msg.0[0], 23, "clz(256) = 23");
|
||||
assert_eq!(msg.0[1], 8, "ctz(256) = 8");
|
||||
assert_eq!(msg.0[2], 8, "popcnt(255) = 8");
|
||||
}
|
||||
|
||||
// ── Spawn 10 actors, stop every other one, remaining still work ─────────────
|
||||
|
||||
#[test]
|
||||
fn stop_every_other_actor_remaining_work() {
|
||||
let engine = SharedEngine::new().unwrap();
|
||||
let rt = Runtime::new(RuntimeConfig::default());
|
||||
let inbox = rt.new_inbox::<ByteMessage>().unwrap();
|
||||
|
||||
let mut addrs = Vec::new();
|
||||
for _ in 0..10 {
|
||||
let actor = WasmActorBuilder::new(engine.clone(), guest_wasm("echo")).build().unwrap();
|
||||
addrs.push(rt.spawn(actor).unwrap());
|
||||
}
|
||||
|
||||
// Stop even-indexed actors
|
||||
for (i, addr) in addrs.iter().enumerate() {
|
||||
if i % 2 == 0 {
|
||||
rt.stop_actor(*addr);
|
||||
}
|
||||
}
|
||||
rt.tick();
|
||||
rt.tick();
|
||||
|
||||
// Send to all — only odd-indexed should respond
|
||||
for (i, addr) in addrs.iter().enumerate() {
|
||||
rt.send_to(*addr, framed_msg(inbox.addr(), &[i as u8])).ok();
|
||||
}
|
||||
rt.tick();
|
||||
|
||||
let mut received = Vec::new();
|
||||
while let Some(msg) = inbox.try_recv() {
|
||||
received.push(msg.0[0]);
|
||||
}
|
||||
received.sort();
|
||||
assert_eq!(received, vec![1, 3, 5, 7, 9], "only odd-indexed actors should respond");
|
||||
}
|
||||
Loading…
Reference in a new issue