Skip to content

Commit e4938ea

Browse files
committed
test(lock.manager): Fix property test timing edge cases
- Increase minimum lockTimeoutMs arbitrary from 1 to 100ms to avoid race conditions with very small timeout values - Replace lockTimeoutMs - delta calculation with Math.min(delta, Math.floor(lockTimeoutMs / 2)) to guarantee lock age stays well within timeout window - Add clarifying comments explaining why lockTimeoutMs / 2 is used to prevent Date.now() drift between test setup and isTimedOut() check from causing flaky failures - Apply timing fix consistently across both non-stale detection test cases (standard and CI environments)
1 parent 9eea9db commit e4938ea

1 file changed

Lines changed: 10 additions & 3 deletions

File tree

__tests__/properties/lock.manager.property.test.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ const createLockManager = lockManagerMod.exports.createLockManager as
112112
typeof import('../../src/core/lock.manager').createLockManager;
113113

114114
/** Arbitrary for lockTimeoutMs (positive integer, reasonable range) */
115-
const arbLockTimeoutMs = fc.integer({ min: 1, max: 600_000 });
115+
const arbLockTimeoutMs = fc.integer({ min: 100, max: 600_000 });
116116

117117
/** Arbitrary for a positive time delta in ms */
118118
const arbPositiveDelta = fc.integer({ min: 50, max: 300_000 });
@@ -229,8 +229,11 @@ describe('Feature: operational-hardening, Property 8: Stale Detection по timeo
229229
arbPositiveDelta,
230230
(pid, operationId, command, hostname, lockTimeoutMs, delta) => {
231231
// createdAt is recent enough that timeout is NOT exceeded
232+
// Use lockTimeoutMs / 2 as the age to guarantee the lock is well within the timeout
233+
// window, avoiding race conditions with very small lockTimeoutMs values.
232234
const now = Date.now();
233-
const createdAtMs = now - Math.max(0, lockTimeoutMs - delta); // guarantees now - createdAt < lockTimeoutMs
235+
const age = Math.min(delta, Math.floor(lockTimeoutMs / 2));
236+
const createdAtMs = now - age;
234237
const createdAt = new Date(createdAtMs).toISOString();
235238

236239
const lockData: LockData = { pid, operationId, command, createdAt, hostname, ci: false };
@@ -350,8 +353,12 @@ describe('Feature: operational-hardening, Property 8: Stale Detection по timeo
350353
arbPositiveDelta,
351354
(pid, operationId, command, hostname, lockTimeoutMs, delta) => {
352355
// Non-stale case in CI — timeout NOT exceeded
356+
// Use lockTimeoutMs / 2 as the age to guarantee the lock is well within the timeout
357+
// window, avoiding race conditions with very small lockTimeoutMs values where
358+
// Date.now() drift between test setup and isTimedOut() check could push age past timeout.
353359
const now = Date.now();
354-
const createdAtMs = now - Math.max(0, lockTimeoutMs - delta);
360+
const age = Math.min(delta, Math.floor(lockTimeoutMs / 2));
361+
const createdAtMs = now - age;
355362
const createdAt = new Date(createdAtMs).toISOString();
356363

357364
const lockData: LockData = { pid, operationId, command, createdAt, hostname, ci: true };

0 commit comments

Comments
 (0)