82 lines
3.4 KiB
JavaScript
82 lines
3.4 KiB
JavaScript
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 repoRoot = path.resolve(import.meta.dirname, "../../..");
|
|
const sourcePath = path.join(repoRoot, "web/protocol/render-compositor-media-recovery.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, []);
|
|
const moduleUrl = "data:text/javascript;base64," + Buffer.from(transpiled.outputText).toString("base64");
|
|
const recovery = await import(moduleUrl);
|
|
|
|
const hash = "a".repeat(64);
|
|
const codes = {
|
|
RENDER: ["OPEN_CANCELLED", "GPU_TEXTURE_BUDGET_EXCEEDED"],
|
|
COMPOSITOR: ["COMPOSITOR_CANCELLED", "COMPOSITOR_BUDGET_EXCEEDED"],
|
|
MEDIA: ["SEQUENCER_CANCELLED", "SEQUENCER_BUDGET_EXCEEDED"],
|
|
};
|
|
const report = (domain) => ({
|
|
schemaVersion: 1,
|
|
domain,
|
|
source: { byteLength: 64, sha256: hash },
|
|
cancellation: { status: "CANCELLED", code: codes[domain][0], publishedResults: 0, temporaryResourcesAfter: 0 },
|
|
restart: {
|
|
status: "RECOVERED",
|
|
generationBefore: 1,
|
|
generationAfter: 2,
|
|
identityBefore: hash,
|
|
identityAfter: hash,
|
|
outputSha256Before: hash,
|
|
outputSha256After: hash,
|
|
},
|
|
budget: { status: "BLOCKED", code: codes[domain][1], retainedIdentityHash: hash, temporaryResourcesAfter: 0 },
|
|
release: { status: "RELEASED", releasedBytes: 64, releasedResources: 1, resourcesAfter: 0 },
|
|
recovery: { status: "RECOVERED", identityHash: hash, outputSha256: hash, outputBytes: 64, visibleUnits: 4 },
|
|
});
|
|
|
|
test("M11-14 accepts the complete render, compositor and media recovery suite", () => {
|
|
const parsed = recovery.parseRenderCompositorMediaRecoverySuite([
|
|
report("MEDIA"),
|
|
report("RENDER"),
|
|
report("COMPOSITOR"),
|
|
]);
|
|
assert.deepEqual(parsed.map((item) => item.domain), ["RENDER", "COMPOSITOR", "MEDIA"]);
|
|
assert.equal(parsed.every((item) => item.release.resourcesAfter === 0), true);
|
|
});
|
|
|
|
test("M11-14 rejects cancellation publication, domain code drift and duplicate domains", () => {
|
|
const published = report("RENDER");
|
|
published.cancellation.publishedResults = 1;
|
|
assert.throws(() => recovery.parseRenderCompositorMediaRecoveryEvidence(published), /must be zero/);
|
|
|
|
const wrongCode = report("MEDIA");
|
|
wrongCode.cancellation.code = "COMPOSITOR_CANCELLED";
|
|
assert.throws(() => recovery.parseRenderCompositorMediaRecoveryEvidence(wrongCode), /cancellation contract/);
|
|
|
|
assert.throws(() => recovery.parseRenderCompositorMediaRecoverySuite([
|
|
report("RENDER"),
|
|
report("RENDER"),
|
|
report("MEDIA"),
|
|
]), /duplicate domains/);
|
|
});
|
|
|
|
test("M11-14 rejects restart drift, budget mutation and incomplete release", () => {
|
|
const restartDrift = report("COMPOSITOR");
|
|
restartDrift.restart.outputSha256After = "b".repeat(64);
|
|
assert.throws(() => recovery.parseRenderCompositorMediaRecoveryEvidence(restartDrift), /restart changed/);
|
|
|
|
const budgetMutation = report("RENDER");
|
|
budgetMutation.budget.retainedIdentityHash = "b".repeat(64);
|
|
assert.throws(() => recovery.parseRenderCompositorMediaRecoveryEvidence(budgetMutation), /budget failure changed/);
|
|
|
|
const leaked = report("MEDIA");
|
|
leaked.release.resourcesAfter = 1;
|
|
assert.throws(() => recovery.parseRenderCompositorMediaRecoveryEvidence(leaked), /must be zero/);
|
|
});
|