89 lines
2.4 KiB
TypeScript
89 lines
2.4 KiB
TypeScript
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
|
|
const diagnosticMocks = vi.hoisted(() => ({
|
|
logLaneEnqueue: vi.fn(),
|
|
logLaneDequeue: vi.fn(),
|
|
diag: {
|
|
debug: vi.fn(),
|
|
warn: vi.fn(),
|
|
error: vi.fn(),
|
|
},
|
|
}));
|
|
|
|
vi.mock("../logging/diagnostic.js", () => ({
|
|
logLaneEnqueue: diagnosticMocks.logLaneEnqueue,
|
|
logLaneDequeue: diagnosticMocks.logLaneDequeue,
|
|
diagnosticLogger: diagnosticMocks.diag,
|
|
}));
|
|
|
|
import { enqueueCommand, getQueueSize } from "./command-queue.js";
|
|
|
|
describe("command queue", () => {
|
|
beforeEach(() => {
|
|
diagnosticMocks.logLaneEnqueue.mockClear();
|
|
diagnosticMocks.logLaneDequeue.mockClear();
|
|
diagnosticMocks.diag.debug.mockClear();
|
|
diagnosticMocks.diag.warn.mockClear();
|
|
diagnosticMocks.diag.error.mockClear();
|
|
});
|
|
|
|
it("runs tasks one at a time in order", async () => {
|
|
let active = 0;
|
|
let maxActive = 0;
|
|
const calls: number[] = [];
|
|
|
|
const makeTask = (id: number) => async () => {
|
|
active += 1;
|
|
maxActive = Math.max(maxActive, active);
|
|
calls.push(id);
|
|
await new Promise((resolve) => setTimeout(resolve, 15));
|
|
active -= 1;
|
|
return id;
|
|
};
|
|
|
|
const results = await Promise.all([
|
|
enqueueCommand(makeTask(1)),
|
|
enqueueCommand(makeTask(2)),
|
|
enqueueCommand(makeTask(3)),
|
|
]);
|
|
|
|
expect(results).toEqual([1, 2, 3]);
|
|
expect(calls).toEqual([1, 2, 3]);
|
|
expect(maxActive).toBe(1);
|
|
expect(getQueueSize()).toBe(0);
|
|
});
|
|
|
|
it("logs enqueue depth after push", async () => {
|
|
const task = enqueueCommand(async () => {});
|
|
|
|
expect(diagnosticMocks.logLaneEnqueue).toHaveBeenCalledTimes(1);
|
|
expect(diagnosticMocks.logLaneEnqueue.mock.calls[0]?.[1]).toBe(1);
|
|
|
|
await task;
|
|
});
|
|
|
|
it("invokes onWait callback when a task waits past the threshold", async () => {
|
|
let waited: number | null = null;
|
|
let queuedAhead: number | null = null;
|
|
|
|
// First task holds the queue long enough to trigger wait notice.
|
|
const first = enqueueCommand(async () => {
|
|
await new Promise((resolve) => setTimeout(resolve, 30));
|
|
});
|
|
|
|
const second = enqueueCommand(async () => {}, {
|
|
warnAfterMs: 5,
|
|
onWait: (ms, ahead) => {
|
|
waited = ms;
|
|
queuedAhead = ahead;
|
|
},
|
|
});
|
|
|
|
await Promise.all([first, second]);
|
|
|
|
expect(waited).not.toBeNull();
|
|
expect(waited as number).toBeGreaterThanOrEqual(5);
|
|
expect(queuedAhead).toBe(0);
|
|
});
|
|
});
|