83 lines
2.2 KiB
TypeScript
83 lines
2.2 KiB
TypeScript
export type GateStepExpectation =
|
|
| Readonly<{ kind: "pass" }>
|
|
| Readonly<{
|
|
kind: "fail";
|
|
expectedExitCode: number;
|
|
expectedDiagnosticId: string;
|
|
}>;
|
|
|
|
export type GateProcessResult = Readonly<{
|
|
status: number | null;
|
|
signal: string | null;
|
|
stdout: string;
|
|
stderr: string;
|
|
error?: Readonly<{ code?: string }>;
|
|
}>;
|
|
|
|
export type GateStepClassification =
|
|
| Readonly<{
|
|
kind: "EXPECTED_PASS" | "EXPECTED_FAILURE";
|
|
expectationMet: true;
|
|
}>
|
|
| Readonly<{
|
|
kind: "UNEXPECTED_EXIT";
|
|
expectationMet: false;
|
|
}>
|
|
| Readonly<{
|
|
kind: "UNEXPECTED_DIAGNOSTIC";
|
|
expectationMet: false;
|
|
}>
|
|
| Readonly<{
|
|
kind: "INFRASTRUCTURE_FAILURE";
|
|
expectationMet: false;
|
|
detail: string;
|
|
}>;
|
|
|
|
/** A negative fixture passes only with its registered exit and diagnostic. */
|
|
export function classifyGateStepResult(
|
|
expectation: GateStepExpectation,
|
|
result: GateProcessResult,
|
|
): GateStepClassification {
|
|
const errorCode = result.error?.code;
|
|
const spawnFailed = result.error !== undefined;
|
|
if (spawnFailed || result.signal || result.status === null) {
|
|
return Object.freeze({
|
|
kind: "INFRASTRUCTURE_FAILURE" as const,
|
|
expectationMet: false as const,
|
|
detail:
|
|
errorCode ??
|
|
result.signal ??
|
|
(spawnFailed ? "SPAWN_ERROR" : "NO_EXIT_STATUS"),
|
|
});
|
|
}
|
|
if (expectation.kind === "pass" && result.status === 0) {
|
|
return Object.freeze({
|
|
kind: "EXPECTED_PASS" as const,
|
|
expectationMet: true as const,
|
|
});
|
|
}
|
|
if (expectation.kind === "fail") {
|
|
if (result.status !== expectation.expectedExitCode) {
|
|
return Object.freeze({
|
|
kind: "UNEXPECTED_EXIT" as const,
|
|
expectationMet: false as const,
|
|
});
|
|
}
|
|
const diagnosticOutput = `${result.stdout}\n${result.stderr}`;
|
|
if (!diagnosticOutput.includes(expectation.expectedDiagnosticId)) {
|
|
return Object.freeze({
|
|
kind: "UNEXPECTED_DIAGNOSTIC" as const,
|
|
expectationMet: false as const,
|
|
});
|
|
}
|
|
return Object.freeze({
|
|
kind: "EXPECTED_FAILURE" as const,
|
|
expectationMet: true as const,
|
|
});
|
|
}
|
|
return Object.freeze({
|
|
kind: "UNEXPECTED_EXIT" as const,
|
|
expectationMet: false as const,
|
|
});
|
|
}
|