Advance Blender 5.2 web parity through M12-03D
This commit is contained in:
70
web/tests/unit/asset-preview-identity.test.mjs
Normal file
70
web/tests/unit/asset-preview-identity.test.mjs
Normal file
@@ -0,0 +1,70 @@
|
||||
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 }));
|
||||
Reference in New Issue
Block a user