Miguel de Benito Delgado c14ca9e508 🚧 WIP 25.1 Cleanup.
More consistent args.
Avoid importing unnecessary namespaces.
Improve file write error handling.

AI-assisted-by: deepseek-flash, gpt-6.1-sol
2026-10-28 19:17:39 +01:00

686 lines
19 KiB
JavaScript

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
// Copyright (c) KALEIDOS SUBSIDIARY SL
// Opt-in: build the release runner and the test bundle first:
//
// pnpm run build:renderer-benchmarks:runner
// pnpm run build:renderer-benchmarks:tests
// RENDER_WASM_RUNNER_BOOT=target/performance/render-wasm/runner.cjs \
// node --test test/performance_tests/render_wasm/cli_integration.cjs
//
// The normal unit test build does not build this CLI.
const assert = require("node:assert/strict");
const { execFile } = require("node:child_process");
const { randomUUID } = require("node:crypto");
const fs = require("node:fs");
const os = require("node:os");
const path = require("node:path");
const { before, test } = require("node:test");
const { pathToFileURL } = require("node:url");
const { promisify } = require("node:util");
const execute = promisify(execFile);
const testOptions = { timeout: 60000 };
let bootstrap;
let frontendRoot;
let transit;
before(async () => {
assert.ok(
process.env.RENDER_WASM_RUNNER_BOOT,
"Set RENDER_WASM_RUNNER_BOOT to the release-compiled runner.cjs",
);
bootstrap = path.resolve(process.env.RENDER_WASM_RUNNER_BOOT);
assert.ok(
fs.existsSync(bootstrap) && fs.statSync(bootstrap).isFile(),
"Run pnpm run build:renderer-benchmarks:runner before the CLI tests",
);
bootstrap = fs.realpathSync(bootstrap);
frontendRoot = path.resolve(path.dirname(bootstrap), "../../..");
assert.ok(fs.statSync(path.join(frontendRoot, "deps.edn")).isFile());
assert.ok(
fs
.statSync(
path.join(frontendRoot, "performance", "benches", "render_wasm"),
)
.isDirectory(),
);
assert.ok(fs.statSync(path.join(frontendRoot, "node_modules")).isDirectory());
// Load the actual Transit JS library emitted by Shadow, without starting
// either the CLJS test runner or the production CLI in this process.
const transitModule = path.join(
frontendRoot,
"target/performance-tests/cljs-runtime/com.cognitect.transit.js",
);
assert.ok(
fs.existsSync(transitModule),
"Run pnpm run build:renderer-benchmarks:tests before the CLI tests",
);
await import(pathToFileURL(transitModule).href);
transit = globalThis.com.cognitect.transit;
});
function createFrontend(t) {
const temporary = fs.mkdtempSync(path.join(os.tmpdir(), "render-wasm-cli-"));
t.after(() => fs.rmSync(temporary, { recursive: true, force: true }));
const root = path.join(temporary, "frontend");
const managed = path.join(root, "target", "performance", "render-wasm");
const renderer = path.join(temporary, "render-wasm");
const runner = path.join(managed, "runner.cjs");
fs.mkdirSync(path.join(root, "performance", "benches", "render_wasm"), {
recursive: true,
});
fs.writeFileSync(path.join(root, "deps.edn"), "{}\n");
fs.mkdirSync(managed, { recursive: true });
fs.copyFileSync(bootstrap, runner);
fs.copyFileSync(
path.join(path.dirname(bootstrap), "commands.cjs"),
path.join(managed, "commands.cjs"),
);
fs.symlinkSync(
path.join(frontendRoot, "node_modules"),
path.join(root, "node_modules"),
"dir",
);
fs.mkdirSync(renderer);
fs.mkdirSync(path.join(managed, "compiler-cache"));
fs.writeFileSync(
path.join(managed, "compiler-cache", "retained.cache"),
"cache\n",
);
return {
managed,
runner,
compiler: path.join(renderer, "build"),
builds: path.join(managed, "builds"),
runs: path.join(managed, "runs"),
};
}
async function runCli(fixture, args) {
try {
const output = await execute(
process.execPath,
[...(fixture.nodeArgs ?? []), fixture.runner, ...args],
{
cwd: os.tmpdir(),
encoding: "utf8",
timeout: 15000,
killSignal: "SIGKILL",
maxBuffer: 1024 * 1024,
},
);
return { exitCode: 0, ...output };
} catch (error) {
// A timeout, signal or spawn failure must fail the test, rather than
// masquerade as the expected nonzero CLI exit.
if (!Number.isInteger(error.code) || error.killed || error.signal) {
throw error;
}
return {
exitCode: error.code,
stdout: error.stdout,
stderr: error.stderr,
};
}
}
function readManifest(file) {
return transit.reader("json").read(fs.readFileSync(file, "utf8"));
}
function manifestText(id, status, type) {
const k = transit.keyword;
return transit
.writer("json")
.write(
transit.map([
k("type"),
k(type),
k("schema-version"),
1,
k("id"),
id,
k("status"),
k(status),
]),
);
}
function seedBuilds(fixture) {
for (const status of ["building", "failed", "ready"]) {
const id = randomUUID();
const directory = path.join(fixture.builds, id);
fs.mkdirSync(directory, { recursive: true });
fs.writeFileSync(
path.join(directory, "build.transit"),
manifestText(id, status, "renderer-build"),
);
fs.writeFileSync(path.join(directory, "build.log"), `${status} build\n`);
}
}
function seedRuns(fixture) {
for (const status of ["complete", "failed"]) {
const id = randomUUID();
const directory = path.join(fixture.runs, id);
fs.mkdirSync(directory, { recursive: true });
fs.writeFileSync(
path.join(directory, "run.transit"),
manifestText(id, status, "renderer-run"),
);
}
}
function runFixtureText({
runId,
caseId,
value,
environment = { node: "v24" },
}) {
const k = transit.keyword;
const map = (pairs) => transit.map(pairs);
const metric = map([
k("value"),
value,
k("unit"),
k("ms"),
k("semantics"),
k("elapsed"),
k("basis"),
map([k("kind"), k("attempt-total")]),
k("zero-policy"),
k("positive"),
k("invalid-reason"),
null,
]);
const preparation = map([
k("preparation-id"),
`${runId}-preparation`,
k("case-id"),
k(caseId),
k("fingerprint"),
map([
k("encoding-version"),
1,
k("algorithm"),
k("sha-256"),
k("digest"),
"a".repeat(64),
]),
k("effective-graphics"),
map([k("webgl2"), true]),
k("diagnostics"),
map([]),
]);
const attempt = map([
k("ordinal"),
0,
k("case-id"),
k(caseId),
k("preparation-id"),
`${runId}-preparation`,
k("warmup?"),
false,
k("outcome"),
k("completed"),
k("metrics"),
map([k("elapsed"), metric]),
k("trace"),
map([]),
]);
const record = map([
k("type"),
k("run-record"),
k("schema-version"),
3,
k("run-id"),
runId,
k("started-at"),
"2026-10-26T00:00:00.000Z",
k("ended-at"),
"2026-10-26T00:01:00.000Z",
k("plan"),
map([
k("cases"),
[map([k("id"), k(caseId)])],
k("warmups"),
0,
k("repetitions"),
1,
k("timeout-policy"),
map([k("attempt-ms"), 30000]),
]),
k("metadata"),
map([
k("git"),
map([k("sha"), runId, k("dirty"), false]),
k("build"),
map([k("functional"), map([k("mode"), k("release")])]),
k("environment"),
map(
Object.entries(environment).flatMap(([key, entry]) => [k(key), entry]),
),
k("scored?"),
true,
k("diagnostics"),
map([]),
]),
k("analysis"),
map([
k("method-version"),
1,
k("draws"),
2000,
k("seed"),
1885695600,
k("confidence"),
0.95,
k("min-ci"),
10,
k("min-p95"),
100,
k("min-p99"),
500,
]),
k("preparations"),
[preparation],
k("attempts"),
[attempt],
k("remaining"),
map([k(caseId), map([k("warmups"), 0, k("repetitions"), 0])]),
k("termination"),
map([k("reason"), k("completed")]),
]);
return transit.writer("json").write(record);
}
function tree(directory) {
return fs
.readdirSync(directory, { withFileTypes: true })
.sort((a, b) => a.name.localeCompare(b.name))
.map((entry) => {
const file = path.join(directory, entry.name);
return [
entry.name,
entry.isDirectory() ? tree(file) : fs.readFileSync(file),
];
});
}
const failingCompiler = `#!/usr/bin/env node
const fs = require("node:fs");
const path = require("node:path");
const directory = path.dirname(process.env.FRONTEND_DEST);
fs.copyFileSync(
path.join(directory, "build.transit"),
path.join(directory, "before-compiler.transit")
);
fs.writeFileSync(
path.join(process.env.FRONTEND_DEST, "partial.js"),
"partial renderer output\\n"
);
process.stdout.write("compiler stdout before failure\\n");
process.stderr.write("compiler stderr before failure\\n");
process.exitCode = 23;
`;
test(
"build retains failure evidence and prints only its UUID",
testOptions,
async (t) => {
const fixture = createFrontend(t);
fs.writeFileSync(fixture.compiler, failingCompiler, { mode: 0o755 });
const args = ["build", "--build-timeout-ms", "10000"];
const result = await runCli(fixture, args);
assert.equal(result.exitCode, 1);
const id = result.stdout.trim();
assert.match(
id,
/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i,
);
assert.equal(result.stdout, `${id}\n`);
assert.deepEqual(fs.readdirSync(fixture.builds), [id]);
const directory = path.join(fixture.builds, id);
const logPath = path.join(directory, "build.log");
const initial = readManifest(
path.join(directory, "before-compiler.transit"),
);
const manifest = readManifest(path.join(directory, "build.transit"));
const k = transit.keyword;
assert.equal(initial.get(k("id")), id);
assert.equal(initial.get(k("status")).toString(), ":building");
assert.equal(manifest.get(k("id")), id);
assert.equal(manifest.get(k("status")).toString(), ":failed");
const failure = manifest.get(k("failure"));
assert.equal(failure.get(k("phase")).toString(), ":renderer");
assert.equal(
failure.get(k("cause"))[0].get(k("type")).toString(),
":process-exit",
);
assert.equal(
fs.readFileSync(path.join(directory, "renderer", "partial.js"), "utf8"),
"partial renderer output\n",
);
const log = fs.readFileSync(logPath, "utf8");
for (const output of [log, result.stderr]) {
assert.ok(output.includes("compiler stdout before failure\n"));
assert.ok(output.includes("compiler stderr before failure\n"));
assert.ok(output.includes("Preparation failed:"));
}
assert.match(result.stderr, /renderer build preparation failed/);
assert.match(
result.stderr,
/:type :benches.render-wasm.node.build\/preparation-failed/,
);
assert.ok(result.stderr.includes(`:build-id "${id}"`));
assert.ok(result.stderr.includes(`:log-path ${JSON.stringify(logPath)}`));
assert.match(result.stderr, /:phase :renderer/);
},
);
test("purge deletes only the selected artifacts", testOptions, async (t) => {
const fixture = createFrontend(t);
const retained = tree(fixture.managed);
seedBuilds(fixture);
seedRuns(fixture);
const runs = tree(fixture.runs);
assert.deepEqual(await runCli(fixture, ["purge", "--only-builds"]), {
exitCode: 0,
stdout: "",
stderr: "",
});
assert.equal(fs.existsSync(fixture.builds), false);
assert.deepEqual(tree(fixture.runs), runs);
assert.deepEqual(
tree(fixture.managed).filter(([name]) => name !== "runs"),
retained,
);
seedBuilds(fixture);
const builds = tree(fixture.builds);
assert.deepEqual(await runCli(fixture, ["purge", "--only-runs"]), {
exitCode: 0,
stdout: "",
stderr: "",
});
assert.equal(fs.existsSync(fixture.runs), false);
assert.deepEqual(tree(fixture.builds), builds);
assert.deepEqual(
tree(fixture.managed).filter(([name]) => name !== "builds"),
retained,
);
seedRuns(fixture);
assert.deepEqual(await runCli(fixture, ["purge"]), {
exitCode: 0,
stdout: "",
stderr: "",
});
assert.equal(fs.existsSync(fixture.builds), false);
assert.equal(fs.existsSync(fixture.runs), false);
assert.deepEqual(tree(fixture.managed), retained);
});
test(
"malformed purge categories leave all files intact",
testOptions,
async (t) => {
const fixture = createFrontend(t);
seedBuilds(fixture);
seedRuns(fixture);
const original = tree(fixture.managed);
for (const args of [
["purge", "--only-builds", "--only-runs"],
["purge", "--only-ready-builds"],
["purge", "--only-builds", "ready"],
]) {
const result = await runCli(fixture, args);
assert.equal(result.exitCode, 1, args.join(" "));
assert.equal(result.stdout, "");
assert.match(
result.stderr,
/:type :benches.render-wasm.node.runner\/invalid-args/,
);
assert.deepEqual(tree(fixture.managed), original, args.join(" "));
}
},
);
test(
"run validates an explicit output dir before preparing a build",
testOptions,
async (t) => {
const fixture = createFrontend(t);
const marker = path.join(fixture.managed, "compiler-ran");
fs.writeFileSync(
fixture.compiler,
`#!/usr/bin/env node
const fs = require("node:fs");
fs.writeFileSync(${JSON.stringify(marker)}, "ran");
`,
{ mode: 0o755 },
);
const output = path.join(fixture.managed, "existing-output");
fs.mkdirSync(output);
const original = tree(fixture.managed);
const result = await runCli(fixture, [
"run",
"--output-dir",
output,
"--warmups",
"0",
"--repetitions",
"1",
]);
assert.equal(result.exitCode, 1);
assert.equal(result.stdout, "");
assert.match(result.stderr, /output directory already exists/);
assert.equal(fs.existsSync(marker), false);
assert.deepEqual(tree(fixture.managed), original);
},
);
test(
"run rejects retained-build feature selection before any work",
testOptions,
async (t) => {
const fixture = createFrontend(t);
const marker = path.join(fixture.managed, "compiler-ran");
fs.writeFileSync(
fixture.compiler,
`#!/usr/bin/env node
const fs = require("node:fs");
fs.writeFileSync(${JSON.stringify(marker)}, "ran");
`,
{ mode: 0o755 },
);
const original = tree(fixture.managed);
const result = await runCli(fixture, [
"run",
"--build",
"retained-id",
"--features",
"functional",
]);
assert.equal(result.exitCode, 1);
assert.equal(result.stdout, "");
assert.match(result.stderr, /cannot be combined/);
assert.equal(fs.existsSync(marker), false);
assert.deepEqual(tree(fixture.managed), original);
},
);
test(
"help and compare work without a frontend checkout or execution dependencies",
testOptions,
async (t) => {
const temporary = fs.mkdtempSync(
path.join(os.tmpdir(), "render-wasm-offline-"),
);
t.after(() => fs.rmSync(temporary, { recursive: true, force: true }));
const runner = path.join(temporary, "runner.cjs");
const guard = path.join(temporary, "guard.cjs");
fs.copyFileSync(bootstrap, runner);
fs.symlinkSync(
path.join(frontendRoot, "node_modules"),
path.join(temporary, "node_modules"),
"dir",
);
fs.writeFileSync(
guard,
`
const Module = require("node:module");
const load = Module._load;
Module._load = function (id, ...args) {
if (["playwright", "http", "node:http", "child_process", "node:child_process"].includes(id)) {
throw new Error("Offline command imported execution dependency: " + id);
}
return load.call(this, id, ...args);
};
`,
);
const baseline = path.join(temporary, "baseline.transit");
const candidate = path.join(temporary, "candidate.transit");
fs.writeFileSync(
baseline,
runFixtureText({ runId: "baseline", caseId: "case/load", value: 10 }),
);
fs.writeFileSync(
candidate,
runFixtureText({ runId: "candidate", caseId: "case/load", value: 12 }),
);
const fixture = { runner, nodeArgs: ["--require", guard] };
const help = await runCli(fixture, ["--help"]);
assert.equal(help.exitCode, 0, help.stderr);
assert.match(help.stdout, /runner compare/);
const comparison = await runCli(fixture, ["compare", baseline, candidate]);
assert.equal(comparison.exitCode, 0, comparison.stderr);
assert.match(comparison.stdout, /median change/);
assert.equal(fs.existsSync(path.join(temporary, "commands.cjs")), false);
},
);
test(
"help lists run and compare without touching managed storage",
testOptions,
async (t) => {
const fixture = createFrontend(t);
const original = tree(fixture.managed);
const result = await runCli(fixture, ["--help"]);
assert.equal(result.exitCode, 0);
assert.match(result.stdout, /runner run/);
assert.match(result.stdout, /runner compare/);
assert.match(result.stdout, /--cases/);
assert.deepEqual(tree(fixture.managed), original);
},
);
test(
"compare reads saved run files without starting resources",
testOptions,
async (t) => {
const fixture = createFrontend(t);
const baseline = path.join(fixture.managed, "baseline.transit");
const candidate = path.join(fixture.managed, "candidate.transit");
fs.writeFileSync(
baseline,
runFixtureText({ runId: "baseline", caseId: "case/load", value: 10 }),
);
fs.writeFileSync(
candidate,
runFixtureText({ runId: "candidate", caseId: "case/load", value: 12 }),
);
const original = tree(fixture.managed);
const result = await runCli(fixture, ["compare", baseline, candidate]);
assert.equal(result.exitCode, 0);
assert.match(result.stdout, /Baseline/);
assert.match(result.stdout, /case\/load/);
assert.match(result.stdout, /median change/);
assert.deepEqual(tree(fixture.managed), original);
},
);
test(
"compare supports explicit pairs and force from the CLI",
testOptions,
async (t) => {
const fixture = createFrontend(t);
const baseline = path.join(fixture.managed, "baseline.transit");
const candidate = path.join(fixture.managed, "candidate.transit");
fs.writeFileSync(
baseline,
runFixtureText({ runId: "baseline", caseId: "a/pan", value: 10 }),
);
fs.writeFileSync(
candidate,
runFixtureText({
runId: "candidate",
caseId: "b/pan",
value: 12,
environment: { node: "v25" },
}),
);
const original = tree(fixture.managed);
const incompatible = await runCli(fixture, [
"compare",
baseline,
candidate,
]);
assert.equal(incompatible.exitCode, 1);
assert.deepEqual(tree(fixture.managed), original);
const forced = await runCli(fixture, [
"compare",
baseline,
candidate,
"--cases",
"a/pan,b/pan",
"--force",
]);
assert.equal(forced.exitCode, 0);
assert.match(forced.stdout, /FORCED COMPARISON/);
assert.match(forced.stdout, /Pair a\/pan,b\/pan/);
assert.deepEqual(tree(fixture.managed), original);
fs.writeFileSync(
candidate,
runFixtureText({
runId: "candidate",
caseId: "a/pan",
value: 12,
environment: { node: "v25" },
}),
);
const automatic = await runCli(fixture, [
"compare",
baseline,
candidate,
"--force",
]);
assert.equal(automatic.exitCode, 0);
assert.match(automatic.stdout, /FORCED COMPARISON/);
assert.match(automatic.stdout, /Pair a\/pan,a\/pan/);
},
);