Files
workinf_Blender_Wasm/web/tests/unit/asset-preview-identity.test.mjs
mes123456 5a11045ca5
Some checks failed
M6 deployable RC / quick (push) Has been cancelled
M6 deployable RC / chromium (push) Has been cancelled
M6 deployable RC / release (push) Has been cancelled
Advance Blender 5.2 web parity through M12-03D
2026-08-17 17:30:27 -04:00

71 lines
4.3 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 { pathToFileURL } from "node:url";
import test from "node:test";
import ts from "typescript";
const root = path.resolve(import.meta.dirname, "../../..");
const temporary = fs.mkdtempSync(path.join(os.tmpdir(), "asset-preview-identity-unit-"));
const sourcePath = path.join(root, "web/protocol/asset-preview.ts");
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, []);
fs.writeFileSync(path.join(temporary, "asset-preview.mjs"), transpiled.outputText);
const preview = await import(pathToFileURL(path.join(temporary, "asset-preview.mjs")));
const manifest = JSON.parse(fs.readFileSync(path.join(root, "tests/golden/M12-02B/manifest.json"), "utf8"));
const golden = JSON.parse(fs.readFileSync(path.join(root, "tests/golden/M12-02B/identity.json"), "utf8"));
const sourceBytes = fs.readFileSync(path.join(root, manifest.artifacts.source.path));
const contentBytes = fs.readFileSync(path.join(root, manifest.artifacts.content.path));
const sha256 = (value) => crypto.createHash("sha256").update(value).digest("hex");
const stableJSON = (value) => Array.isArray(value)
? `[${value.map(stableJSON).join(",")}]`
: value && typeof value === "object"
? `{${Object.keys(value).sort().map((key) => `${JSON.stringify(key)}:${stableJSON(value[key])}`).join(",")}}`
: JSON.stringify(value);
test("M12-02B binds source, content, generator, protocol, and settings artifacts", () => {
assert.equal(manifest.task, "M12-02B");
assert.equal(manifest.enablingTask, true);
assert.equal(manifest.parityStateChange, false);
assert.equal(manifest.nextTask, "M12-02C");
for (const artifact of Object.values(manifest.artifacts)) {
assert.equal(sha256(fs.readFileSync(path.join(root, artifact.path))), artifact.sha256, artifact.path);
}
assert.equal(sha256(stableJSON(manifest.generatorSettings)), manifest.generatorSettingsSha256);
assert.equal(manifest.generatorSettingsSha256, golden.generator.settingsSha256);
});
test("M12-02B creates and parses the canonical preview identity", async () => {
const { identitySha256, ...base } = golden;
assert.deepEqual(await preview.createAssetPreviewIdentity(base), golden);
assert.deepEqual(await preview.parseAssetPreviewIdentity(golden), golden);
assert.equal(identitySha256, await preview.computeAssetPreviewIdentity(base));
assert.notEqual(golden.source.sha256, golden.content.sha256);
assert.deepEqual(await preview.verifyAssetPreviewIdentity(
golden,
sourceBytes.buffer.slice(sourceBytes.byteOffset, sourceBytes.byteOffset + sourceBytes.byteLength),
contentBytes.buffer.slice(contentBytes.byteOffset, contentBytes.byteOffset + contentBytes.byteLength),
golden.generator,
), golden);
});
test("M12-02B rejects independent source, content, generator, dimensions, and unknown-field drift", async () => {
const source = sourceBytes.buffer.slice(sourceBytes.byteOffset, sourceBytes.byteOffset + sourceBytes.byteLength);
const content = contentBytes.buffer.slice(contentBytes.byteOffset, contentBytes.byteOffset + contentBytes.byteLength);
const changedSource = source.slice(0); new Uint8Array(changedSource)[0] ^= 1;
const changedContent = content.slice(0); new Uint8Array(changedContent)[0] ^= 1;
await assert.rejects(preview.verifyAssetPreviewIdentity(golden, changedSource, content, golden.generator), { code: "ASSET_SOURCE_HASH_MISMATCH" });
await assert.rejects(preview.verifyAssetPreviewIdentity(golden, source, changedContent, golden.generator), { code: "ASSET_SOURCE_HASH_MISMATCH" });
await assert.rejects(preview.verifyAssetPreviewIdentity(golden, source, content, { ...golden.generator, settingsSha256: "f".repeat(64) }), { code: "ASSET_PREVIEW_IDENTITY_MISMATCH" });
await assert.rejects(preview.parseAssetPreviewIdentity({ ...golden, content: { ...golden.content, width: 9 } }), { code: "ASSET_PREVIEW_IDENTITY_MISMATCH" });
await assert.rejects(preview.parseAssetPreviewIdentity({ ...golden, future: true }), { code: "ASSET_MANIFEST_INVALID" });
});
test.after(() => fs.rmSync(temporary, { recursive: true, force: true }));