110 lines
4.9 KiB
JavaScript
110 lines
4.9 KiB
JavaScript
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 { spawnSync } from "node:child_process";
|
|
import { fileURLToPath } from "node:url";
|
|
|
|
const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../..");
|
|
const installer = path.join(repoRoot, "tools/web/install-web-engine-assets.sh");
|
|
const workspace = fs.mkdtempSync(path.join(os.tmpdir(), "engine-variant-install-test-"));
|
|
|
|
function sha256(bytes) {
|
|
return crypto.createHash("sha256").update(bytes).digest("hex");
|
|
}
|
|
|
|
function writeBuild(directory, label, includeWasm = true) {
|
|
fs.mkdirSync(directory, { recursive: true });
|
|
fs.writeFileSync(path.join(directory, "web_engine.js"), `export default ${JSON.stringify(label)};\n`);
|
|
if (includeWasm) fs.writeFileSync(path.join(directory, "web_engine.wasm"), Buffer.from(`wasm:${label}`));
|
|
}
|
|
|
|
function writeLegacyManifest(publicRoot) {
|
|
fs.mkdirSync(publicRoot, { recursive: true });
|
|
const manifestPath = path.join(publicRoot, "engine-manifest.json");
|
|
fs.writeFileSync(manifestPath, `${JSON.stringify({
|
|
schemaVersion: 1,
|
|
protocolVersion: 1,
|
|
engineVersion: "blender-wasm-install-test",
|
|
engine: "blender-wasm",
|
|
memory: { initialPages: 256, maximumPages: 32768, shared: false },
|
|
wasm: [],
|
|
}, null, 2)}\n`);
|
|
return manifestPath;
|
|
}
|
|
|
|
function runInstaller(singleBuild, pthreadBuild, publicRoot) {
|
|
return spawnSync("bash", [installer], {
|
|
cwd: repoRoot,
|
|
encoding: "utf8",
|
|
env: {
|
|
...process.env,
|
|
WEB_ENGINE_SINGLE_BUILD_DIR: singleBuild,
|
|
WEB_ENGINE_PTHREAD_BUILD_DIR: pthreadBuild,
|
|
WEB_ENGINE_PUBLIC_ROOT: publicRoot,
|
|
},
|
|
});
|
|
}
|
|
|
|
try {
|
|
const positive = path.join(workspace, "positive");
|
|
const singleBuild = path.join(positive, "build-single");
|
|
const pthreadBuild = path.join(positive, "build-pthread");
|
|
const publicRoot = path.join(positive, "public");
|
|
writeBuild(singleBuild, "single-output");
|
|
writeBuild(pthreadBuild, "pthread-output");
|
|
writeLegacyManifest(publicRoot);
|
|
fs.mkdirSync(path.join(publicRoot, "vendor/blender"), { recursive: true });
|
|
fs.writeFileSync(path.join(publicRoot, "vendor/blender/web_engine.js"), "legacy-loader\n");
|
|
|
|
const installed = runInstaller(singleBuild, pthreadBuild, publicRoot);
|
|
assert.equal(installed.status, 0, installed.stderr || installed.stdout);
|
|
const manifest = JSON.parse(fs.readFileSync(path.join(publicRoot, "engine-manifest.json"), "utf8"));
|
|
assert.equal(manifest.schemaVersion, 2);
|
|
assert.equal(manifest.releaseId, "blender-wasm-install-test");
|
|
assert.deepEqual(manifest.variants.map((variant) => variant.id), ["single", "pthread"]);
|
|
for (const [index, buildDirectory] of [[0, singleBuild], [1, pthreadBuild]]) {
|
|
const variant = manifest.variants[index];
|
|
for (const role of ["js", "wasm"]) {
|
|
const resource = variant.resources[role];
|
|
const source = fs.readFileSync(path.join(buildDirectory, resource.fileName));
|
|
const target = fs.readFileSync(path.join(publicRoot, resource.url));
|
|
assert.deepEqual(target, source);
|
|
assert.equal(resource.sha256, sha256(source));
|
|
}
|
|
}
|
|
assert.equal(fs.readFileSync(path.join(publicRoot, "vendor/blender/web_engine.js"), "utf8"), "legacy-loader\n");
|
|
assert.deepEqual(manifest.variants[1].resources.pthreadWorker, manifest.variants[1].resources.js);
|
|
|
|
const sameBuildRoot = path.join(workspace, "same-build-negative");
|
|
const sameBuild = path.join(sameBuildRoot, "build");
|
|
const samePublic = path.join(sameBuildRoot, "public");
|
|
writeBuild(sameBuild, "same-output");
|
|
const sameManifest = writeLegacyManifest(samePublic);
|
|
const beforeSame = fs.readFileSync(sameManifest);
|
|
const sameResult = runInstaller(sameBuild, sameBuild, samePublic);
|
|
assert.notEqual(sameResult.status, 0);
|
|
assert.match(sameResult.stderr, /independent build directories/);
|
|
assert.deepEqual(fs.readFileSync(sameManifest), beforeSame);
|
|
assert.equal(fs.existsSync(path.join(samePublic, "vendor/blender/single")), false);
|
|
|
|
const missingRoot = path.join(workspace, "missing-asset-negative");
|
|
const completeBuild = path.join(missingRoot, "build-single");
|
|
const incompleteBuild = path.join(missingRoot, "build-pthread");
|
|
const missingPublic = path.join(missingRoot, "public");
|
|
writeBuild(completeBuild, "complete-output");
|
|
writeBuild(incompleteBuild, "incomplete-output", false);
|
|
const missingManifest = writeLegacyManifest(missingPublic);
|
|
const beforeMissing = fs.readFileSync(missingManifest);
|
|
const missingResult = runInstaller(completeBuild, incompleteBuild, missingPublic);
|
|
assert.notEqual(missingResult.status, 0);
|
|
assert.deepEqual(fs.readFileSync(missingManifest), beforeMissing);
|
|
assert.equal(fs.existsSync(path.join(missingPublic, "vendor/blender/single")), false);
|
|
|
|
process.stdout.write("engine-variant-install-ok variants=2 negativeCases=2\n");
|
|
}
|
|
finally {
|
|
fs.rmSync(workspace, { recursive: true, force: true });
|
|
}
|