89 lines
5.4 KiB
TypeScript
89 lines
5.4 KiB
TypeScript
import assert from "node:assert/strict";
|
|
import { mkdir, readFile, rm, writeFile } from "node:fs/promises";
|
|
import os from "node:os";
|
|
import path from "node:path";
|
|
import { test } from "bun:test";
|
|
|
|
import { runHwlabCli } from "../src/hwlab-cli-lib.ts";
|
|
import { artifactsFromKeilStatusForTest, extractKeilJobId, jobStatusCommandForTest } from "../src/hwlab-caserun-lib.ts";
|
|
|
|
test("hwlab-cli case prepare copies a case hwpod-spec into isolated run state", async () => {
|
|
const root = await mkdtempCaseRoot();
|
|
const caseRepo = path.join(root, "hwlab-case-registry");
|
|
const cwd = path.join(root, "hwlab");
|
|
const caseDir = path.join(caseRepo, "cases", "d601-f103-v2-compile");
|
|
try {
|
|
await mkdir(path.join(caseRepo, ".git"), { recursive: true });
|
|
await writeFile(path.join(caseRepo, ".git", "HEAD"), "ref: refs/heads/main\n", "utf8");
|
|
await mkdir(caseDir, { recursive: true });
|
|
await mkdir(cwd, { recursive: true });
|
|
await writeFile(path.join(caseDir, "case.json"), JSON.stringify({ contractVersion: "hwpod-case-v1", caseId: "d601-f103-v2-compile", hwpodSpec: "hwpod-spec.yaml", subject: { repo: "git@github.com:pikasTech/D601-HWLAB.git", ref: "main", subdir: "projects/01_baseline" } }, null, 2), "utf8");
|
|
await writeFile(path.join(caseDir, "hwpod-spec.yaml"), "kind: Hwpod\nspec:\n nodeBinding:\n nodeId: node-d601-f103-v2\n workspace:\n path: F:\\\\Work\\\\D601-HWLAB\n targetDevice:\n board: D601-F103-V2\n debugProbe:\n type: daplink\n ioProbe:\n uart:\n port: COM9\n", "utf8");
|
|
|
|
const result = await runHwlabCli(["case", "prepare", "d601-f103-v2-compile", "--case-repo", caseRepo, "--run-id", "run-test"], { cwd, now: () => "2026-06-05T00:00:00.000Z" });
|
|
|
|
assert.equal(result.exitCode, 0);
|
|
assert.equal(result.payload.action, "case.prepare.prepare");
|
|
assert.equal(result.payload.runId, "run-test");
|
|
assert.equal(result.payload.caseRepo, caseRepo);
|
|
assert.equal(result.payload.compileOnly, true);
|
|
assert.match(await readFile(path.join(cwd, ".state", "hwlab-cli", "caserun", "run-test", ".hwlab", "hwpod-spec.yaml"), "utf8"), /node-d601-f103-v2/u);
|
|
} finally {
|
|
await rm(root, { recursive: true, force: true });
|
|
}
|
|
});
|
|
|
|
test("case prepare uses the new registry by default and refuses the removed hwpod-cases path", async () => {
|
|
const root = await mkdtempCaseRoot();
|
|
const cwd = path.join(root, "hwlab");
|
|
const newRepo = path.join(root, "hwlab-case-registry");
|
|
const removedRepo = path.join(root, "hwpod-cases");
|
|
const caseId = "d601-f103-v2-compile";
|
|
try {
|
|
await createCaseRepo(newRepo, caseId);
|
|
await createCaseRepo(removedRepo, caseId);
|
|
await mkdir(cwd, { recursive: true });
|
|
|
|
const defaultResult = await runHwlabCli(["case", "prepare", caseId, "--run-id", "run-default"], { cwd, now: () => "2026-06-05T00:00:00.000Z" });
|
|
assert.equal(defaultResult.exitCode, 0);
|
|
assert.equal(defaultResult.payload.caseRepo, newRepo);
|
|
|
|
const removedResult = await runHwlabCli(["case", "prepare", caseId, "--case-repo", removedRepo], { cwd, now: () => "2026-06-05T00:00:00.000Z" });
|
|
assert.equal(removedResult.exitCode, 1);
|
|
assert.equal(removedResult.payload.error.code, "removed_case_repo_path");
|
|
assert.equal(removedResult.payload.error.details.standardCaseRepo, "/root/hwlab-case-registry");
|
|
} finally {
|
|
await rm(root, { recursive: true, force: true });
|
|
}
|
|
});
|
|
|
|
test("case run extracts Keil async job ids from hwpod-node output", () => {
|
|
const jobId = extractKeilJobId({ body: { results: [{ stdout: JSON.stringify({ ok: true, job_id: "20260605_203835_798515c0" }) }] } });
|
|
assert.equal(jobId, "20260605_203835_798515c0");
|
|
|
|
const nestedJobId = extractKeilJobId({ body: { results: [{ output: { stdout: JSON.stringify({ accepted: true, job_id: "20260605_210457_bdf3292a" }) } }] } });
|
|
assert.equal(nestedJobId, "20260605_210457_bdf3292a");
|
|
});
|
|
|
|
test("case run uses cmd.run command plus argv for Keil job-status", () => {
|
|
const command = jobStatusCommandForTest("py -3", "C:\\Users\\liang\\.agents\\skills\\keil\\keil-cli.py", "job-1");
|
|
assert.deepEqual(command, { command: "py", argv: ["-3", "C:\\Users\\liang\\.agents\\skills\\keil\\keil-cli.py", "job-status", "job-1"] });
|
|
});
|
|
|
|
test("case run exposes Keil hex and axf artifacts in evidence summary", () => {
|
|
assert.deepEqual(artifactsFromKeilStatusForTest({ result: { hex_file: "F:\\out.hex", axf_file: "F:\\out.axf" } }), ["F:\\out.hex", "F:\\out.axf"]);
|
|
});
|
|
|
|
async function mkdtempCaseRoot() {
|
|
return await import("node:fs/promises").then(({ mkdtemp }) => mkdtemp(path.join(os.tmpdir(), "hwlab-caserun-")));
|
|
}
|
|
|
|
async function createCaseRepo(caseRepo: string, caseId: string) {
|
|
const caseDir = path.join(caseRepo, "cases", caseId);
|
|
await mkdir(path.join(caseRepo, ".git"), { recursive: true });
|
|
await writeFile(path.join(caseRepo, ".git", "HEAD"), "ref: refs/heads/main\n", "utf8");
|
|
await mkdir(caseDir, { recursive: true });
|
|
await writeFile(path.join(caseDir, "case.json"), JSON.stringify({ contractVersion: "hwpod-case-v1", caseId, hwpodSpec: "hwpod-spec.yaml", subject: { repo: "git@github.com:pikasTech/D601-HWLAB.git", ref: "main", subdir: "projects/01_baseline" } }, null, 2), "utf8");
|
|
await writeFile(path.join(caseDir, "hwpod-spec.yaml"), "kind: Hwpod\nspec:\n nodeBinding:\n nodeId: node-d601-f103-v2\n workspace:\n path: F:\\\\Work\\\\D601-HWLAB\n targetDevice:\n board: D601-F103-V2\n debugProbe:\n type: daplink\n ioProbe:\n uart:\n port: COM9\n", "utf8");
|
|
}
|