UNPKG

@nostr-fetch/kernel

Version:
144 lines (121 loc) 3.4 kB
import { setTimeout as wait } from "node:timers/promises"; import { inspect } from "node:util"; import { describe, expect, test } from "vitest"; import { Channel } from "./channel"; describe("channel", () => { test.concurrent("convey message (receiver is faster)", async () => { const [tx, chIter] = Channel.make<number>(); let n = 0; const i = setInterval(() => { if (n >= 10) { tx.close(); clearInterval(i); return; } tx.send(n); n++; }, 100); const res = []; for await (const d of chIter) { res.push(d); } expect(res).toEqual([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); }); test.concurrent("convey message (sender is faster)", async () => { const [tx, chIter] = Channel.make<number>(); let n = 0; const i = setInterval(() => { if (n >= 10) { tx.close(); clearInterval(i); return; } tx.send(n); n++; }, 0); const res = []; for await (const d of chIter) { res.push(d); await wait(100); } expect(res).toEqual([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); }); test.concurrent("convey error and it interrupts receiver", async () => { const [tx, chIter] = Channel.make<number>(); let n = 0; const i = setInterval(() => { if (n === 5) { tx.error("rejects 5!"); return; } if (n >= 10) { tx.close(); clearInterval(i); return; } tx.send(n); n++; }, 0); await expect(async () => { const res = []; for await (const d of chIter) { res.push(d); } return res; }).rejects.toThrow("rejects 5!"); }); test.concurrent("can't be iterated multiple times", async () => { const [tx, chIter] = Channel.make<number>(); let n = 0; const i = setInterval(() => { if (n >= 10) { tx.close(); clearInterval(i); return; } tx.send(n); n++; }, 100); const res = []; const iterate = async (iter: AsyncIterable<number>) => { for await (const n of iter) { res.push(n); } }; await expect(async () => { await Promise.all([iterate(chIter), iterate(chIter)]); }).rejects.toThrow("Iterating a single channel in multiple location is not allowed"); }); test.concurrent("backpressure", async () => { const [tx, chIter] = Channel.make<number>({ highWaterMark: 3 }); for (const n of [0, 1, 2, 3]) { tx.send(n); } tx.close(); // check if `wait` is pending const wait1 = tx.waitUntilDrained(); const wait2 = tx.waitUntilDrained(); [wait1, wait2].forEach((w) => { expect(inspect(w).includes("pending")).toBe(true); }); const res = []; // drain first item -> sendQ is now drained enough const iterBody = chIter[Symbol.asyncIterator](); const fst = await iterBody.next(); res.push(fst.value); // check if `wait` have been resolved [wait1, wait2].forEach((w) => { expect(inspect(w).includes("pending")).toBe(false); }); await expect(Promise.all([wait1, wait2])).resolves.toEqual([undefined, undefined]); // drain remaining items while (true) { const { done, value } = await iterBody.next(); if (done) { break; } res.push(value); } expect(res).toEqual([0, 1, 2, 3]); }); });