Skip to content

Commit db115c1

Browse files
committed
test: fix race condition in watch mode tests
The watch mode tests using runInBackground() had a race condition where stdout "Failed running" message could arrive before stderr was fully collected, causing assertions on stderr content to fail with empty strings. Fix by waiting for stderr 'data' event if stderr is empty when "Failed running" is detected. This is an event-driven approach rather than timing-based. Refs: nodejs/reliability#1450
1 parent c5136c4 commit db115c1

File tree

2 files changed

+30
-12
lines changed

2 files changed

+30
-12
lines changed

test/sequential/test-watch-mode-restart-esm-loading-error.mjs

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,14 +42,23 @@ function runInBackground({ args = [], options = {}, completed = 'Completed runni
4242
stdout = [];
4343
stderr = '';
4444
} else if (data.startsWith('Failed running')) {
45-
if (shouldFail) {
46-
future.resolve({ stderr, stdout });
45+
const settle = () => {
46+
if (shouldFail) {
47+
future.resolve({ stderr, stdout });
48+
} else {
49+
future.reject({ stderr, stdout });
50+
}
51+
future = Promise.withResolvers();
52+
stdout = [];
53+
stderr = '';
54+
};
55+
// If stderr is empty, wait for it to receive data before settling.
56+
// This handles the race condition where stdout arrives before stderr.
57+
if (stderr === '') {
58+
child.stderr.once('data', settle);
4759
} else {
48-
future.reject({ stderr, stdout });
60+
settle();
4961
}
50-
future = Promise.withResolvers();
51-
stdout = [];
52-
stderr = '';
5362
}
5463
}
5564
});

test/sequential/test-watch-mode.mjs

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,14 +54,23 @@ function runInBackground({ args = [], options = {}, completed = 'Completed runni
5454
stdout = [];
5555
stderr = '';
5656
} else if (data.startsWith('Failed running')) {
57-
if (shouldFail) {
58-
future.resolve({ stderr, stdout });
57+
const settle = () => {
58+
if (shouldFail) {
59+
future.resolve({ stderr, stdout });
60+
} else {
61+
future.reject({ stderr, stdout });
62+
}
63+
future = Promise.withResolvers();
64+
stdout = [];
65+
stderr = '';
66+
};
67+
// If stderr is empty, wait for it to receive data before settling.
68+
// This handles the race condition where stdout arrives before stderr.
69+
if (stderr === '') {
70+
child.stderr.once('data', settle);
5971
} else {
60-
future.reject({ stderr, stdout });
72+
settle();
6173
}
62-
future = Promise.withResolvers();
63-
stdout = [];
64-
stderr = '';
6574
}
6675
}
6776
});

0 commit comments

Comments
 (0)