Files
2026-05-27 23:47:53 +01:00

104 lines
3.7 KiB
TypeScript

import { describe, expect, it } from "@suaveplan/testing/runner";
import fc from "fast-check";
import { JobQueue } from "../src/queue/job-queue.js";
describe("property: JobQueue monotonic dequeue", () => {
it("always returns entries in non-decreasing runAt order", {
timeout: 30_000,
}, () => {
fc.assert(
fc.property(
fc.array(
fc.record({
jobId: fc.string({ minLength: 1, maxLength: 8 }),
runAt: fc.integer({ min: 0, max: 1_000_000 }),
}),
{ minLength: 0, maxLength: 200 }
),
(entries) => {
const q = new JobQueue();
for (let i = 0; i < entries.length; i++) {
const e = entries[i] as {
jobId: string;
runAt: number;
};
q.enqueue({
jobId: `${e.jobId}-${i}`,
runAt: e.runAt,
});
}
let prev = Number.NEGATIVE_INFINITY;
while (q.size() > 0) {
const out = q.dequeue();
if (out === undefined) break;
expect(out.runAt).toBeGreaterThanOrEqual(prev);
prev = out.runAt;
}
}
),
{ numRuns: 100 }
);
});
});
describe("property: enqueue+remove leaves consistent heap", () => {
it("after removing every inserted id, queue is empty", {
timeout: 30_000,
}, () => {
fc.assert(
fc.property(
fc.array(
fc.record({
jobId: fc.uuid(),
runAt: fc.integer({ min: 0, max: 1_000_000 }),
}),
{ minLength: 0, maxLength: 100 }
),
(entries) => {
const q = new JobQueue();
const ids = new Set<string>();
for (const e of entries) {
if (ids.has(e.jobId)) continue;
ids.add(e.jobId);
q.enqueue({ jobId: e.jobId, runAt: e.runAt });
}
for (const id of ids) {
expect(q.remove(id)).toBe(true);
}
expect(q.size()).toBe(0);
expect(q.peek()).toBeUndefined();
}
),
{ numRuns: 100 }
);
});
});
describe("property: enqueue followed by N dequeues equals sorted input", () => {
it("produces a sorted output prefix", { timeout: 30_000 }, () => {
fc.assert(
fc.property(
fc.array(fc.integer({ min: 0, max: 1_000_000 }), {
minLength: 1,
maxLength: 50,
}),
(runAts) => {
const q = new JobQueue();
runAts.forEach((runAt, i) => {
q.enqueue({ jobId: `j-${i}`, runAt });
});
const got: number[] = [];
while (q.size() > 0) {
const e = q.dequeue();
if (e === undefined) break;
got.push(e.runAt);
}
const expected = [...runAts].sort((a, b) => a - b);
expect(got).toEqual(expected);
}
),
{ numRuns: 100 }
);
});
});