Skip to content

Commit c2980fa

Browse files
committed
test: bound deadline keepalive harness
1 parent 90cea43 commit c2980fa

1 file changed

Lines changed: 13 additions & 5 deletions

File tree

tests/zcode-client.test.mjs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,11 @@ test('CI timeout multiplier is bounded and defaults to one', () => {
3030
assert.equal(scaleTestTimeout(500, { ZCODE_TEST_TIMEOUT_MULTIPLIER: '3' }), 1_500);
3131
});
3232

33-
async function withTestDeadlineKeepalive(operation) {
34-
const keepalive = setInterval(() => {}, 1_000);
35-
try { return await operation(); } finally { clearInterval(keepalive); }
33+
async function withTestDeadlineKeepalive(operation, timeoutMs = 2_000) {
34+
/** @type {NodeJS.Timeout|undefined} */ let guard;
35+
try {
36+
return await Promise.race([operation(), new Promise((_, rejectPromise) => { guard = setTimeout(() => rejectPromise(new Error('test deadline keepalive timed out')), timeoutMs); })]);
37+
} finally { clearTimeout(guard); }
3638
}
3739

3840
async function boundedTestPromise(promise, label, timeoutMs = 1_000) {
@@ -46,6 +48,10 @@ async function boundedTestPromise(promise, label, timeoutMs = 1_000) {
4648
} finally { clearTimeout(timer); }
4749
}
4850

51+
test('test deadline keepalive bounds an operation that never settles', { timeout: scaleTestTimeout(500) }, async () => {
52+
await assert.rejects(withTestDeadlineKeepalive(() => new Promise(() => {}), scaleTestTimeout(50)), /test deadline keepalive timed out/u);
53+
});
54+
4955
async function compactBrokerTemp() {
5056
const base = process.platform === 'win32' ? tmpdir() : realpathSync('/tmp');
5157
const directory = await mkdtemp(join(base, 'zb-'));
@@ -1816,8 +1822,10 @@ test('owner release aborts its unlocked winner read after a reset compensation m
18161822
if (cleanupErrors.length > 1) throw new AggregateError(cleanupErrors, `owner release cleanup failed: caller residual=${releaseOutcome ? (releaseOutcomeSettled ? 'settled' : 'pending') : 'not-started'}; task residual=${broker.releaseTasks.size}`);
18171823
});
18181824
const releasing = broker.releaseOwner(socket, ownerId, [], Date.now() + scaleTestTimeout(1_000)); releaseOutcome = releasing.then((value) => ({ kind: 'fulfilled', value }), (error) => ({ kind: 'rejected', error })); void releaseOutcome.then(() => { releaseOutcomeSettled = true; });
1819-
const boundary = await Promise.race([secondWriteEntered.then(() => 'second-write'), releaseOutcome.then(() => 'release-settled')]); assert.equal(boundary, 'second-write'); assert.equal(writes, 2);
1820-
await withTestDeadlineKeepalive(() => assert.rejects(releasing, { code: 'ZCODE_OWNER_RELEASE_TIMEOUT' }));
1825+
await withTestDeadlineKeepalive(async () => {
1826+
const boundary = await Promise.race([secondWriteEntered.then(() => 'second-write'), releaseOutcome.then(() => 'release-settled')]); assert.equal(boundary, 'second-write'); assert.equal(writes, 2);
1827+
await assert.rejects(releasing, { code: 'ZCODE_OWNER_RELEASE_TIMEOUT' });
1828+
}, scaleTestTimeout(2_000));
18211829
for (let turn = 0; turn < 100 && broker.releaseTasks.size; turn += 1) await new Promise((resolvePromise) => setImmediate(resolvePromise));
18221830
assert.equal(broker.releaseTasks.size, 0);
18231831
assert.equal(observedSignal?.aborted, true); assert.equal(observedSignal, compensationSignal); assert.equal(broker.sessionOwners.get(sessionId)?.ownerId, ownerId); assert.equal(broker.sessionOwners.get(siblingId)?.ownerId, ownerId); assert.equal(broker.uncertainOwnerReleases.get(sessionId), ownerId); assert.equal(broker.uncertainOwnerReleases.get(siblingId), ownerId); assert.equal(broker.stoppingSessions.has(sessionId), false); assert.equal(broker.stoppingSessions.has(siblingId), false);

0 commit comments

Comments
 (0)