fix(test:free): exact root-bound JUnit path matching; serial timeout text names the wall the parallel phase left

Adversarial pass 2 (GSTA-203 PR 2): a plain relative path now matches a planned
file exactly, and an absolute or ../-prefixed path matches only when its prefix is
the child's root, so an unplanned browse/test/x.test.ts is never credited to
test/x.test.ts. The serial sub-shard's FREE_SUBSHARD_TIMEOUT text says how much of
the shard wall the parallel phase left it.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
This commit is contained in:
garrytanandcapy-ai[bot] committed 2026-10-31 19:11:58 +00:00
1 parent f7eb79f9ad
commit 8ab672cfd6
3 files changed
+35 -12

No files matched your search

+14
View File
@@ -311,6 +311,15 @@ describe('per-file test and expect() counts from bun JUnit', () => {
expect(counts.problem).toContain('unplanned');
});
test('an absolute path is credited to the planned file under the root; an unplanned file never borrows a shorter planned path', () => {
const planned = ['test/telemetry.test.ts', 'browse/test/telemetry.test.ts'];
expect(Object.keys(parseJunitCounts(xml('/repo/browse/test/telemetry.test.ts'), planned, 4, '/repo').files)).toEqual(['browse/test/telemetry.test.ts']);
expect(Object.keys(parseJunitCounts(xml('../../repo/test/telemetry.test.ts'), planned, 4, '/repo').files)).toEqual(['test/telemetry.test.ts']);
const borrowed = parseJunitCounts(xml('browse/test/x.test.ts'), ['test/x.test.ts'], 4, '/repo');
expect(borrowed).toMatchObject({ complete: false, problem: expect.stringContaining('browse/test/x.test.ts') });
expect(parseJunitCounts(xml('/elsewhere/test/x.test.ts'), ['test/x.test.ts'], 4, '/repo').complete).toBe(false);
});
test('the report is read only as a bounded regular file, never through a link or a FIFO', () => {
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'gstack-junit-'));
try {
@@ -447,5 +456,10 @@ describe('serial lists and the duration seed', () => {
expect(ciRunContext('p.json', {}).runId).toBe('local');
expect(subShardTimeoutText(2, 4, { id: 'x:2.1', phase: 'parallel', files: ['test/a.test.ts'], status: 'timed-out', exitCode: null, elapsedMs: 1, failingFiles: [], unattributedFailures: 0 },
[], 10_000, context)[1]).toContain('in flight: unknown');
const serial = { id: 'x:2.5', phase: 'serial' as const, files: ['test/s.test.ts'], status: 'timed-out' as const, exitCode: null, elapsedMs: 1, failingFiles: [], unattributedFailures: 0 };
const squeezed = subShardTimeoutText(2, 4, serial, [], 4_000, context, 360_000);
expect(squeezed[0]).toContain('hit its 4s wall');
expect(squeezed[4]).toContain('left this serial sub-shard 4s of the 360s shard wall');
expect(subShardTimeoutText(2, 4, serial, [], 360_000, context, 360_000)[4]).toContain('already runs alone');
});
});