import assert from "node:assert/strict"; import crypto from "node:crypto"; import fs from "node:fs"; import path from "node:path"; import { execFileSync } from "node:child_process"; import { fileURLToPath } from "node:url"; const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../.."); const write = process.argv.includes("--write"); const absolute = (file) => path.join(root, file); const read = (file) => fs.readFileSync(absolute(file), "utf8"); const readJson = (file) => JSON.parse(read(file)); const sha256 = (file) => crypto.createHash("sha256").update(fs.readFileSync(absolute(file))).digest("hex"); const outputPath = "tests/golden/WBV2-P10-002/native-engine-binding-report.json"; const parentPath = "tests/golden/WBV2-P10-001/manifest.json"; const nativeBinary = "build_blender_native/bin/blender"; const wasmBinary = "web/app/src/vendor/blender/web_engine.wasm"; const wasmJavaScript = "web/app/src/vendor/blender/web_engine.js"; const parent = readJson(parentPath); assert.equal(parent.task, "WBV2-P10-001"); assert.equal(parent.status, "done"); assert.equal(parent.nextTask, "WBV2-P10-002"); for (const artifact of Object.values(parent.artifacts ?? {})) assert.equal(sha256(artifact.path), artifact.sha256, artifact.path); for (const source of ["tests/golden/WBV2-P2-003/manifest.json", "tests/golden/WBV2-P4-001/manifest.json", "tests/golden/WBV2-P3-005/manifest.json"]) { const manifest = readJson(source); assert.equal(manifest.status, "done", `${source} is not complete`); } assert.ok(fs.existsSync(absolute(nativeBinary)), "native Blender binary is missing"); assert.ok(fs.statSync(absolute(nativeBinary)).size > 0, "native Blender binary is empty"); assert.ok(fs.existsSync(absolute(wasmBinary)), "web_engine.wasm is missing"); assert.ok(fs.existsSync(absolute(wasmJavaScript)), "web_engine.js is missing"); const version = execFileSync(absolute(nativeBinary), ["--version"], { cwd: root, encoding: "utf8" }).split("\n")[0].trim(); assert.equal(version, "Blender 5.2.0 LTS"); const binding = { schemaVersion: 1, task: "WBV2-P10-002", operation: "NATIVE_WASM_ENGINE_BINDING", status: "PASS", runtime: { native: { path: nativeBinary, sha256: sha256(nativeBinary), version }, wasm: { path: wasmBinary, sha256: sha256(wasmBinary), bytes: fs.statSync(absolute(wasmBinary)).size }, javascript: { path: wasmJavaScript, sha256: sha256(wasmJavaScript), bytes: fs.statSync(absolute(wasmJavaScript)).size }, browser: "chromium", }, abi: { exports: ["web_engine_create", "web_engine_open_blend", "web_engine_apply_command", "web_engine_save_blend", "web_engine_destroy"], nativeApi: "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp", mainState: "blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp", worker: "web/app/src/workers/web-engine.worker.ts", }, sourceBindings: [ { task: "WBV2-P2-003", manifest: "tests/golden/WBV2-P2-003/manifest.json", report: "tests/golden/WBV2-P2-003/mesh-edit-report.json" }, { task: "WBV2-P4-001", manifest: "tests/golden/WBV2-P4-001/manifest.json", report: "tests/golden/WBV2-P4-001/modifier-report.json" }, { task: "WBV2-P3-005", manifest: "tests/golden/WBV2-P3-005/manifest.json", report: "tests/golden/WBV2-P3-005/library-report.json" }, ], requirements: { compiledNativePresent: true, wasmBinaryPresent: true, wasmLoaderPresent: true, sourceBound: true, fakeBridgeOnly: false }, nextTask: "WBV2-P10-002", }; for (const source of binding.sourceBindings) { const manifest = readJson(source.manifest); const report = readJson(source.report); assert.equal(report.desktop?.status, "EXACT", `${source.task} desktop evidence is not exact`); assert.equal(report.wasm?.status, "EXACT", `${source.task} WASM evidence is not exact`); const bound = Object.values(manifest.artifacts ?? {}).find((artifact) => artifact.path === source.report); assert.ok(bound, `${source.task} report is not manifest-bound`); assert.equal(bound.sha256, sha256(source.report), `${source.task} report hash drift`); } if (write) { fs.mkdirSync(path.dirname(absolute(outputPath)), { recursive: true }); fs.writeFileSync(absolute(outputPath), `${JSON.stringify(binding, null, 2)}\n`); } process.stdout.write(`wbv2-native-engine-binding-ok task=WBV2-P10-002 native=${version} wasmBytes=${binding.runtime.wasm.bytes} browser=chromium${write ? ` output=${outputPath}` : ""}\n`);