Files
scriptc/tests/node-parallel/common/index.cjs
T
Chris Tate 37128308c3 Match Node's emitWarning, kill, chdir and userInfo behavior
process.emitWarning checks its arguments in Node's order: an options
object replaces type with `options.type || "Warning"` and code with
`options.code`, type and code are checked before the warning and for
Error warnings too, an empty type names the warning "Warning", and a
DeprecationWarning type returns at once under process.noDeprecation.
Wrong kinds throw ERR_INVALID_ARG_TYPE with Node's "Received ..." tail.
An instance of an Error subclass is an Error warning, and a typed record
in the options position is read as the options object. The default
report reads the warning's message, code and detail as property reads
do, so an Error subclass's own code is reported. A deprecation thrown
under process.throwDeprecation is thrown as the Error it encodes, so the
uncaught report names it.

process.kill throws ERR_UNKNOWN_SIGNAL for an unknown signal name, as
subprocess.kill does, and a failed kill(2) is Node's errnoException with
errno, code and syscall. A failed process.chdir names the working
directory as path and the target as dest.

os.userInfo() reads the passwd entry of the effective uid: uid and gid
are the entry's pw_uid and pw_gid (-1 on Windows), not the process ids.
os.homedir() answers $HOME whenever it is set, an empty value included.

The minimal test/common for Node's test/parallel files gains isAIX,
isIBMi and isSunOS.
2026-10-29 03:22:35 -05:00

139 lines
4.0 KiB
JavaScript

"use strict";
// A minimal test/common for building Node's test/parallel files with scriptc:
// the helpers those files use, with the semantics of Node's
// test/common/index.js. Add a helper here, with Node's semantics, when a
// lane's files need it.
const assert = require("assert");
const os = require("os");
const { inspect } = require("util");
const hasIntl = true;
const isDebug = false;
const isWindows = process.platform === "win32";
const isAIX = os.type() === "AIX";
const isIBMi = os.type() === "OS400";
const isSunOS = process.platform === "sunos";
const mustCallChecks = [];
function runCallChecks(exitCode) {
if (exitCode !== 0) return;
const failed = mustCallChecks.filter((context) => {
if ("minimum" in context) return context.actual < context.minimum;
return context.actual !== context.exact;
});
for (const context of failed) {
console.log(
"Mismatched %s function calls. Expected %s, actual %d.",
context.name,
String(context.exact ?? context.minimum),
context.actual,
);
}
if (failed.length) process.exit(1);
}
function noop() {}
function mustCallInner(fn, criteria, field) {
if (typeof fn === "number") {
criteria = fn;
fn = noop;
} else if (fn === undefined) {
fn = noop;
}
if (criteria === undefined) criteria = 1;
const context = { actual: 0, name: fn.name || "<anonymous>" };
context[field] = criteria;
if (mustCallChecks.length === 0) process.on("exit", runCallChecks);
mustCallChecks.push(context);
return function (...args) {
context.actual++;
return fn.apply(this, args);
};
}
function mustCall(fn, exact) {
return mustCallInner(fn, exact, "exact");
}
function mustCallAtLeast(fn, minimum) {
return mustCallInner(fn, minimum, "minimum");
}
function mustNotCall(msg) {
return function mustNotCall() {
assert.fail(msg || "function should not have been called");
};
}
function skip(msg) {
console.log(`1..0 # Skipped: ${msg}`);
process.exit(0);
}
function expectWarning(name, expected, code) {
if (typeof expected === "string") expected = [[expected, code]];
else if (expected.length !== 0 && !Array.isArray(expected[0]))
expected = [[expected[0], expected[1]]];
const check = mustCall((warning) => {
const [message, warningCode] = expected.shift();
assert.strictEqual(warning.name, name);
if (typeof message === "string") assert.strictEqual(warning.message, message);
else assert.match(warning.message, message);
assert.strictEqual(warning.code, warningCode);
}, expected.length);
process.on("warning", (warning) => {
if (warning.name !== name)
throw new TypeError(`"${warning.name}" was triggered without being expected.`);
check(warning);
});
}
function invalidArgTypeHelper(input) {
if (input == null) return ` Received ${input}`;
if (typeof input === "function") return ` Received function ${input.name}`;
if (typeof input === "object") {
const name = input.constructor?.name;
if (typeof name === "string" && name !== "") return ` Received an instance of ${name}`;
return ` Received ${inspect(input, { depth: -1 })}`;
}
let inspected = inspect(input, { colors: false });
if (inspected.length > 28) inspected = `${inspected.slice(inspected, 0, 25)}...`;
return ` Received type ${typeof input} (${inspected})`;
}
function spawnPromisified(...args) {
const { spawn } = require("child_process");
let stderr = "";
let stdout = "";
const child = spawn(...args);
child.stderr.setEncoding("utf8");
child.stderr.on("data", (data) => {
stderr += data;
});
child.stdout.setEncoding("utf8");
child.stdout.on("data", (data) => {
stdout += data;
});
return new Promise((resolve, reject) => {
child.on("close", (code, signal) => resolve({ code, signal, stderr, stdout }));
child.on("error", (code, signal) => reject({ code, signal, stderr, stdout }));
});
}
module.exports = {
hasIntl,
isAIX,
isDebug,
isIBMi,
isSunOS,
isWindows,
mustCall,
mustCallAtLeast,
mustNotCall,
skip,
expectWarning,
invalidArgTypeHelper,
spawnPromisified,
};