CI green on a loaded shared machine: browser suites (now also glyph-ligatures and feature-fit, through the shared launch helper) in one dedicated shard started first at concurrency 2; timeouts scaled by load ÷ cores (tests/helpers/load.ts, max(1-, 5-min average), capped at 5x, logged) for browser tests, waits, launch/close, the other shards' default and the desktop boot check; one retry for a browser test that timed out while the factor was above 2, listed as 'retried under load' in the CI summary, never for an assertion failure; the six-type App Privacy walk no longer dumps every step (the --debug-dump check walks two types), wait timeouts print per-line times; play-edit-lock checks reads in flight instead of wall time; tests/load-retry.test.ts

This commit is contained in:
CRTkafa 2026-10-14 05:21:15 +08:00
parent 21fa91afd1
commit 918146d4a6
13 changed files with 261 additions and 96 deletions

View file

@ -9,16 +9,23 @@ describe('tools/ci-plan: test shards', () => {
expect(shardCount({ STOREBOUND_CI_SHARDS: '3' }, 10)).toBe(3);
expect(shardCount({ STOREBOUND_CI_SHARDS: 'x' }, 10)).toBe(8);
});
test('balance: every file once, longest first, heavy suites never share a shard', () => {
test('balance: every file once; the heavy suites first, in one dedicated shard; light files balanced over the rest', () => {
const cost: Record<string, number> = { h1: 10, h2: 9, a: 5, b: 4, c: 3, d: 2, e: 1 };
const shards = balance(Object.keys(cost), 3, f => cost[f]!, ['h1', 'h2']);
expect(shards.flat().sort()).toEqual(Object.keys(cost).sort());
for (const s of shards) expect(s.filter(f => f.startsWith('h')).length).toBeLessThanOrEqual(1);
const loads = shards.map(s => s.reduce((n, f) => n + cost[f]!, 0));
expect(shards[0]).toEqual(['h1', 'h2']);
const rest = shards.slice(1);
expect(rest).toHaveLength(2);
for (const s of rest) expect(s.some(f => f.startsWith('h'))).toBe(false);
const loads = rest.map(s => s.reduce((n, f) => n + cost[f]!, 0));
expect(Math.max(...loads) - Math.min(...loads)).toBeLessThanOrEqual(cost.a!);
});
test('balance: more heavy suites than shards still places each once; empty shards dropped', () => {
expect(balance(['h1', 'h2', 'h3'], 2, () => 1, ['h1', 'h2', 'h3']).flat().sort()).toEqual(['h1', 'h2', 'h3']);
test('balance: two browser shards split the heavy suites by cost; one shard in all takes everything; empty shards dropped', () => {
const cost: Record<string, number> = { h1: 10, h2: 9, h3: 2, a: 1 };
const shards = balance(Object.keys(cost), 4, f => cost[f]!, ['h1', 'h2', 'h3'], 2);
expect(shards.slice(0, 2).map(s => [...s].sort())).toEqual([['h1'], ['h2', 'h3']]);
expect(shards.slice(2)).toEqual([['a']]);
expect(balance(['h1', 'h2', 'a'], 1, () => 1, ['h1', 'h2']).flat().sort()).toEqual(['a', 'h1', 'h2']);
expect(balance(['a'], 8, () => 1)).toEqual([['a']]);
});
test('JUnit report: per-file seconds from the top-level suites only', () => {