Skip to content

Commit 83fd325

Browse files
authored
test(crashtracker): improve reliability and debuggability of crash tests (#83)
- Increase crashtracker handler timeout from 3s to 15s and crash-report wait timeout from 10s to 20s to reduce flakiness in CI - Guard stdout/stderr log file reads in the timeout handler with existence checks to avoid masking the real timeout error - Add error and close handlers to child processes so tests fail with a clear message instead of hanging indefinitely - Add console.log labels to each test for easier debugging
1 parent 8ea1cff commit 83fd325

2 files changed

Lines changed: 46 additions & 6 deletions

File tree

test/crashtracker/index.js

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,21 @@ rmSync(path.join(cwd, 'stdout.log'), { force: true })
2020
rmSync(path.join(cwd, 'stderr.log'), { force: true })
2121

2222
const timeout = setTimeout(() => {
23-
execSync('cat stdout.log', opts)
24-
execSync('cat stderr.log', opts)
23+
const stdoutLog = path.join(cwd, 'stdout.log')
24+
const stderrLog = path.join(cwd, 'stderr.log')
25+
if (existsSync(stdoutLog)) {
26+
execSync(`cat ${stdoutLog}`, opts)
27+
} else {
28+
console.error('stdout.log not found (crashtracker-receiver may not have started)')
29+
}
30+
if (existsSync(stderrLog)) {
31+
execSync(`cat ${stderrLog}`, opts)
32+
} else {
33+
console.error('stderr.log not found (crashtracker-receiver may not have started)')
34+
}
2535

2636
throw new Error('No crash report received before timing out.')
27-
}, 10_000)
37+
}, 20_000)
2838

2939
let currentTest
3040

@@ -51,20 +61,46 @@ app.post('/telemetry/proxy/api/v2/apmtelemetry', (req, res) => {
5161
let PORT
5262

5363
function runApp (script) {
54-
return new Promise((resolve) => {
55-
exec(`node ${script}`, {
64+
return new Promise((resolve, reject) => {
65+
let closeTimer
66+
let done = false
67+
68+
const child = exec(`node ${script}`, {
5669
...opts,
5770
env: { ...process.env, PORT },
5871
})
5972

73+
child.on('error', (err) => {
74+
cleanup()
75+
reject(new Error(`Child process for "${script}" failed to start`, { cause: err }))
76+
})
77+
78+
child.on('close', (code, signal) => {
79+
if (done) return
80+
// Allow a grace period for the crash report HTTP request to arrive
81+
// after the child process exits (e.g. segfault sends report then dies).
82+
closeTimer = setTimeout(() => {
83+
const reason = signal ? `signal ${signal}` : `exit code ${code}`
84+
reject(new Error(`Child process for "${script}" exited with ${reason} before sending a crash report`))
85+
}, 5000)
86+
})
87+
6088
currentTest = (logPayload, tags) => {
89+
cleanup()
6190
currentTest = undefined
6291
resolve({ logPayload, tags })
6392
}
93+
94+
function cleanup () {
95+
clearTimeout(closeTimer)
96+
done = true
97+
}
6498
})
6599
}
66100

67101
async function testSegfault () {
102+
console.log('Running test: testSegfault')
103+
68104
const { logPayload, tags } = await runApp('app-seg-fault')
69105
const stackTrace = JSON.parse(logPayload.message).error.stack.frames
70106
const boomFrame = stackTrace.find(frame => frame.function?.toLowerCase().includes('segfaultify'))
@@ -79,6 +115,8 @@ async function testSegfault () {
79115
}
80116

81117
async function testUnhandledError (label, script, { expectedType, expectedMessage, expectedFrame }) {
118+
console.log('Running test: testUnhandledError', label)
119+
82120
const { logPayload } = await runApp(script)
83121
const crashReport = JSON.parse(logPayload.message)
84122

@@ -91,6 +129,8 @@ async function testUnhandledError (label, script, { expectedType, expectedMessag
91129
}
92130

93131
async function testUnhandledNonError (label, script, { expectedFallbackType, expectedValue }) {
132+
console.log('Running test: testUnhandledNonError', label)
133+
94134
const { logPayload } = await runApp(script)
95135
const crashReport = JSON.parse(logPayload.message)
96136

test/crashtracker/test-utils.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ function initTestCrashtracker () {
1616
},
1717
timeout_ms: 3000,
1818
},
19-
timeout: { secs: 3, nanos: 0 },
19+
timeout: { secs: 15, nanos: 0 },
2020
resolve_frames: 'EnabledWithInprocessSymbols',
2121
wait_for_receiver: true,
2222
demangle_names: false,

0 commit comments

Comments
 (0)