Skip to content

Commit e00959d

Browse files
authored
test(gitnexus): stabilize rel-csv-split stream teardown on Windows (expect.poll) (#1052)
* test(lbug): stabilize rel-csv-split Windows CI with expect.poll Fixed sleeps assumed readline had already created the first mock stream within 20ms; windows-latest can lag, causing streams.length===0 and ENOTEMPTY tempdir cleanup. Poll up to 10s instead (Vitest 4). Refs #1051 Made-with: Cursor * test(lbug): use exact toBe assertions in rel-csv-split (DoD §2.7) - Poll for streams.length === 2 after unblock (two pair keys only) - disk-full test: streams.length === 1 for single Function|Class row Made-with: Cursor * test(lbug): replace rel-csv-split setTimeout waits with expect.poll Shared pollOpts; drain-listener and disk-full tests now wait on streams.length instead of fixed 50ms sleeps (DoD §2.7 deterministic tests). Made-with: Cursor
1 parent ac9246c commit e00959d

1 file changed

Lines changed: 10 additions & 12 deletions

File tree

gitnexus/test/unit/rel-csv-split.test.ts

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,8 @@ function writeCsv(lines: string[]): string {
106106
// ---------------------------------------------------------------------------
107107
describe('splitRelCsvByLabelPair', () => {
108108
const validTables = new Set(['Function', 'Class', 'File', 'Method']);
109+
/** Bounded poll for readline + split loop to reach an observable milestone (DoD §2.7). */
110+
const pollOpts = { interval: 10, timeout: 10_000 } as const;
109111

110112
it('splits lines into per-pair files with correct row counts', async () => {
111113
const csvPath = writeCsv([
@@ -197,8 +199,8 @@ describe('splitRelCsvByLabelPair', () => {
197199
mockFactory(streams, { blocked: true }),
198200
);
199201

200-
// Give readline time to buffer and fire lines
201-
await new Promise((r) => setTimeout(r, 50));
202+
// All rows share Function|Class — one stream, blocked on header or row drain
203+
await expect.poll(() => streams.length, pollOpts).toBe(1);
202204

203205
// Unblock all streams so the Promise can resolve
204206
for (const ws of streams) ws.unblock();
@@ -222,9 +224,7 @@ describe('splitRelCsvByLabelPair', () => {
222224
mockFactory(streams, { blocked: true }),
223225
);
224226

225-
// Wait for readline to process, then error while paused on drain
226-
await new Promise((r) => setTimeout(r, 50));
227-
expect(streams.length).toBeGreaterThan(0);
227+
await expect.poll(() => streams.length, pollOpts).toBe(1);
228228
streams[0].triggerError(new Error('disk full'));
229229

230230
await expect(promise).rejects.toThrow('disk full');
@@ -247,14 +247,12 @@ describe('splitRelCsvByLabelPair', () => {
247247
mockFactory(streams, { blocked: true }),
248248
);
249249

250-
// The first pair stream is created immediately and blocks on its header
251-
// write. Unblock it once so the loop advances and creates the second
252-
// pair stream (also blocked). Now both streams exist — trigger the error.
253-
await new Promise((r) => setTimeout(r, 20));
254-
expect(streams.length).toBe(1);
250+
// First pair stream once readline delivered a row; poll avoids Windows CI races.
251+
await expect.poll(() => streams.length, pollOpts).toBe(1);
255252
streams[0].unblock();
256-
await new Promise((r) => setTimeout(r, 20));
257-
expect(streams.length).toBeGreaterThanOrEqual(2);
253+
// Exactly two pair keys before the third CSV row: Function|Class then
254+
// File|Method; the loop is blocked on the second stream's header drain.
255+
await expect.poll(() => streams.length, pollOpts).toBe(2);
258256
streams[0].triggerError(new Error('EMFILE'));
259257

260258
await expect(promise).rejects.toThrow('EMFILE');

0 commit comments

Comments
 (0)