Files
scriptc/tests/harness/node-parallel-runner.test.ts
T
Chris Tate d813fdafd3 Compare termination signals and resolve the Node checkout path in the test/parallel runner
A run that a signal ends has a null exit code, so the runner recorded a
pass when Node and the executable ended by different signals, or when one
ended by a signal and the other with an exit code compared as null. The
verdict now compares both the exit code and the signal (verdict.mjs), and
records Node's signal in nodeExit as it does for the executable.

A relative --node path also made the minimal lane's fixtures symlink
relative to the copied tree, where it does not resolve. The checkout path
is now resolved first.

tests/harness/node-parallel-runner.test.ts covers both: the termination
comparison, and a relative --node path whose fixtures resolve from the
minimal tree.
2026-10-24 16:00:06 -05:00

53 lines
2.4 KiB
TypeScript

import { spawnSync } from "node:child_process";
import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join, relative, resolve } from "node:path";
import { afterAll, expect, test } from "vitest";
// @ts-expect-error -- a plain ESM helper of the runner script
import { sameTermination, termination } from "../node-parallel/verdict.mjs";
const repo = resolve(import.meta.dirname, "../..");
const scratch = mkdtempSync(join(tmpdir(), "scriptc-node-parallel-"));
afterAll(() => rmSync(scratch, { recursive: true, force: true }));
test("runs that end by different signals, or by a signal and an exit, differ", () => {
expect(sameTermination({ code: 0, signal: null }, { code: 0, signal: null })).toBe(true);
expect(
sameTermination({ code: null, signal: "SIGABRT" }, { code: null, signal: "SIGABRT" }),
).toBe(true);
expect(
sameTermination({ code: null, signal: "SIGABRT" }, { code: null, signal: "SIGSEGV" }),
).toBe(false);
expect(sameTermination({ code: 1, signal: null }, { code: null, signal: "SIGKILL" })).toBe(false);
expect(sameTermination({ code: 0, signal: null }, { code: 1, signal: null })).toBe(false);
expect(termination({ code: null, signal: "SIGSEGV" })).toBe("SIGSEGV");
expect(termination({ code: 0, signal: null })).toBe(0);
});
test("a relative --node path links the checkout's fixtures into the minimal tree", () => {
const checkout = join(scratch, "node");
mkdirSync(join(checkout, "test", "parallel"), { recursive: true });
mkdirSync(join(checkout, "test", "fixtures"), { recursive: true });
mkdirSync(join(checkout, "test", "common"), { recursive: true });
writeFileSync(join(checkout, "test", "fixtures", "marker.txt"), "fixture\n");
writeFileSync(join(checkout, "test", "common", "fixtures.js"), "module.exports = {};\n");
const out = join(scratch, "out");
const result = spawnSync(
process.execPath,
[
join(repo, "tests/node-parallel/run.mjs"),
"--node",
relative(scratch, checkout),
"--pattern",
"^no-such-test$",
"--out",
out,
],
{ cwd: scratch, encoding: "utf8" },
);
expect(result.status, result.stderr).toBe(0);
const linked = join(out, "tree", "test", "fixtures", "marker.txt");
expect(existsSync(linked)).toBe(true);
expect(readFileSync(linked, "utf8")).toBe("fixture\n");
});