Skip to content

Commit 4dc319b

Browse files
committed
test: key the interrupt fixtures' sleep length on the test pid
This file runs twice in one local CI run (npm test in one Gate slot, the Bun matrix in another), and pgrep -f on a fixed length matched the other run's child, firing SIGINT before this run had spawned anything, the same failure the wait was added to fix. Claude-Session: https://claude.ai/code/session_0125BCU48L9AmmM1JbBKeyQe
1 parent e391e9e commit 4dc319b

1 file changed

Lines changed: 11 additions & 6 deletions

File tree

‎test/cli/ci.test.mjs‎

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -159,9 +159,14 @@ test('Ctrl-C: the first signal winds the run down as interrupted (exit 130), a s
159159

160160
// The signal must land while the CHILD is running, not before the bin has
161161
// spawned it (under a loaded machine 700ms was not enough and the run ended
162-
// with nothing to interrupt). Each fixture uses a unique sleep length so
163-
// pgrep can wait for exactly its child.
162+
// with nothing to interrupt). Each fixture uses a sleep length unique to
163+
// this PROCESS so pgrep can wait for exactly its child: this file runs twice
164+
// in one local CI run (npm test in one slot, the Bun matrix in another), and
165+
// a fixed length would match the other run's child and fire the signal
166+
// before this run had spawned anything.
164167
const { execFileSync } = await import('node:child_process');
168+
const longSleep = `20.${process.pid}`;
169+
const shortSleep = `4.${process.pid}`;
165170
const childUp = async (pattern) => {
166171
for (let i = 0; i < 100; i++) {
167172
try { execFileSync('pgrep', ['-f', pattern], { stdio: 'ignore' }); return; } catch {}
@@ -170,11 +175,11 @@ test('Ctrl-C: the first signal winds the run down as interrupted (exit 130), a s
170175
throw new Error(`child matching ${pattern} never started`);
171176
};
172177

173-
const dir = await fixture(t, { ci: { steps: [{ title: 'G', parallel: 2, steps: [{ title: 'sleeper', run: 'sleep 20.71' }] }] } });
178+
const dir = await fixture(t, { ci: { steps: [{ title: 'G', parallel: 2, steps: [{ title: 'sleeper', run: `sleep ${longSleep}` }] }] } });
174179
const one = spawn(process.execPath, [CLI, 'ci'], { cwd: dir, env: { ...process.env, NO_COLOR: '1' }, stdio: ['ignore', 'pipe', 'pipe'] });
175180
let out1 = '';
176181
one.stdout.on('data', (d) => { out1 += d; });
177-
await childUp('sleep 20.71');
182+
await childUp(`sleep ${longSleep}`);
178183
one.kill('SIGINT');
179184
const r1 = await Promise.race([exited(one), wait(6000).then(() => null)]);
180185
assert.ok(r1, 'a single interrupt winds the run down within the bound (the detached sleep is reaped)');
@@ -183,9 +188,9 @@ test('Ctrl-C: the first signal winds the run down as interrupted (exit 130), a s
183188

184189
// A captured child that ignores SIGTERM cannot be wound down; the second
185190
// Ctrl-C is the door out.
186-
const stubborn = await fixture(t, { ci: { steps: [{ title: 'G', parallel: 2, steps: [{ title: 'stubborn', run: "trap '' TERM INT; sleep 4.37" }] }] } });
191+
const stubborn = await fixture(t, { ci: { steps: [{ title: 'G', parallel: 2, steps: [{ title: 'stubborn', run: `trap '' TERM INT; sleep ${shortSleep}` }] }] } });
187192
const two = spawn(process.execPath, [CLI, 'ci'], { cwd: stubborn, env: { ...process.env, NO_COLOR: '1' }, stdio: ['ignore', 'pipe', 'pipe'] });
188-
await childUp('sleep 4.37');
193+
await childUp(`sleep ${shortSleep}`);
189194
two.kill('SIGINT');
190195
await wait(400);
191196
const stillRunning = two.exitCode === null;

0 commit comments

Comments
 (0)