Checkpoint web parity through Chromium input tasks
This commit is contained in:
87
tools/web/check-io-format-receipt-freshness.mjs
Normal file
87
tools/web/check-io-format-receipt-freshness.mjs
Normal file
@@ -0,0 +1,87 @@
|
||||
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 repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../..");
|
||||
const parentPath = path.join(repoRoot, "tests/golden/M12-05E/bound-runtime-receipts.json");
|
||||
const freshPath = path.join(repoRoot, "tests/golden/M12-05F/fresh-runtime-receipts.json");
|
||||
const appFreshPath = path.join(repoRoot, "web/app/src/capabilities/io-format-runtime-receipts-freshness.json");
|
||||
const appExpectedPath = path.join(repoRoot, "web/app/src/capabilities/io-format-runtime-receipts-freshness-expected.json");
|
||||
const appPath = path.join(repoRoot, "web/app/src/app/App.tsx");
|
||||
const protocolPath = path.join(repoRoot, "web/protocol/io-format-receipt-freshness.ts");
|
||||
const temporary = fs.mkdtempSync(path.join(os.tmpdir(), "io-format-receipt-freshness-"));
|
||||
const sha256 = (bytes) => crypto.createHash("sha256").update(bytes).digest("hex");
|
||||
const stableValue = (value) => Array.isArray(value) ? value.map(stableValue) : value && typeof value === "object" ? Object.fromEntries(Object.keys(value).sort().map((key) => [key, stableValue(value[key])])) : value;
|
||||
const stableSha256 = (value) => sha256(JSON.stringify(stableValue(value)));
|
||||
|
||||
function transpile(sourcePath, outputName, replacements = []) {
|
||||
const transpiled = ts.transpileModule(fs.readFileSync(sourcePath, "utf8"), { compilerOptions: { module: ts.ModuleKind.ES2022, target: ts.ScriptTarget.ES2022 }, fileName: sourcePath, reportDiagnostics: true });
|
||||
assert.deepEqual(transpiled.diagnostics, []);
|
||||
let output = transpiled.outputText;
|
||||
for (const [from, to] of replacements) output = output.replaceAll(from, to);
|
||||
const outputPath = path.join(temporary, outputName);
|
||||
fs.writeFileSync(outputPath, output);
|
||||
return outputPath;
|
||||
}
|
||||
|
||||
try {
|
||||
const parentBytes = fs.readFileSync(parentPath);
|
||||
const bound = JSON.parse(parentBytes);
|
||||
const freshBytes = fs.readFileSync(freshPath);
|
||||
const fresh = JSON.parse(freshBytes);
|
||||
assert.deepEqual(fs.readFileSync(appFreshPath), freshBytes, "App freshness receipt drifted from golden");
|
||||
const appExpected = JSON.parse(fs.readFileSync(appExpectedPath));
|
||||
const runtimeModule = transpile(path.join(repoRoot, "web/protocol/io-format-runtime-receipt.ts"), "io-format-runtime-receipt.mjs");
|
||||
const bindingModule = transpile(path.join(repoRoot, "web/protocol/io-format-receipt-binding.ts"), "io-format-receipt-binding.mjs");
|
||||
const protocolModule = transpile(protocolPath, "io-format-receipt-freshness.mjs", [["./io-format-receipt-binding\"", "./io-format-receipt-binding.mjs\""], ["./io-format-runtime-receipt\"", "./io-format-runtime-receipt.mjs\""]]);
|
||||
const protocol = await import(pathToFileURL(protocolModule));
|
||||
const expected = {
|
||||
parentBindingSha256: sha256(parentBytes),
|
||||
parentReceiptSetSha256: bound.parentReceiptSetSha256,
|
||||
inventorySha256: bound.inventorySha256,
|
||||
boundReceiptSetSha256: stableSha256(bound),
|
||||
runtimeSha256: stableSha256(bound.runtime),
|
||||
runtime: bound.runtime,
|
||||
receiptIdentities: bound.receipts,
|
||||
};
|
||||
assert.equal(fresh.parentBindingSha256, expected.parentBindingSha256);
|
||||
assert.equal(fresh.boundReceiptSetSha256, expected.boundReceiptSetSha256);
|
||||
assert.equal(fresh.runtimeSha256, expected.runtimeSha256);
|
||||
assert.deepEqual(appExpected, {
|
||||
parentBindingSha256: expected.parentBindingSha256,
|
||||
parentReceiptSetSha256: expected.parentReceiptSetSha256,
|
||||
inventorySha256: expected.inventorySha256,
|
||||
boundReceiptSetSha256: expected.boundReceiptSetSha256,
|
||||
runtimeSha256: expected.runtimeSha256,
|
||||
runtime: expected.runtime,
|
||||
receiptIdentities: expected.receiptIdentities,
|
||||
});
|
||||
const appSource = fs.readFileSync(appPath, "utf8");
|
||||
assert.match(appSource, /resolveFreshIOFormatRuntimeRoute\(IO_FORMAT_RUNTIME_RECEIPTS, IO_FORMAT_RUNTIME_RECEIPT_EXPECTED/);
|
||||
await protocol.verifyIOFormatReceiptFreshness(fresh, expected);
|
||||
assert.equal(protocol.resolveFreshIOFormatRuntimeRoute(fresh, expected, { format: "GLB", operation: "EXPORT" }).status, "READY");
|
||||
assert.equal(protocol.resolveFreshIOFormatRuntimeRoute(fresh, expected, { format: "USD", operation: "EXPORT" }).status, "BLOCKED");
|
||||
|
||||
const forged = structuredClone(fresh);
|
||||
forged.bound.receipts[0].operator = "forged.operator";
|
||||
await assert.rejects(() => protocol.verifyIOFormatReceiptFreshness(forged, expected), (error) => error.reason === "RECEIPT_FORGED");
|
||||
const stale = structuredClone(fresh);
|
||||
stale.bound.inventorySha256 = "a".repeat(64);
|
||||
assert.equal(protocol.resolveFreshIOFormatRuntimeRoute(stale, expected, { format: "GLB", operation: "EXPORT" }).reason, "RECEIPT_STALE");
|
||||
const crossVersion = structuredClone(fresh);
|
||||
crossVersion.bound.runtime.versionTuple = [5, 3, 0];
|
||||
assert.equal(protocol.resolveFreshIOFormatRuntimeRoute(crossVersion, expected, { format: "GLB", operation: "EXPORT" }).reason, "RECEIPT_CROSS_VERSION");
|
||||
|
||||
const regenerated = path.join(temporary, "fresh-runtime-receipts.json");
|
||||
execFileSync(process.execPath, [path.join(repoRoot, "tools/web/generate-io-format-receipt-freshness.mjs"), "--output", regenerated], { cwd: repoRoot });
|
||||
assert.deepEqual(fs.readFileSync(regenerated), freshBytes, "freshness receipt is not deterministic");
|
||||
process.stdout.write("io-format-receipt-freshness-ok receipts=14 forged=BLOCKED stale=BLOCKED cross-version=BLOCKED deterministic=true\n");
|
||||
}
|
||||
finally {
|
||||
fs.rmSync(temporary, { recursive: true, force: true });
|
||||
}
|
||||
Reference in New Issue
Block a user