From 78258c4f9bc13c42e83f2b71400ddcbd40205e39 Mon Sep 17 00:00:00 2001 From: Claude Fable 5 Date: Sun, 2 Aug 2026 14:01:14 +0200 Subject: [PATCH] test: give the 10k-iteration sort-key property test its own timeout Under parallel CI load the test repeatedly exceeded the default 5000 ms per-test timeout (run 685 on main, run 699 on an unrelated PR); the identical test passed on rerun. Locally it finishes in about 1.3 s, so 30 s is generous headroom, not a mask for a regression. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_017aviRTgWCcAHUh1SBoxf6P --- apps/api/src/pages/sort-key.test.ts | 84 ++++++++++++++++------------- 1 file changed, 46 insertions(+), 38 deletions(-) diff --git a/apps/api/src/pages/sort-key.test.ts b/apps/api/src/pages/sort-key.test.ts index 2878034..7643ca9 100644 --- a/apps/api/src/pages/sort-key.test.ts +++ b/apps/api/src/pages/sort-key.test.ts @@ -26,48 +26,56 @@ describe('sort-key helpers (issue #45)', () => { * pattern — repeatedly drop the last page between the first two — must never * collide and never overflow the key length, because the caller rebalances * when {@link nextKeyOrRebalance} returns null. + * + * Under parallel CI load the 10.000 iterations have repeatedly exceeded the + * default 5 s per-test timeout (runs 685, 699 — same code passed on rerun), + * so this test carries its own budget. */ - it('10.000 adversarial reorders never collide or overflow (rebalance verified)', () => { - // Start with five pages in a fixed order. - let order = evenlySpacedKeys(5).map((key, i) => ({ id: `p${i}`, key })); - let rebalances = 0; + it( + '10.000 adversarial reorders never collide or overflow (rebalance verified)', + { timeout: 30_000 }, + () => { + // Start with five pages in a fixed order. + let order = evenlySpacedKeys(5).map((key, i) => ({ id: `p${i}`, key })); + let rebalances = 0; - const rebalance = (): void => { - const keys = evenlySpacedKeys(order.length); - order = order.map((page, i) => ({ ...page, key: keys[i]! })); - rebalances += 1; - }; + const rebalance = (): void => { + const keys = evenlySpacedKeys(order.length); + order = order.map((page, i) => ({ ...page, key: keys[i]! })); + rebalances += 1; + }; - for (let i = 0; i < 10_000; i += 1) { - // Move the last page to sit between the first and second — the tightest - // possible gap, which is what grows key length fastest. - const moved = order[order.length - 1]!; - const rest = order.slice(0, -1); - const afterKey = rest[0]!.key; - const beforeKey = rest[1]!.key; + for (let i = 0; i < 10_000; i += 1) { + // Move the last page to sit between the first and second — the tightest + // possible gap, which is what grows key length fastest. + const moved = order[order.length - 1]!; + const rest = order.slice(0, -1); + const afterKey = rest[0]!.key; + const beforeKey = rest[1]!.key; - const key = nextKeyOrRebalance(afterKey, beforeKey); - if (key === null) { - // Rebalance keeps the CURRENT order, then retry the move once. - rebalance(); - const k2 = nextKeyOrRebalance(order[0]!.key, order[1]!.key); - expect(k2).not.toBeNull(); - order = [order[0]!, { ...moved, key: k2! }, ...order.slice(1)]; - } else { - order = [rest[0]!, { ...moved, key }, ...rest.slice(1)]; + const key = nextKeyOrRebalance(afterKey, beforeKey); + if (key === null) { + // Rebalance keeps the CURRENT order, then retry the move once. + rebalance(); + const k2 = nextKeyOrRebalance(order[0]!.key, order[1]!.key); + expect(k2).not.toBeNull(); + order = [order[0]!, { ...moved, key: k2! }, ...order.slice(1)]; + } else { + order = [rest[0]!, { ...moved, key }, ...rest.slice(1)]; + } + + // Invariants after every move: keys unique, bounded, and consistent with + // the intended array order. + const keys = order.map((p) => p.key); + expect(new Set(keys).size).toBe(keys.length); + expect(Math.max(...keys.map((k) => k.length))).toBeLessThanOrEqual(MAX_SORT_KEY_LENGTH); + for (let j = 1; j < keys.length; j += 1) { + expect(keys[j - 1]! < keys[j]!).toBe(true); + } } - // Invariants after every move: keys unique, bounded, and consistent with - // the intended array order. - const keys = order.map((p) => p.key); - expect(new Set(keys).size).toBe(keys.length); - expect(Math.max(...keys.map((k) => k.length))).toBeLessThanOrEqual(MAX_SORT_KEY_LENGTH); - for (let j = 1; j < keys.length; j += 1) { - expect(keys[j - 1]! < keys[j]!).toBe(true); - } - } - - // The adversarial pattern must have forced at least one rebalance. - expect(rebalances).toBeGreaterThan(0); - }); + // The adversarial pattern must have forced at least one rebalance. + expect(rebalances).toBeGreaterThan(0); + }, + ); }); -- 2.45.2