fix(test): use backpressure to keep promise pending during error tests

The error tests were racing — readline finished reading the tiny CSV
and resolved the Promise before setTimeout fired the error. Now the
mock streams use blocked=true to trigger backpressure, keeping the
Promise pending so the error fires while the split is still in progress.
This commit is contained in:
MekayelAnik 2026-04-14 16:03:24 +06:00
parent 20dc22d902
commit d71a6408c7

View file

@ -303,39 +303,47 @@ describe('splitRelCsvByLabelPair', () => {
it('rejects the Promise when a WriteStream emits an error', async () => {
const csvPath = writeCsv([HEADER, csvLine('Function:a', 'Class:b')]);
const factory = () => {
const ws = new MockWriteStream();
// Trigger error after first write
setTimeout(() => ws.triggerError(new Error('disk full')), 10);
return ws;
};
await expect(
splitRelCsvByLabelPair(csvPath, tmpDir, validTables, getNodeLabel, factory),
).rejects.toThrow('disk full');
});
it('destroys all streams when one errors (no lingering FDs)', async () => {
const csvPath = writeCsv([
HEADER,
csvLine('Function:a', 'Class:b'),
csvLine('File:c', 'Method:d'),
]);
const streams: MockWriteStream[] = [];
const factory = () => {
const ws = new MockWriteStream();
ws.blocked = true; // hold the promise open via backpressure
streams.push(ws);
return ws;
};
// Error the first stream after both are created
const promise = splitRelCsvByLabelPair(csvPath, tmpDir, validTables, getNodeLabel, factory);
await new Promise((r) => setTimeout(r, 20));
if (streams.length > 0) {
streams[0].triggerError(new Error('EMFILE'));
// Wait for readline to process, then error while paused on drain
await new Promise((r) => setTimeout(r, 50));
expect(streams.length).toBeGreaterThan(0);
streams[0].triggerError(new Error('disk full'));
await expect(promise).rejects.toThrow('disk full');
});
it('destroys all streams when one errors (no lingering FDs)', async () => {
// Use enough lines to create two different pair streams
const lines = [HEADER];
for (let i = 0; i < 10; i++) {
lines.push(csvLine(`Function:f${i}`, `Class:c${i}`));
lines.push(csvLine(`File:e${i}`, `Method:m${i}`));
}
const csvPath = writeCsv(lines);
const streams: MockWriteStream[] = [];
const factory = () => {
const ws = new MockWriteStream();
ws.blocked = true; // hold all streams open via backpressure
streams.push(ws);
return ws;
};
const promise = splitRelCsvByLabelPair(csvPath, tmpDir, validTables, getNodeLabel, factory);
// Wait for readline to process and create streams
await new Promise((r) => setTimeout(r, 50));
expect(streams.length).toBeGreaterThanOrEqual(2);
streams[0].triggerError(new Error('EMFILE'));
await expect(promise).rejects.toThrow('EMFILE');