102 lines
4.2 KiB
TypeScript
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("&", "&")
|
|
.replaceAll("<", "<")
|
|
.replaceAll(">", ">")
|
|
.replaceAll("\"", """);
|
|
}
|