Files
kuber/tests/server/build-reconciler.test.ts

104 lines
2.9 KiB
TypeScript

import { describe, expect, test } from "bun:test";
import {
BackgroundBuildReconciler,
DEFAULT_BUILD_RECONCILE_MS,
DEFAULT_BUILD_RECONCILE_TIMEOUT_MS,
MAX_BUILD_RECONCILE_TIMEOUT_MS,
MAX_BUILD_RECONCILE_MS,
buildReconcileIntervalMs,
buildReconcileTimeoutMs,
} from "../../server/build-reconciler";
describe("build reconciliation interval", () => {
test("uses positive finite configured intervals and defaults invalid values", () => {
expect(buildReconcileIntervalMs("1500")).toBe(1500);
expect(buildReconcileIntervalMs(String(MAX_BUILD_RECONCILE_MS))).toBe(
MAX_BUILD_RECONCILE_MS,
);
for (const value of [
undefined,
"",
"0",
"-1",
"Infinity",
"nope",
String(MAX_BUILD_RECONCILE_MS + 1),
])
expect(buildReconcileIntervalMs(value)).toBe(DEFAULT_BUILD_RECONCILE_MS);
});
});
describe("background build reconciliation", () => {
test("does not overlap a timed-out scan and resumes after it settles", async () => {
const scans: AbortSignal[] = [];
let expire!: () => void;
let releaseFirst!: () => void;
let firstSettled!: () => void;
const firstReleased = new Promise<void>((resolve) => {
releaseFirst = resolve;
});
const settled = new Promise<void>((resolve) => {
firstSettled = resolve;
});
const failures: unknown[] = [];
const reconciler = new BackgroundBuildReconciler({
runner: {
reconcilePendingBuilds: async ({ signal } = {}) => {
scans.push(signal!);
if (scans.length === 1) {
await firstReleased;
firstSettled();
}
},
},
timeoutMs: 100,
onFailure: (error) => failures.push(error),
setTimeout: ((callback: () => void) => {
expire = callback;
return 0 as unknown as ReturnType<typeof setTimeout>;
}) as typeof setTimeout,
clearTimeout: (() => {}) as typeof clearTimeout,
});
reconciler.tick();
reconciler.tick();
expect(scans).toHaveLength(1);
expire();
expect(scans[0]!.aborted).toBe(true);
reconciler.tick();
await Promise.resolve();
expect(scans).toHaveLength(1);
expect(failures).toHaveLength(1);
releaseFirst();
await settled;
await Promise.resolve();
await Promise.resolve();
reconciler.tick();
await Promise.resolve();
expect(scans).toHaveLength(2);
});
test("uses positive finite configured timeouts and defaults invalid values", () => {
expect(buildReconcileTimeoutMs("1500")).toBe(1500);
expect(
buildReconcileTimeoutMs(String(MAX_BUILD_RECONCILE_TIMEOUT_MS)),
).toBe(MAX_BUILD_RECONCILE_TIMEOUT_MS);
for (const value of [
undefined,
"",
"0",
"-1",
"Infinity",
"nope",
String(MAX_BUILD_RECONCILE_TIMEOUT_MS + 1),
])
expect(buildReconcileTimeoutMs(value)).toBe(
DEFAULT_BUILD_RECONCILE_TIMEOUT_MS,
);
});
});