-
Notifications
You must be signed in to change notification settings - Fork 30k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
test: add Worker initialization failure test case
Cover the scenario fixed through #31621 Unfortunately there is no easy way to test this, in a cross-platform manner. So the approach is: - open a child process with ulimit restriction on file descriptors - in the child process, start few workers - more than the fd limit - make sure some workers fail, with the expected error type. - skip the test in windows, as there is no ulimit there. Refs: #31621 PR-URL: #31929 Reviewed-By: Denys Otrishko <shishugi@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net>
- Loading branch information
1 parent
0ddfd0f
commit 5b899d6
Showing
1 changed file
with
67 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
'use strict'; | ||
const common = require('../common'); | ||
const assert = require('assert'); | ||
const child_process = require('child_process'); | ||
|
||
// Test that workers fail with meaningful error message | ||
// when their initialization fails. | ||
|
||
if (common.isWindows) { | ||
common.skip('ulimit does not work on Windows.'); | ||
} | ||
|
||
// A reasonably low fd count. An empty node process | ||
// creates around 30 fds for its internal purposes, | ||
// so making it too low will crash the process early, | ||
// making it too high will cause too much resource use. | ||
const OPENFILES = 128; | ||
|
||
// Double the open files - so that some workers fail for sure. | ||
const WORKERCOUNT = 256; | ||
|
||
if (process.argv[2] === 'child') { | ||
const { Worker } = require('worker_threads'); | ||
for (let i = 0; i < WORKERCOUNT; ++i) { | ||
const worker = new Worker( | ||
'require(\'worker_threads\').parentPort.postMessage(2 + 2)', | ||
{ eval: true }); | ||
worker.on('message', (result) => { | ||
assert.strictEqual(result, 4); | ||
}); | ||
|
||
// We want to test that if there is an error in a constrained running | ||
// environment, it will be one of `EMFILE` or `ERR_WORKER_INIT_FAILED`. | ||
// `common.mustCall*` cannot be used here as in some environments | ||
// (i.e. single cpu) `ulimit` may not lead to such an error. | ||
|
||
worker.on('error', (e) => { | ||
assert.match(e.message, /EMFILE/); | ||
assert.ok(e.code === 'ERR_WORKER_INIT_FAILED' || e.code === 'EMFILE'); | ||
}); | ||
} | ||
|
||
} else { | ||
// Limit the number of open files, to force workers to fail. | ||
let testCmd = `ulimit -n ${OPENFILES} && `; | ||
testCmd += `${process.execPath} ${__filename} child`; | ||
const cp = child_process.exec(testCmd); | ||
|
||
// Turn on the child streams for debugging purposes. | ||
let stdout = ''; | ||
cp.stdout.setEncoding('utf8'); | ||
cp.stdout.on('data', (chunk) => { | ||
stdout += chunk; | ||
}); | ||
let stderr = ''; | ||
cp.stderr.setEncoding('utf8'); | ||
cp.stderr.on('data', (chunk) => { | ||
stderr += chunk; | ||
}); | ||
|
||
cp.on('exit', common.mustCall((code, signal) => { | ||
console.log(`child stdout: ${stdout}\n`); | ||
console.log(`child stderr: ${stderr}\n`); | ||
assert.strictEqual(code, 0); | ||
assert.strictEqual(signal, null); | ||
})); | ||
} |