Files
qinglong/packages/ql3-runtime-core/test/clusterControlRecovery.test.cjs

71 lines
1.9 KiB
JavaScript

const assert = require('node:assert/strict');
const { test } = require('node:test');
const {
ClusterControlRecoveryConvergenceVerifier,
MAX_CLUSTER_CONTROL_RECOVERY_PAGE_SIZE,
} = require('../dist');
test('proves convergence with one bounded recovery-source read', async () => {
const limits = [];
const verifier = new ClusterControlRecoveryConvergenceVerifier({
async listOutstanding(limit) {
limits.push(limit);
return { observedAtMs: 123, candidates: [], hasMore: false };
},
});
assert.deepEqual(await verifier.verify(), {
safe: true,
remaining: 0,
failed: 0,
});
assert.deepEqual(limits, [1]);
assert.equal(MAX_CLUSTER_CONTROL_RECOVERY_PAGE_SIZE, 128);
});
test('fails closed with a lower-bound remaining count', async () => {
const verifier = new ClusterControlRecoveryConvergenceVerifier({
async listOutstanding() {
return {
observedAtMs: 123,
candidates: [
{
kind: 'run',
id: 'run-1',
runId: 'run-1',
status: 'running',
createdAtMs: 1,
},
],
hasMore: true,
};
},
});
assert.deepEqual(await verifier.verify(), {
safe: false,
remaining: 2,
failed: 0,
});
});
test('rejects an internally inconsistent recovery page', async () => {
const verifier = new ClusterControlRecoveryConvergenceVerifier({
async listOutstanding() {
return { observedAtMs: 123, candidates: [], hasMore: true };
},
});
await assert.rejects(verifier.verify(), /hasMore without a candidate/);
});
test('rejects an invalid durable-source observation', async () => {
const verifier = new ClusterControlRecoveryConvergenceVerifier({
async listOutstanding() {
return { observedAtMs: Number.NaN, candidates: [], hasMore: false };
},
});
await assert.rejects(verifier.verify(), /observation is invalid/);
});