37 lines
3.2 KiB
JavaScript
37 lines
3.2 KiB
JavaScript
import assert from "node:assert/strict";
|
|
import crypto from "node:crypto";
|
|
import fs from "node:fs";
|
|
import os from "node:os";
|
|
import path from "node:path";
|
|
import { execFileSync } from "node:child_process";
|
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
import ts from "../../web/node_modules/typescript/lib/typescript.js";
|
|
|
|
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../..");
|
|
const inventoryPath = path.join(root, "tests/golden/M12-05A/format-inventory.json");
|
|
const parentPath = path.join(root, "tests/golden/M12-05D/runtime-receipts.json");
|
|
const boundPath = path.join(root, "tests/golden/M12-05E/bound-runtime-receipts.json");
|
|
const protocolPath = path.join(root, "web/protocol/io-format-receipt-binding.ts");
|
|
const temporary = fs.mkdtempSync(path.join(os.tmpdir(), "io-format-receipt-bindings-"));
|
|
const hashBytes = (value) => crypto.createHash("sha256").update(value).digest("hex");
|
|
const canonical = (value) => value === null || typeof value !== "object" ? JSON.stringify(value) : Array.isArray(value) ? `[${value.map(canonical).join(",")}]` : `{${Object.keys(value).sort().map((key) => `${JSON.stringify(key)}:${canonical(value[key])}`).join(",")}}`;
|
|
const hash = (value) => hashBytes(canonical(value));
|
|
try {
|
|
const inventoryBytes = fs.readFileSync(inventoryPath); const parentBytes = fs.readFileSync(parentPath); const boundBytes = fs.readFileSync(boundPath);
|
|
const inventory = JSON.parse(inventoryBytes); const parent = JSON.parse(parentBytes); const bound = JSON.parse(boundBytes);
|
|
const transpiled = ts.transpileModule(fs.readFileSync(protocolPath, "utf8"), { compilerOptions: { module: ts.ModuleKind.ES2022, target: ts.ScriptTarget.ES2022 }, fileName: protocolPath, reportDiagnostics: true });
|
|
assert.deepEqual(transpiled.diagnostics, []); const modulePath = path.join(temporary, "protocol.mjs"); fs.writeFileSync(modulePath, transpiled.outputText); const protocol = await import(pathToFileURL(modulePath));
|
|
const parsed = protocol.validateIOFormatBoundReceiptSet(bound, hashBytes(parentBytes), hashBytes(inventoryBytes));
|
|
assert.equal(parsed.receipts.length, 14);
|
|
const runtimeSha256 = hash(inventory.runtime);
|
|
for (const receipt of parsed.receipts) {
|
|
const source = inventory.formats.find((entry) => entry.format === receipt.format)[receipt.operation.toLowerCase()];
|
|
assert.equal(receipt.sourceSha256, hash({ format: receipt.format, family: receipt.family, operation: receipt.operation, operator: receipt.operator, registered: receipt.registered, rnaIdentifier: receipt.rnaIdentifier }));
|
|
assert.equal(receipt.settingsSha256, hash({ buildOption: receipt.buildOption, buildOptionEnabled: receipt.buildOptionEnabled, variants: receipt.variants, extensions: receipt.extensions, properties: source.properties }));
|
|
assert.equal(receipt.runtimeSha256, runtimeSha256);
|
|
}
|
|
const regenerated = path.join(temporary, "bound-runtime-receipts.json"); execFileSync(process.execPath, [path.join(root, "tools/web/generate-io-format-receipt-bindings.mjs"), "--output", regenerated], { cwd: root }); assert.deepEqual(fs.readFileSync(regenerated), boundBytes);
|
|
process.stdout.write("io-format-receipt-bindings-ok receipts=14 source-settings-runtime=bound deterministic=true\n");
|
|
}
|
|
finally { fs.rmSync(temporary, { recursive: true, force: true }); }
|