Advance M8-M11 parity workflows
This commit is contained in:
66
web/tests/unit/server-render-job.test.mjs
Normal file
66
web/tests/unit/server-render-job.test.mjs
Normal file
@@ -0,0 +1,66 @@
|
||||
import assert from "node:assert/strict";
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import test from "node:test";
|
||||
import ts from "typescript";
|
||||
|
||||
const root = path.resolve(import.meta.dirname, "../../..");
|
||||
const sourcePath = path.join(root, "web/protocol/server-render-job.ts");
|
||||
const source = fs.readFileSync(sourcePath, "utf8").replace('import type { ErrorCode } from "./error";\n', "");
|
||||
const transpiled = ts.transpileModule(source, {
|
||||
compilerOptions: { module: ts.ModuleKind.ES2022, target: ts.ScriptTarget.ES2022 },
|
||||
fileName: sourcePath,
|
||||
reportDiagnostics: true,
|
||||
});
|
||||
assert.deepEqual(transpiled.diagnostics, []);
|
||||
const jobs = await import("data:text/javascript;base64," + Buffer.from(transpiled.outputText).toString("base64"));
|
||||
|
||||
const sourceBytes = new TextEncoder().encode("server-render-source-v1").buffer;
|
||||
const build = { version: "5.2.0", buildSha256: "a".repeat(64) };
|
||||
const settings = {
|
||||
renderEngine: "BLENDER_CYCLES",
|
||||
frameStart: 1,
|
||||
frameEnd: 1,
|
||||
resolutionX: 32,
|
||||
resolutionY: 32,
|
||||
resolutionPercentage: 100,
|
||||
samples: 4,
|
||||
outputMime: "image/png",
|
||||
transparent: false,
|
||||
};
|
||||
|
||||
test("M11-06 binds source bytes, Blender build and canonical render settings", async () => {
|
||||
const request = await jobs.createServerRenderJobRequest(sourceBytes, build, settings, { jobId: "render:test", sourceRevision: 7 });
|
||||
assert.equal(request.sourceBlendByteLength, sourceBytes.byteLength);
|
||||
assert.match(request.sourceBlendSha256, /^[a-f0-9]{64}$/);
|
||||
assert.match(request.settingsSha256, /^[a-f0-9]{64}$/);
|
||||
assert.match(request.requestSha256, /^[a-f0-9]{64}$/);
|
||||
assert.deepEqual(await jobs.verifyServerRenderJobRequest(request, sourceBytes), request);
|
||||
const reordered = await jobs.createServerRenderJobRequest(sourceBytes, build, { transparent: settings.transparent, ...settings }, { jobId: "render:test", sourceRevision: 7 });
|
||||
assert.equal(reordered.settingsSha256, request.settingsSha256);
|
||||
assert.equal(await jobs.createServerRenderJobKey(request), await jobs.createServerRenderJobKey(reordered));
|
||||
});
|
||||
|
||||
test("M11-06 verifies output hash and rejects every provenance drift", async () => {
|
||||
const request = await jobs.createServerRenderJobRequest(sourceBytes, build, settings, { jobId: "render:verify", sourceRevision: 2 });
|
||||
const output = Uint8Array.from([0x89, 0x50, 0x4e, 0x47, 0x00, 0x01]).buffer;
|
||||
const result = await jobs.createServerRenderJobResult(request, output);
|
||||
assert.equal(result.status, "SUCCEEDED");
|
||||
assert.deepEqual(await jobs.verifyServerRenderJobResult(result, request, output), result);
|
||||
await assert.rejects(jobs.verifyServerRenderJobRequest(request, Uint8Array.from([1, 2, 3]).buffer), { code: "SERVER_RENDER_SOURCE_HASH_MISMATCH" });
|
||||
await assert.rejects(jobs.verifyServerRenderJobResult(result, request, Uint8Array.from([9, 9]).buffer), { code: "SERVER_RENDER_OUTPUT_HASH_MISMATCH" });
|
||||
await assert.rejects(jobs.verifyServerRenderJobResult({ ...result, sourceBlendSha256: "b".repeat(64) }, request, output), { code: "SERVER_RENDER_BINDING_MISMATCH" });
|
||||
await assert.rejects(jobs.verifyServerRenderJobRequest({ ...request, blenderBuild: { ...build, buildSha256: "b".repeat(64) } }), { code: "SERVER_RENDER_REQUEST_HASH_MISMATCH" });
|
||||
await assert.rejects(jobs.createServerRenderJobRequest(sourceBytes, { ...build, version: "5.3.0" }, settings), { code: "SERVER_RENDER_BUILD_INVALID" });
|
||||
await assert.rejects(jobs.createServerRenderJobRequest(sourceBytes, build, { ...settings, samples: 0 }), { code: "SERVER_RENDER_SETTINGS_INVALID" });
|
||||
});
|
||||
|
||||
test("M11-06 rejects malformed result metadata and settings budget abuse", async () => {
|
||||
await assert.rejects(jobs.createServerRenderJobRequest(sourceBytes, build, { ...settings, payload: "x".repeat(300_000) }), { code: "SERVER_RENDER_SETTINGS_INVALID" });
|
||||
const request = await jobs.createServerRenderJobRequest(sourceBytes, build, settings);
|
||||
const result = await jobs.createServerRenderJobResult(request, Uint8Array.from([1]).buffer);
|
||||
await assert.rejects(jobs.verifyServerRenderJobResult({ ...result, outputByteLength: result.outputByteLength + 1 }, request), { code: "SERVER_RENDER_RESULT_HASH_MISMATCH" });
|
||||
await assert.rejects(jobs.verifyServerRenderJobResult({ ...result, outputMime: "image/openexr" }, request), { code: "SERVER_RENDER_OUTPUT_INVALID" });
|
||||
await assert.rejects(jobs.verifyServerRenderJobResult({ ...result, errorCode: "SERVER_RENDER_FAILED" }, request), { code: "SERVER_RENDER_OUTPUT_INVALID" });
|
||||
await assert.rejects(jobs.verifyServerRenderJobRequest({ ...request, unexpected: true }), { code: "SERVER_RENDER_REQUEST_INVALID" });
|
||||
});
|
||||
Reference in New Issue
Block a user