93 lines
4.1 KiB
JavaScript
93 lines
4.1 KiB
JavaScript
import assert from "node:assert/strict";
|
|
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 repoRoot = path.resolve(import.meta.dirname, "../../..");
|
|
const temporary = fs.mkdtempSync(path.join(os.tmpdir(), "paint-pbvh-capability-unit-"));
|
|
|
|
function transpile(sourceName, outputName, replacements = []) {
|
|
const sourcePath = path.join(repoRoot, "web/protocol", sourceName);
|
|
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 output = replacements.reduce((source, [from, to]) => source.replaceAll(from, to), transpiled.outputText);
|
|
fs.writeFileSync(path.join(temporary, outputName), output);
|
|
}
|
|
|
|
transpile("capability-gates.ts", "capability-gates.mjs");
|
|
transpile("paint-pbvh-capability.ts", "paint-pbvh-capability.mjs", [
|
|
['from "./capability-gates"', 'from "./capability-gates.mjs"'],
|
|
]);
|
|
const pbvh = await import(pathToFileURL(path.join(temporary, "paint-pbvh-capability.mjs")));
|
|
|
|
const base = {
|
|
schemaVersion: 1,
|
|
operation: "PBVH_BRUSH",
|
|
domain: "VERTEX_COLOR",
|
|
brush: "DRAW",
|
|
objectId: "object:Paint",
|
|
meshId: "mesh:Paint",
|
|
baseRevision: 7,
|
|
};
|
|
|
|
test("M9-13 freezes the active Blender 5.2 PBVH-related brush inventory", () => {
|
|
const inventory = pbvh.paintPBVHBrushInventory();
|
|
const counts = Object.fromEntries(["SCULPT", "VERTEX_COLOR", "WEIGHT", "TEXTURE"].map((domain) => [
|
|
domain,
|
|
inventory.filter((entry) => entry.domain === domain).length,
|
|
]));
|
|
assert.deepEqual(counts, { SCULPT: 32, VERTEX_COLOR: 4, WEIGHT: 4, TEXTURE: 6 });
|
|
assert.equal(new Set(inventory.map((entry) => `${entry.domain}:${entry.brush}`)).size, 46);
|
|
assert.ok(inventory.every((entry) => entry.source.endsWith("DNA_brush_enums.h")));
|
|
});
|
|
|
|
test("M9-13 blocks every PBVH brush when the WASM entrypoint is absent", () => {
|
|
for (const entry of pbvh.paintPBVHBrushInventory()) {
|
|
const gate = pbvh.gatePaintPBVHCapability({ ...base, domain: entry.domain, brush: entry.brush }, {
|
|
nativeEntrypointPresent: false,
|
|
sessionContextReady: false,
|
|
verifiedBrushes: new Set(),
|
|
currentRevision: 7,
|
|
currentObjectId: base.objectId,
|
|
currentMeshId: base.meshId,
|
|
});
|
|
assert.equal(gate.taskId, "N-017");
|
|
assert.equal(gate.status, "BLOCKED");
|
|
assert.deepEqual(gate.issues.map((issue) => issue.code), ["PAINT_PBVH_UNAVAILABLE"]);
|
|
assert.equal(gate.issues[0].recoverable, false);
|
|
}
|
|
});
|
|
|
|
test("M9-13 remains fail-closed after symbol discovery until context and a brush golden exist", () => {
|
|
const common = { nativeEntrypointPresent: true, verifiedBrushes: new Set(), currentRevision: 7 };
|
|
assert.equal(pbvh.gatePaintPBVHCapability(base, { ...common, sessionContextReady: false }).issues[0].code, "PAINT_PBVH_CONTEXT_UNAVAILABLE");
|
|
assert.equal(pbvh.gatePaintPBVHCapability(base, { ...common, sessionContextReady: true }).issues[0].code, "PAINT_PBVH_BRUSH_UNVERIFIED");
|
|
assert.equal(pbvh.gatePaintPBVHCapability(base, {
|
|
...common,
|
|
sessionContextReady: true,
|
|
verifiedBrushes: new Set(["VERTEX_COLOR:DRAW"]),
|
|
}).status, "READY");
|
|
});
|
|
|
|
test("M9-13 validates identity and revision before reporting runtime availability", () => {
|
|
const context = {
|
|
nativeEntrypointPresent: false,
|
|
sessionContextReady: false,
|
|
verifiedBrushes: new Set(),
|
|
currentRevision: 7,
|
|
currentObjectId: base.objectId,
|
|
currentMeshId: base.meshId,
|
|
};
|
|
assert.equal(pbvh.gatePaintPBVHCapability({ ...base, baseRevision: 6 }, context).issues[0].code, "REVISION_CONFLICT");
|
|
assert.equal(pbvh.gatePaintPBVHCapability({ ...base, objectId: "object:Other" }, context).issues[0].code, "PAINT_SCHEMA_INVALID");
|
|
assert.throws(() => pbvh.parsePaintPBVHCapabilityRequest({ ...base, brush: "FAKE" }), { code: "PAINT_PBVH_BRUSH_UNVERIFIED" });
|
|
assert.throws(() => pbvh.parsePaintPBVHCapabilityRequest({ ...base, proxySuccess: true }), { code: "PAINT_SCHEMA_INVALID" });
|
|
});
|