mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-08 00:19:42 +02:00
test: de-flake StaleExpirationMap age/TTL timing assertions for CI
The new CI test gate surfaced a pre-existing flaky timing test: 'should return age of entry' asserted age>=50 after a 50ms setTimeout and measured 49ms on a jittery CI runner. Widened the elapsed-time windows (age >=40/<500; remaining TTL >700/<=960) so they tolerate timer jitter. Pre-existing flakiness, unrelated to the API migration. (File was also normalized by prettier per the pre-commit hook.) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -79,7 +79,7 @@ describe('StaleExpirationMap', () => {
|
|||||||
expect(map.get('a')).toBe(1);
|
expect(map.get('a')).toBe(1);
|
||||||
|
|
||||||
// Wait for expiration
|
// Wait for expiration
|
||||||
await new Promise(r => setTimeout(r, 150));
|
await new Promise((r) => setTimeout(r, 150));
|
||||||
|
|
||||||
expect(map.get('a')).toBeUndefined();
|
expect(map.get('a')).toBeUndefined();
|
||||||
expect(map.has('a')).toBe(false);
|
expect(map.has('a')).toBe(false);
|
||||||
@@ -99,7 +99,7 @@ describe('StaleExpirationMap', () => {
|
|||||||
map.set('b', 2);
|
map.set('b', 2);
|
||||||
|
|
||||||
// Wait for cleanup
|
// Wait for cleanup
|
||||||
await new Promise(r => setTimeout(r, 200));
|
await new Promise((r) => setTimeout(r, 200));
|
||||||
|
|
||||||
expect(expired).toContainEqual(['a', 1]);
|
expect(expired).toContainEqual(['a', 1]);
|
||||||
expect(expired).toContainEqual(['b', 2]);
|
expect(expired).toContainEqual(['b', 2]);
|
||||||
@@ -117,11 +117,11 @@ describe('StaleExpirationMap', () => {
|
|||||||
map.set('a', 1);
|
map.set('a', 1);
|
||||||
|
|
||||||
// Access at 75ms (halfway through TTL)
|
// Access at 75ms (halfway through TTL)
|
||||||
await new Promise(r => setTimeout(r, 75));
|
await new Promise((r) => setTimeout(r, 75));
|
||||||
expect(map.get('a')).toBe(1); // This refreshes TTL
|
expect(map.get('a')).toBe(1); // This refreshes TTL
|
||||||
|
|
||||||
// Wait another 100ms (entry should still be valid because TTL was refreshed)
|
// Wait another 100ms (entry should still be valid because TTL was refreshed)
|
||||||
await new Promise(r => setTimeout(r, 100));
|
await new Promise((r) => setTimeout(r, 100));
|
||||||
expect(map.get('a')).toBe(1);
|
expect(map.get('a')).toBe(1);
|
||||||
|
|
||||||
map.dispose();
|
map.dispose();
|
||||||
@@ -137,11 +137,11 @@ describe('StaleExpirationMap', () => {
|
|||||||
map.set('a', 1);
|
map.set('a', 1);
|
||||||
|
|
||||||
// Access at 50ms
|
// Access at 50ms
|
||||||
await new Promise(r => setTimeout(r, 50));
|
await new Promise((r) => setTimeout(r, 50));
|
||||||
expect(map.get('a')).toBe(1); // Does NOT refresh TTL
|
expect(map.get('a')).toBe(1); // Does NOT refresh TTL
|
||||||
|
|
||||||
// Wait another 75ms (entry should be expired)
|
// Wait another 75ms (entry should be expired)
|
||||||
await new Promise(r => setTimeout(r, 75));
|
await new Promise((r) => setTimeout(r, 75));
|
||||||
expect(map.get('a')).toBeUndefined();
|
expect(map.get('a')).toBeUndefined();
|
||||||
|
|
||||||
map.dispose();
|
map.dispose();
|
||||||
@@ -159,11 +159,11 @@ describe('StaleExpirationMap', () => {
|
|||||||
map.set('a', 1);
|
map.set('a', 1);
|
||||||
|
|
||||||
// Peek at 50ms
|
// Peek at 50ms
|
||||||
await new Promise(r => setTimeout(r, 50));
|
await new Promise((r) => setTimeout(r, 50));
|
||||||
expect(map.peek('a')).toBe(1); // Does NOT refresh TTL
|
expect(map.peek('a')).toBe(1); // Does NOT refresh TTL
|
||||||
|
|
||||||
// Wait another 75ms (entry should be expired)
|
// Wait another 75ms (entry should be expired)
|
||||||
await new Promise(r => setTimeout(r, 75));
|
await new Promise((r) => setTimeout(r, 75));
|
||||||
expect(map.peek('a')).toBeUndefined();
|
expect(map.peek('a')).toBeUndefined();
|
||||||
|
|
||||||
map.dispose();
|
map.dispose();
|
||||||
@@ -178,11 +178,11 @@ describe('StaleExpirationMap', () => {
|
|||||||
map.set('a', 1);
|
map.set('a', 1);
|
||||||
|
|
||||||
// Touch at 75ms
|
// Touch at 75ms
|
||||||
await new Promise(r => setTimeout(r, 75));
|
await new Promise((r) => setTimeout(r, 75));
|
||||||
expect(map.touch('a')).toBe(true);
|
expect(map.touch('a')).toBe(true);
|
||||||
|
|
||||||
// Wait another 100ms (entry should still be valid)
|
// Wait another 100ms (entry should still be valid)
|
||||||
await new Promise(r => setTimeout(r, 100));
|
await new Promise((r) => setTimeout(r, 100));
|
||||||
expect(map.has('a')).toBe(true);
|
expect(map.has('a')).toBe(true);
|
||||||
|
|
||||||
map.dispose();
|
map.dispose();
|
||||||
@@ -202,12 +202,13 @@ describe('StaleExpirationMap', () => {
|
|||||||
const map = new StaleExpirationMap<string, number>({ ttlMs: 10000 });
|
const map = new StaleExpirationMap<string, number>({ ttlMs: 10000 });
|
||||||
map.set('a', 1);
|
map.set('a', 1);
|
||||||
|
|
||||||
await new Promise(r => setTimeout(r, 50));
|
await new Promise((r) => setTimeout(r, 50));
|
||||||
|
|
||||||
const age = map.getAge('a');
|
const age = map.getAge('a');
|
||||||
expect(age).toBeDefined();
|
expect(age).toBeDefined();
|
||||||
expect(age!).toBeGreaterThanOrEqual(50);
|
// Tolerate timer jitter on slow/loaded CI runners (setTimeout isn't exact).
|
||||||
expect(age!).toBeLessThan(150);
|
expect(age!).toBeGreaterThanOrEqual(40);
|
||||||
|
expect(age!).toBeLessThan(500);
|
||||||
|
|
||||||
map.dispose();
|
map.dispose();
|
||||||
});
|
});
|
||||||
@@ -224,13 +225,13 @@ describe('StaleExpirationMap', () => {
|
|||||||
const map = new StaleExpirationMap<string, number>({ ttlMs: 1000 });
|
const map = new StaleExpirationMap<string, number>({ ttlMs: 1000 });
|
||||||
map.set('a', 1);
|
map.set('a', 1);
|
||||||
|
|
||||||
await new Promise(r => setTimeout(r, 100));
|
await new Promise((r) => setTimeout(r, 100));
|
||||||
|
|
||||||
const remaining = map.getRemainingTtl('a');
|
const remaining = map.getRemainingTtl('a');
|
||||||
expect(remaining).toBeDefined();
|
expect(remaining).toBeDefined();
|
||||||
// Allow small timing variance (setTimeout isn't exact)
|
// Allow generous timing variance (setTimeout isn't exact; CI runners are jittery)
|
||||||
expect(remaining!).toBeLessThanOrEqual(910);
|
expect(remaining!).toBeLessThanOrEqual(960);
|
||||||
expect(remaining!).toBeGreaterThan(800);
|
expect(remaining!).toBeGreaterThan(700);
|
||||||
|
|
||||||
map.dispose();
|
map.dispose();
|
||||||
});
|
});
|
||||||
@@ -244,7 +245,11 @@ describe('StaleExpirationMap', () => {
|
|||||||
map.set('c', 3);
|
map.set('c', 3);
|
||||||
|
|
||||||
const entries = Array.from(map);
|
const entries = Array.from(map);
|
||||||
expect(entries).toEqual([['a', 1], ['b', 2], ['c', 3]]);
|
expect(entries).toEqual([
|
||||||
|
['a', 1],
|
||||||
|
['b', 2],
|
||||||
|
['c', 3],
|
||||||
|
]);
|
||||||
|
|
||||||
map.dispose();
|
map.dispose();
|
||||||
});
|
});
|
||||||
@@ -277,7 +282,7 @@ describe('StaleExpirationMap', () => {
|
|||||||
const expired: string[] = [];
|
const expired: string[] = [];
|
||||||
const map = new StaleExpirationMap<string, number>({
|
const map = new StaleExpirationMap<string, number>({
|
||||||
ttlMs: 50,
|
ttlMs: 50,
|
||||||
cleanupIntervalMs: 10000, // Long interval so automatic cleanup doesn't run
|
cleanupIntervalMs: 10000, // Long interval so automatic cleanup doesn't run
|
||||||
onExpire: (key) => expired.push(key),
|
onExpire: (key) => expired.push(key),
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -285,7 +290,7 @@ describe('StaleExpirationMap', () => {
|
|||||||
map.set('b', 2);
|
map.set('b', 2);
|
||||||
|
|
||||||
// Wait for expiration
|
// Wait for expiration
|
||||||
await new Promise(r => setTimeout(r, 100));
|
await new Promise((r) => setTimeout(r, 100));
|
||||||
|
|
||||||
// Manual cleanup
|
// Manual cleanup
|
||||||
const removed = map.cleanup();
|
const removed = map.cleanup();
|
||||||
|
|||||||
Reference in New Issue
Block a user