diff --git a/test/napi/napi-app/test_experimental_with_timeout.js b/test/napi/napi-app/test_experimental_with_timeout.js index 8bd34862370e..0020cca87529 100644 --- a/test/napi/napi-app/test_experimental_with_timeout.js +++ b/test/napi/napi-app/test_experimental_with_timeout.js @@ -36,15 +36,15 @@ proc.stdout.on('data', (data) => { proc.stderr.on('data', (data) => { stderr += data.toString(); process.stderr.write(data); - - // Check if we've seen the expected crash messages - if (data.toString().includes('FATAL ERROR')) { + + // Check the accumulated output: a marker can be split across two chunks. + if (stderr.includes('FATAL ERROR')) { sawFatalError = true; } - if (data.toString().includes('panic(main thread)')) { + if (stderr.includes('panic(main thread)')) { sawPanic = true; } - + // If we've seen both messages, kill the process immediately // This avoids hanging on llvm-symbolizer if (sawFatalError && sawPanic) { @@ -57,9 +57,11 @@ const timeout = setTimeout(() => { proc.kill('SIGKILL'); }, 5000); -proc.on('exit', (code, signal) => { +// 'close', not 'exit': 'exit' can fire before the stdio pipes have been +// drained, and the verdict below depends on everything the child wrote. +proc.on('close', (code, signal) => { clearTimeout(timeout); - + // Check if the test passed if (sawFatalError && sawPanic) { console.log('\n\nTEST PASSED: Process crashed as expected'); diff --git a/test/napi/napi.test.ts b/test/napi/napi.test.ts index 1e044ea4a4bf..cba9044bc902 100644 --- a/test/napi/napi.test.ts +++ b/test/napi/napi.test.ts @@ -1378,18 +1378,18 @@ describe.concurrent.skipIf(!canBuildNodeAddons())("napi", () => { bunProc.exited, ]); - // The wrapper script should exit with 0 if the test passed - expect(bunExitCode).toBe(0); + // Combined output first, so a failure shows what the wrapper and child wrote. + expect(bunStdout + "\n---- stderr ----\n" + bunStderr).toContain("TEST PASSED: Process crashed as expected"); expect(bunStdout + bunStderr).toContain("Loading experimental module"); expect(bunStdout + bunStderr).toContain("Created"); expect(bunStderr).toContain("FATAL ERROR"); - expect(bunStdout + bunStderr).toContain("TEST PASSED: Process crashed as expected"); // The marker must NOT have actually been printed. Only check stdout: the // fixture prints the marker via console.log (stdout), while stderr contains // the debug-build panic report whose "Args:" line echoes the full -e script // source, including the literal "ERROR: Did not crash! Test failed!". expect(bunStdout).not.toContain("ERROR: Did not crash"); + expect(bunExitCode).toBe(0); }, 25_000, );