Files
suaveplan/packages/security-stack/security/tpm-struct/src/errors/error-codes.test.ts
2026-05-27 23:47:53 +01:00

154 lines
5.3 KiB
TypeScript

import { readFileSync } from "node:fs";
import { join } from "node:path";
import { SuaveplanError } from "@suaveplan/error";
import { describe, expect, expectTypeOf, it } from "@suaveplan/testing/runner";
import {
TPM_STRUCT_CODES,
TpmStructError,
type TpmStructErrorCode,
tpmStructError,
} from "./error-codes.js";
const SRC_ROOT = join(import.meta.dirname, "..");
describe("TPM_STRUCT_CODES", () => {
it("contains exactly the 10 documented codes", { timeout: 5000 }, () => {
const keys = Object.keys(TPM_STRUCT_CODES).sort();
expect(keys).toEqual([
"ALG_UNSUPPORTED",
"ATTEST_TYPE_UNSUPPORTED",
"CURVE_UNSUPPORTED",
"MAGIC_INVALID",
"MALFORMED",
"NAME_ALG_NULL",
"OBJECT_ATTRIBUTES_RESERVED_NONZERO",
"PARAMETERS_INVALID",
"TRUNCATED",
"TYPE_MISMATCH",
]);
for (const k of keys) {
expect(TPM_STRUCT_CODES[k as keyof typeof TPM_STRUCT_CODES]).toBe(
`TPM_STRUCT.${k}`
);
}
});
it("every TPM_STRUCT code reachable from a production path", {
timeout: 5000,
}, () => {
const sources = readSrcSources(SRC_ROOT);
for (const code of Object.values(TPM_STRUCT_CODES)) {
const reason = (code as string).split(".")[1] as string;
const found = sources.some(({ body }) => body.includes(reason));
expect(found, `code ${code} not referenced in src/`).toBe(true);
}
});
it("literal union pins to registry keys", { timeout: 5000 }, () => {
expectTypeOf<TpmStructErrorCode>().toEqualTypeOf<
| "TPM_STRUCT.MAGIC_INVALID"
| "TPM_STRUCT.TRUNCATED"
| "TPM_STRUCT.ALG_UNSUPPORTED"
| "TPM_STRUCT.CURVE_UNSUPPORTED"
| "TPM_STRUCT.TYPE_MISMATCH"
| "TPM_STRUCT.MALFORMED"
| "TPM_STRUCT.NAME_ALG_NULL"
| "TPM_STRUCT.ATTEST_TYPE_UNSUPPORTED"
| "TPM_STRUCT.PARAMETERS_INVALID"
| "TPM_STRUCT.OBJECT_ATTRIBUTES_RESERVED_NONZERO"
>();
});
});
describe("TpmStructError", () => {
it("instances carry the TPM_STRUCT.* code literal", {
timeout: 5000,
}, () => {
const err = tpmStructError(TPM_STRUCT_CODES.MAGIC_INVALID, "test");
expect(err).toBeInstanceOf(TpmStructError);
expect(err).toBeInstanceOf(SuaveplanError);
expect(err.code).toBe("TPM_STRUCT.MAGIC_INVALID");
expect(err.message).toContain("TPM_STRUCT.MAGIC_INVALID");
});
it("threads structured detail through the cause chain", {
timeout: 5000,
}, () => {
const err = tpmStructError(TPM_STRUCT_CODES.TRUNCATED, "short", {
cursor: 5,
requested: 4,
});
const cause = (
err as unknown as {
cause: Error & { detail?: Record<string, unknown> };
}
).cause;
expect(cause).toBeInstanceOf(Error);
expect(cause?.detail).toEqual({ cursor: 5, requested: 4 });
});
it("constructor without options has no cause", { timeout: 5000 }, () => {
const err = new TpmStructError(TPM_STRUCT_CODES.MALFORMED, "no opts");
expect(err.code).toBe("TPM_STRUCT.MALFORMED");
expect((err as unknown as { cause?: unknown }).cause).toBeUndefined();
});
it("constructor accepts an Error cause directly", {
timeout: 5000,
}, () => {
const inner = new Error("inner");
const err = new TpmStructError(TPM_STRUCT_CODES.MALFORMED, "outer", {
cause: inner,
});
expect((err as unknown as { cause: Error }).cause).toBe(inner);
});
it("constructor silently drops non-Error causes", {
timeout: 5000,
}, () => {
const err = new TpmStructError(TPM_STRUCT_CODES.MALFORMED, "outer", {
cause: "string-not-error",
});
expect((err as unknown as { cause?: unknown }).cause).toBeUndefined();
});
it("tpmStructError without detail has no cause", {
timeout: 5000,
}, () => {
const err = tpmStructError(TPM_STRUCT_CODES.MALFORMED, "bare");
expect((err as unknown as { cause?: unknown }).cause).toBeUndefined();
});
});
type SrcSource = { path: string; body: string };
function readSrcSources(root: string): SrcSource[] {
const out: SrcSource[] = [];
// biome lint hint: this is a test helper; readdirSync is the simplest walker
const fs = require("node:fs") as typeof import("node:fs");
function walk(dir: string): void {
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
const full = join(dir, entry.name);
if (entry.isDirectory()) {
if (
entry.name === "__fixtures__" ||
entry.name === "__benchmarks__" ||
entry.name === "__integration__"
) {
continue;
}
walk(full);
} else if (
entry.name.endsWith(".ts") &&
!entry.name.endsWith(".test.ts") &&
!entry.name.endsWith(".types.ts") &&
!entry.name.endsWith(".bench.ts")
) {
out.push({ path: full, body: readFileSync(full, "utf8") });
}
}
}
walk(root);
return out;
}