test: stabilize process and transcript liveness checks (#17126)

This commit is contained in:
Neil
2026-08-29 01:45:20 -07:00
committed by GitHub
parent 6bef6d2727
commit d73d36bc99
2 changed files with 22 additions and 6 deletions
@@ -60,7 +60,8 @@ function claudeLine(uuid: string, role: 'user' | 'assistant', text: string): str
})}\n`
}
async function waitFor(predicate: () => boolean, timeoutMs = 2_000): Promise<void> {
// fs.watch and filesystem mutations use the platform clock; poll observable callbacks to a deadline.
async function waitFor(predicate: () => boolean, timeoutMs = 5_000): Promise<void> {
const start = Date.now()
while (!predicate()) {
if (Date.now() - start > timeoutMs) {
@@ -166,13 +167,14 @@ describe('native chat transcript watcher liveness', () => {
onReplace: replacements,
onAppend: () => {},
debounceMs: 0,
reconciliationIntervalMs: 20
reconciliationIntervalMs: 10_000
})
await waitFor(() => snapshots.mock.calls.length === 1)
await writeFile(filePath, prefixAfter + stableTail)
const future = new Date(Date.now() + 10_000)
await utimes(filePath, future, future)
watchCallbacks[0]!('change', 'transcript.jsonl')
await waitFor(() =>
replacements.mock.calls.flat(2).some((message) => message.id === 'prefix-new')
)
@@ -30,6 +30,18 @@ function isAlive(pid: number): boolean {
}
}
// Job-object teardown is external to fake timers; poll the real process table to a deadline.
async function waitForProcessExit(pid: number, timeoutMs: number): Promise<boolean> {
const deadline = Date.now() + timeoutMs
while (Date.now() < deadline) {
if (!isAlive(pid)) {
return true
}
await sleep(50)
}
return !isAlive(pid)
}
describeOnWindows('host job reaps the tree when the host dies', () => {
let dir: string
@@ -83,11 +95,13 @@ describeOnWindows('host job reaps the tree when the host dies', () => {
// Force-kill only the host: no tree kill, nothing given a chance to unwind.
// This is the daemon-crash shape.
process.kill(host.pid!, 'SIGKILL')
await sleep(3_000)
try {
expect(isAlive(shellPid)).toBe(false)
expect(isAlive(grandchildPid)).toBe(false)
const [shellExited, grandchildExited] = await Promise.all([
waitForProcessExit(shellPid, 15_000),
waitForProcessExit(grandchildPid, 15_000)
])
expect(shellExited).toBe(true)
expect(grandchildExited).toBe(true)
} finally {
for (const pid of [shellPid, grandchildPid]) {
try {