112 lines
3.3 KiB
TypeScript
112 lines
3.3 KiB
TypeScript
import { afterEach, expect, it, vi } from "vitest";
|
|
|
|
import { createCli } from "../../src/cli.js";
|
|
import { CLI_COMMANDS } from "../../src/cliCommandNames.js";
|
|
import * as composition from "../../src/composition/binaryDiagnostics.js";
|
|
import { BinaryLayoutService } from "../../src/application/binaryDiagnostics/BinaryLayoutService.js";
|
|
import { RecordedCrashService } from "../../src/application/binaryDiagnostics/RecordedCrashService.js";
|
|
import { AnalysisOutputError } from "../../src/domain/analysisErrorCore.js";
|
|
import { ProviderCleanupError } from "../../src/domain/providerCleanupError.js";
|
|
import { err } from "../../src/domain/result.js";
|
|
import { analysisErrorWithCleanupFailure } from "../../src/domain/analysisErrorCleanup.js";
|
|
|
|
const exitCode = process.exitCode;
|
|
afterEach(() => {
|
|
vi.restoreAllMocks();
|
|
process.exitCode = exitCode;
|
|
});
|
|
|
|
it.each(["layout", "recorded"] as const)(
|
|
"projects the final owned outcome through the public CLI: %s",
|
|
async (scenario) => {
|
|
const primary = new AnalysisOutputError(
|
|
"inspect_binary_layout",
|
|
"fixture decoder output overflow",
|
|
{
|
|
capturedOutput: {
|
|
stdout: "partial original output",
|
|
stderr: "warning",
|
|
truncated: true,
|
|
},
|
|
},
|
|
);
|
|
const cleanup = new ProviderCleanupError(
|
|
"fixture-decoder",
|
|
["owned-process", "/retained/runtime"],
|
|
{ reason: "fixture process inspection still denied" },
|
|
);
|
|
const inspectAndClose = vi.fn(async () =>
|
|
err(
|
|
analysisErrorWithCleanupFailure(
|
|
primary,
|
|
cleanup,
|
|
"inspect_binary_layout",
|
|
),
|
|
),
|
|
);
|
|
const identity = {
|
|
id: "fixture-decoder",
|
|
name: "Fixture decoder",
|
|
version: "1",
|
|
};
|
|
if (scenario === "layout")
|
|
vi.spyOn(composition, "createBinaryLayoutService").mockReturnValue(
|
|
new BinaryLayoutService({
|
|
identity,
|
|
inspect: () => {
|
|
throw new Error("CLI must request a terminal inspection");
|
|
},
|
|
inspectAndClose,
|
|
}),
|
|
);
|
|
else
|
|
vi.spyOn(composition, "createRecordedCrashService").mockReturnValue(
|
|
new RecordedCrashService({
|
|
identity,
|
|
inspect: () => {
|
|
throw new Error("CLI must request a terminal inspection");
|
|
},
|
|
inspectAndClose,
|
|
}),
|
|
);
|
|
|
|
const cli = createCli({});
|
|
let stdout = "";
|
|
await cli.serve(
|
|
[
|
|
scenario === "layout"
|
|
? CLI_COMMANDS.inspectBinaryLayout
|
|
: CLI_COMMANDS.inspectRecordedCrash,
|
|
"/selected/fixture.elf",
|
|
"--json",
|
|
],
|
|
{
|
|
env: {},
|
|
stdout: (text) => {
|
|
stdout += text;
|
|
},
|
|
exit: () => undefined,
|
|
},
|
|
);
|
|
const output: unknown = JSON.parse(stdout);
|
|
expect(output).toMatchObject({
|
|
code: "cleanup_incomplete",
|
|
details: {
|
|
cleanup: "incomplete",
|
|
resources: ["owned-process", "/retained/runtime"],
|
|
captured_output: {
|
|
stdout: "partial original output",
|
|
stderr: "warning",
|
|
truncated: true,
|
|
},
|
|
diagnostics: {
|
|
primary_error: { code: "unreadable_output" },
|
|
cleanup_error: { code: "cleanup_incomplete" },
|
|
},
|
|
},
|
|
});
|
|
expect(inspectAndClose).toHaveBeenCalledOnce();
|
|
expect(process.exitCode).toBe(1);
|
|
},
|
|
);
|