From c660048759fa0e20bc4f7cd953652176cd8f5950 Mon Sep 17 00:00:00 2001 From: Tianyi Cui <53024+tianyicui@users.noreply.github.com> Date: Sun, 19 Jul 2026 12:52:42 +0800 Subject: [PATCH] test(subagent): cover late forced-wait exit markers Exercise both exitCode and signalCode arriving after the SIGTERM grace begins but before the bounded SIGKILL confirmation helper starts. This pins the fast path that avoids signaling an already-terminated child and restores the package's per-file 100% branch and statement coverage. Keep the marker transition deterministic by withholding the synthetic exit event, matching the OS state race the defensive pre-check exists to absorb. --- .../tests/subagent-subprocess.spec.ts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/packages/subagent/subagent-subprocess/tests/subagent-subprocess.spec.ts b/packages/subagent/subagent-subprocess/tests/subagent-subprocess.spec.ts index e81957baa0..d674937e92 100644 --- a/packages/subagent/subagent-subprocess/tests/subagent-subprocess.spec.ts +++ b/packages/subagent/subagent-subprocess/tests/subagent-subprocess.spec.ts @@ -222,6 +222,21 @@ describe('disposeChildProcess', () => { expect(fake.signalCode).toBe('SIGKILL') }) + it.each(['exitCode', 'signalCode'] as const)('accepts a late OS %s marker before the final forced wait', async (marker) => { + const fake = new FakeChild() + vi.spyOn(fake, 'kill').mockImplementation((signal) => { + fake.kills.push(signal) + queueMicrotask(() => { + if (marker === 'exitCode') fake.exitCode = 0 + else fake.signalCode = 'SIGTERM' + }) + return true + }) + + await disposeChildProcess(asChild(fake), { disposeEofGraceMs: 1, disposeGraceMs: 10 }, 'linux') + expect(fake.kills).toEqual(['SIGTERM']) + }) + it('walks the ladder for a child spawned without a stdin pipe', async () => { const fake = new FakeChild({ stdin: false, diesOn: 'SIGTERM', delayMs: 5 }) await disposeChildProcess(asChild(fake), { disposeEofGraceMs: 20, disposeGraceMs: 1000 }, 'linux')