Files
radicle-explorer/tests/unit/mutexExecutor.test.ts

121 lines
2.9 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { describe, expect, test, vi } from "vitest";
import * as mutexExecutor from "@app/lib/mutexExecutor";
import { sleep } from "@app/lib/sleep";
describe("executor", () => {
test("cancels running task", async () => {
const e = mutexExecutor.create();
const first = e.run(async () => {
await sleep(10);
return "first";
});
const second = e.run(async () => {
return "second";
});
expect(await first).toBe(undefined);
expect(await second).toBe("second");
const third = e.run(async () => {
await sleep(10);
return "third";
});
const fourth = e.run(async () => {
return "fourth";
});
expect(await third).toBe(undefined);
expect(await fourth).toBe("fourth");
});
test("cancels multiple tasks", async () => {
const e = mutexExecutor.create();
const canceled1 = e.run(async () => {
await sleep(10);
return true;
});
const canceled2 = e.run(async () => {
await sleep(10);
return true;
});
const canceled3 = e.run(async () => {
await sleep(10);
return true;
});
const last = e.run(async () => {
return true;
});
expect(await canceled1).toBe(undefined);
expect(await canceled2).toBe(undefined);
expect(await canceled3).toBe(undefined);
expect(await last).toBe(true);
});
test("triggers abort signal event", async () => {
const e = mutexExecutor.create();
const abortListener = vi.fn();
void e.run(async abort => {
abort.addEventListener("abort", abortListener);
await sleep(10);
return "first";
});
expect(abortListener).not.toHaveBeenCalled();
// eslint-disable-next-line @typescript-eslint/no-empty-function
void e.run(async () => {});
expect(abortListener).toHaveBeenCalled();
});
test("don’t throw error on aborted task", async () => {
const e = mutexExecutor.create();
const first = e.run(async () => {
await sleep(10);
throw new Error();
});
const second = e.run(async () => {
return "second";
});
expect(await first).toBe(undefined);
expect(await second).toBe("second");
});
});
describe("worker", () => {
test("sequential work", async () => {
const w = mutexExecutor.createWorker(async (value: number) => {
await sleep(10);
return value;
});
const outputs: number[] = [];
w.output.onValue(value => outputs.push(value));
await w.submit(1);
await w.submit(2);
await w.submit(3);
expect(outputs).toEqual([1, 2, 3]);
});
test("overlapping work cancels", async () => {
const w = mutexExecutor.createWorker(async (value: number) => {
await sleep(10);
return value;
});
const nextOutput = w.output.firstToPromise();
void w.submit(1);
void w.submit(2);
void w.submit(3);
expect(await nextOutput).toEqual(3);
});
});