test: remove crash marker publication race
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { spawn } from 'node:child_process'
|
||||
import { access, mkdtemp, readFile, rm } from 'node:fs/promises'
|
||||
import { mkdtemp, readFile, rm, writeFile } from 'node:fs/promises'
|
||||
import { tmpdir } from 'node:os'
|
||||
import { join } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
@@ -18,16 +18,21 @@ const sessionId = SessionId('semantic-checkpoint-crash')
|
||||
const roots: string[] = []
|
||||
const CHILD_FAILPOINT_TIMEOUT_MS = 30_000
|
||||
|
||||
async function waitForFile(path: string): Promise<void> {
|
||||
async function waitForMarker(path: string, expected: string): Promise<string> {
|
||||
const deadline = Date.now() + CHILD_FAILPOINT_TIMEOUT_MS
|
||||
for (;;) {
|
||||
try {
|
||||
await access(path)
|
||||
return
|
||||
const content = await readFile(path, 'utf8')
|
||||
if (content === expected) return content
|
||||
if (!expected.startsWith(content)) {
|
||||
throw new Error(`crash child wrote unexpected failpoint ${JSON.stringify(content)}`)
|
||||
}
|
||||
} catch (error: unknown) {
|
||||
if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error
|
||||
}
|
||||
if (Date.now() >= deadline) throw new Error(`crash child did not reach failpoint ${path}`)
|
||||
if (Date.now() >= deadline) {
|
||||
throw new Error(`crash child did not publish failpoint ${JSON.stringify(expected)} at ${path}`)
|
||||
}
|
||||
await new Promise(resolve => setTimeout(resolve, 10))
|
||||
}
|
||||
}
|
||||
@@ -36,6 +41,9 @@ async function crashAt(mode: 'request' | 'tool'): Promise<{ root: string; marker
|
||||
const root = await mkdtemp(join(tmpdir(), `dsh-semantic-${mode}-`))
|
||||
roots.push(root)
|
||||
const marker = join(root, 'failpoint')
|
||||
// Keep the open-before-write window deterministic: readiness is marker content, not path existence.
|
||||
await writeFile(marker, '')
|
||||
const expectedMarker = mode === 'request' ? 'request-dispatched' : 'tool-side-effect'
|
||||
const child = spawn(process.execPath, ['--import', tsxLoader, childScript, mode, root, marker], {
|
||||
cwd: repoRoot,
|
||||
env: { ...process.env, TSX_TSCONFIG_PATH: join(repoRoot, 'tsconfig.json') },
|
||||
@@ -45,8 +53,7 @@ async function crashAt(mode: 'request' | 'tool'): Promise<{ root: string; marker
|
||||
child.stderr.setEncoding('utf8')
|
||||
child.stderr.on('data', (chunk: string) => { stderr += chunk })
|
||||
try {
|
||||
await waitForFile(marker)
|
||||
const markerText = await readFile(marker, 'utf8')
|
||||
const markerText = await waitForMarker(marker, expectedMarker)
|
||||
const closed = new Promise<{ code: number | null; signal: NodeJS.Signals | null }>((resolve) => {
|
||||
child.once('close', (code, signal) => { resolve({ code, signal }) })
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user