import { WasmRuntime, WasmAddr, spawn_counter, spawn_relay, } from "./pkg/wasm.js"; let passed = 0; let failed = 0; function assert(cond, msg) { if (!cond) { console.error(` FAIL: ${msg}`); failed++; } else { passed++; } } function assertEq(a, b, msg) { const aj = JSON.stringify(a); const bj = JSON.stringify(b); if (aj !== bj) { console.error(` FAIL: ${msg} (got ${aj}, expected ${bj})`); failed++; } else { passed++; } } function drainInbox(inbox) { const results = []; let v; while ((v = inbox.try_recv()) !== undefined) results.push(v); return results; } // ---- accumulator ---------------------------------------------------------- { console.log("test: accumulator processes messages via WasmAddr"); const rt = new WasmRuntime(); const inbox = rt.new_inbox_u32(); const c = spawn_counter(rt, inbox.addr()); rt.send_u32(c, 1); rt.send_u32(c, 2); rt.send_u32(c, 10); rt.tick(); assertEq(drainInbox(inbox), [1, 3, 13], "running totals"); inbox.free(); rt.free(); } // ---- relay ---------------------------------------------------------------- { console.log("test: relay forwards to counter"); const rt = new WasmRuntime(); const inbox = rt.new_inbox_u32(); const c = spawn_counter(rt, inbox.addr()); const r = spawn_relay(rt, c); rt.send_u32(r, 5); rt.send_u32(r, 7); // tick 1: relay receives and forwards (same worker → pending_local) // tick 2: counter receives forwarded messages rt.tick(); rt.tick(); assertEq(drainInbox(inbox), [5, 12], "relayed totals"); inbox.free(); rt.free(); } // ---- multiple counters ---------------------------------------------------- { console.log("test: multiple independent counters"); const rt = new WasmRuntime(); const inbox = rt.new_inbox_u32(); const a = spawn_counter(rt, inbox.addr()); const b = spawn_counter(rt, inbox.addr()); rt.send_u32(a, 10); rt.send_u32(b, 100); rt.tick(); const results = drainInbox(inbox); assert( results.includes(10) && results.includes(100) && results.length === 2, "both counters report" ); inbox.free(); rt.free(); } // ---- actor_count ---------------------------------------------------------- { console.log("test: actor_count tracks spawns"); const rt = new WasmRuntime(); const inbox = rt.new_inbox_u32(); spawn_counter(rt, inbox.addr()); spawn_counter(rt, inbox.addr()); spawn_counter(rt, inbox.addr()); rt.tick(); // drain spawn queue assertEq(rt.actor_count(), 3, "three actors"); inbox.free(); rt.free(); } // ---- WasmAddr toString ---------------------------------------------------- { console.log("test: WasmAddr has string representation"); const rt = new WasmRuntime(); const inbox = rt.new_inbox_u32(); const addr = spawn_counter(rt, inbox.addr()); const s = addr.toString(); // no_random generates deterministic addresses — just check it's a non-empty hex string assert(typeof s === "string" && s.length > 0, "addr toString is non-empty string"); inbox.free(); rt.free(); } // ---- stop_actor ----------------------------------------------------------- { console.log("test: stop_actor removes actor"); const rt = new WasmRuntime(); const inbox = rt.new_inbox_u32(); const c = spawn_counter(rt, inbox.addr()); rt.tick(); // drain spawn assertEq(rt.actor_count(), 1, "one actor before stop"); rt.stop_actor(c); rt.tick(); // process stop + cleanup assertEq(rt.actor_count(), 0, "zero actors after stop"); inbox.free(); rt.free(); } // ---- bytes inbox ---------------------------------------------------------- { console.log("test: byte inbox receives Uint8Array"); const rt = new WasmRuntime(); const inbox = rt.new_inbox_bytes(); // Send bytes directly (no actor — just to the inbox address) rt.send_bytes(inbox.addr(), new Uint8Array([1, 2, 3])); rt.tick(); const result = inbox.try_recv(); assert(result instanceof Uint8Array, "result is Uint8Array"); assertEq(Array.from(result), [1, 2, 3], "bytes match"); inbox.free(); rt.free(); } // ---- uptime --------------------------------------------------------------- { console.log("test: uptime_ms returns a number"); const rt = new WasmRuntime(); const uptime = rt.uptime_ms(); assert(typeof uptime === "number" && uptime >= 0, "uptime is non-negative number"); rt.free(); } // ---- results -------------------------------------------------------------- console.log(`\n${passed} passed, ${failed} failed`); if (failed > 0) process.exit(1);