Files
KDL_WORK/kdl-wasm/web/scripts/run-abb120-spec-suite.ts
2026-06-28 20:58:18 +08:00

102 lines
4.2 KiB
TypeScript

import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
import { dirname, join, resolve } from "node:path";
import { fileURLToPath } from "node:url";
import { runAbb120SpecSuite } from "../src/suites/abb120SpecSuite.js";
const webRoot = resolve(dirname(fileURLToPath(import.meta.url)), "..");
const specRoot = join(webRoot, "tests", "fixtures", "abb120", "spec-programs");
const manifest = JSON.parse(readFileSync(join(specRoot, "manifest.json"), "utf8"));
const programs = manifest.programs.map((entry: { program_id: string; file: string }) => ({
program_id: entry.program_id,
file: entry.file,
text: readFileSync(join(specRoot, entry.file), "utf8")
}));
const job = runAbb120SpecSuite(manifest, programs, {
gitRevision: process.env.GIT_REVISION ?? "working-tree"
});
const outputRoot = resolve(webRoot, "test-results", "abb120-spec", job.job_id);
mkdirSync(outputRoot, { recursive: true });
writeFileSync(join(outputRoot, "manifest.json"), `${JSON.stringify(manifest, null, 2)}\n`);
writeFileSync(join(outputRoot, "job.json"), `${JSON.stringify(job, null, 2)}\n`);
writeFileSync(join(outputRoot, "report.json"), `${JSON.stringify(reportJson(job), null, 2)}\n`);
writeFileSync(join(outputRoot, "report.html"), reportHtml(job));
for (const program of job.programs) {
const programDir = join(outputRoot, "programs", program.program_id);
mkdirSync(programDir, { recursive: true });
writeFileSync(join(programDir, "compile.json"), `${JSON.stringify(program.compile, null, 2)}\n`);
writeFileSync(join(programDir, "controller.json"), `${JSON.stringify(program.controller ?? {}, null, 2)}\n`);
writeFileSync(join(programDir, "motion-queue.json"), `${JSON.stringify(program.motionQueue ?? {}, null, 2)}\n`);
writeFileSync(join(programDir, "trace.json"), `${JSON.stringify(program.trace ?? [], null, 2)}\n`);
writeFileSync(join(programDir, "io.json"), `${JSON.stringify(program.io ?? {}, null, 2)}\n`);
writeFileSync(join(programDir, "trajectory.json"), `${JSON.stringify(program.trajectory ?? {}, null, 2)}\n`);
writeFileSync(join(programDir, "post-report.json"), `${JSON.stringify(program.post ?? {}, null, 2)}\n`);
writeFileSync(join(programDir, "roundtrip.json"), `${JSON.stringify(program.roundtrip ?? {}, null, 2)}\n`);
}
console.log(JSON.stringify({
job_id: job.job_id,
outputRoot,
programs: job.programs.length,
missingSections: job.coverage.missingSections
}, null, 2));
function reportJson(job: ReturnType<typeof runAbb120SpecSuite>) {
return {
job_id: job.job_id,
suite_id: job.suite_id,
robot_id: job.robot_id,
coverage: job.coverage,
summary: {
programs: job.programs.length,
pass: job.programs.filter((program) => program.status === "pass").length,
diagnostic: job.programs.filter((program) => program.status === "diagnostic").length,
fail: job.programs.filter((program) => program.status === "fail").length
},
diagnostics: job.programs.flatMap((program) =>
program.diagnostics.map((diagnostic) => ({
program_id: program.program_id,
...diagnostic
}))
)
};
}
function reportHtml(job: ReturnType<typeof runAbb120SpecSuite>): string {
const rows = job.programs.map((program) =>
`<tr><td>${escapeHtml(program.program_id)}</td><td>${escapeHtml(program.coverage_level)}</td><td>${escapeHtml(program.status)}</td><td>${program.diagnostics.length}</td></tr>`
).join("\n");
return `<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>${escapeHtml(job.job_id)}</title>
<style>
body { font-family: Arial, sans-serif; margin: 24px; color: #1f2933; }
table { border-collapse: collapse; width: 100%; }
th, td { border: 1px solid #ccd5dd; padding: 8px; text-align: left; }
th { background: #eef2f4; }
</style>
</head>
<body>
<h1>${escapeHtml(job.job_id)}</h1>
<p>Suite ${escapeHtml(job.suite_id)} / Robot ${escapeHtml(job.robot_id)}</p>
<p>Covered sections: ${job.coverage.coveredSections.join(", ")}</p>
<table>
<thead><tr><th>Program</th><th>Layer</th><th>Status</th><th>Diagnostics</th></tr></thead>
<tbody>${rows}</tbody>
</table>
</body>
</html>
`;
}
function escapeHtml(value: unknown): string {
return String(value)
.replaceAll("&", "&amp;")
.replaceAll("<", "&lt;")
.replaceAll(">", "&gt;")
.replaceAll("\"", "&quot;");
}