test: Cycle 52 — shift ops, bitwise AND/OR, echo+double coexist, i16 load
- guest_uses_shift_operations: i32.shl and i32.shr_u bit shifts - guest_uses_bitwise_and_or: i32.and (0xFF & 0x0F) and i32.or (0xF0 | 0x0F) - echo_and_double_coexist_same_worker: different guest types on same runtime - guest_reads_i16_from_payload: i32.load16_u reads little-endian 16-bit value All 224 tests pass. No new bugs found. Authored by Claude, lovingly guided by Zachery Aaron Shores-Chmielewski
This commit is contained in:
parent
372c0bbf9e
commit
af5e0644bc
1 changed files with 145 additions and 0 deletions
|
|
@ -7769,3 +7769,148 @@ fn byte_message_various_constructors() {
|
|||
let msg3 = ByteMessage(vec![0; 1024]);
|
||||
assert_eq!(msg3.0.len(), 1024);
|
||||
}
|
||||
|
||||
// ── Guest with i32.shl/shr_u shift operations ─────────────────────────────
|
||||
|
||||
#[test]
|
||||
fn guest_uses_shift_operations() {
|
||||
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)
|
||||
;; Read first payload byte, shift left by 1, store result
|
||||
(i32.store8 (i32.const 200)
|
||||
(i32.shl
|
||||
(i32.load8_u (i32.add (local.get $ptr) (i32.const 32)))
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
;; Read second payload byte, shift right by 2
|
||||
(i32.store8 (i32.const 201)
|
||||
(i32.shr_u
|
||||
(i32.load8_u (i32.add (local.get $ptr) (i32.const 33)))
|
||||
(i32.const 2)
|
||||
)
|
||||
)
|
||||
(call $send (local.get $ptr) (i32.const 200) (i32.const 2))
|
||||
)
|
||||
)
|
||||
"#;
|
||||
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(), &[5, 100])).unwrap();
|
||||
rt.tick();
|
||||
|
||||
let msg = inbox.try_recv().unwrap();
|
||||
assert_eq!(msg.0[0], 10, "5 << 1 = 10");
|
||||
assert_eq!(msg.0[1], 25, "100 >> 2 = 25");
|
||||
}
|
||||
|
||||
// ── Guest with i32.and/or for masking ──────────────────────────────────────
|
||||
|
||||
#[test]
|
||||
fn guest_uses_bitwise_and_or() {
|
||||
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)
|
||||
;; AND: 0xFF & 0x0F = 0x0F
|
||||
(i32.store8 (i32.const 200) (i32.and (i32.const 0xFF) (i32.const 0x0F)))
|
||||
;; OR: 0xF0 | 0x0F = 0xFF
|
||||
(i32.store8 (i32.const 201) (i32.or (i32.const 0xF0) (i32.const 0x0F)))
|
||||
(call $send (local.get $ptr) (i32.const 200) (i32.const 2))
|
||||
)
|
||||
)
|
||||
"#;
|
||||
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"mask")).unwrap();
|
||||
rt.tick();
|
||||
|
||||
let msg = inbox.try_recv().unwrap();
|
||||
assert_eq!(msg.0[0], 0x0F, "0xFF & 0x0F = 0x0F");
|
||||
assert_eq!(msg.0[1], 0xFF, "0xF0 | 0x0F = 0xFF");
|
||||
}
|
||||
|
||||
// ── Two WASM actors with different guest modules on same worker ─────────────
|
||||
|
||||
#[test]
|
||||
fn echo_and_double_coexist_same_worker() {
|
||||
let engine = SharedEngine::new().unwrap();
|
||||
let echo = WasmActorBuilder::new(engine.clone(), guest_wasm("echo")).build().unwrap();
|
||||
let double = WasmActorBuilder::new(engine, guest_wasm("double")).build().unwrap();
|
||||
|
||||
let rt = Runtime::new(RuntimeConfig::default());
|
||||
let inbox = rt.new_inbox::<ByteMessage>().unwrap();
|
||||
let e_addr = rt.spawn(echo).unwrap();
|
||||
let d_addr = rt.spawn(double).unwrap();
|
||||
|
||||
rt.send_to(e_addr, framed_msg(inbox.addr(), b"E")).unwrap();
|
||||
rt.send_to(d_addr, framed_msg(inbox.addr(), b"D")).unwrap();
|
||||
rt.tick();
|
||||
|
||||
let mut msgs: Vec<Vec<u8>> = Vec::new();
|
||||
while let Some(msg) = inbox.try_recv() {
|
||||
msgs.push(msg.0);
|
||||
}
|
||||
msgs.sort();
|
||||
// Echo: "E" (1x), Double: "D" (2x)
|
||||
assert_eq!(msgs, vec![b"D".to_vec(), b"D".to_vec(), b"E".to_vec()]);
|
||||
}
|
||||
|
||||
// ── Guest reads i16 from payload (i32.load16_u) ────────────────────────────
|
||||
|
||||
#[test]
|
||||
fn guest_reads_i16_from_payload() {
|
||||
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)
|
||||
;; Read 2-byte LE value from first payload bytes
|
||||
(local $val i32)
|
||||
(local.set $val
|
||||
(i32.load16_u (i32.add (local.get $ptr) (i32.const 32)))
|
||||
)
|
||||
;; Store low byte of the i16 value
|
||||
(i32.store8 (i32.const 200) (local.get $val))
|
||||
;; Store high byte
|
||||
(i32.store8 (i32.const 201) (i32.shr_u (local.get $val) (i32.const 8)))
|
||||
(call $send (local.get $ptr) (i32.const 200) (i32.const 2))
|
||||
)
|
||||
)
|
||||
"#;
|
||||
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();
|
||||
|
||||
// Send 0x0102 as little-endian: [0x02, 0x01]
|
||||
rt.send_to(addr, framed_msg(inbox.addr(), &[0x02, 0x01])).unwrap();
|
||||
rt.tick();
|
||||
|
||||
let msg = inbox.try_recv().unwrap();
|
||||
// i32.load16_u reads LE: 0x0102
|
||||
assert_eq!(msg.0[0], 0x02, "low byte of 0x0102");
|
||||
assert_eq!(msg.0[1], 0x01, "high byte of 0x0102");
|
||||
}
|
||||
Loading…
Reference in a new issue