Files
workinf_Blender_Wasm/web/tests/e2e/pthread-engine-isolated.spec.ts
mes123456 7c16b279ae
Some checks failed
M6 deployable RC / quick (push) Has been cancelled
M6 deployable RC / chromium (push) Has been cancelled
M6 deployable RC / release (push) Has been cancelled
Advance M7 workflows and release operations
2026-08-15 17:43:53 -04:00

79 lines
3.5 KiB
TypeScript

import { expect, test } from "@playwright/test";
test("loads the selected pthread engine with shared memory and its worker pool", async ({ page }) => {
const pthreadRequests: string[] = [];
page.on("request", (request) => {
const pathname = new URL(request.url()).pathname;
if (pathname.startsWith("/vendor/blender/pthread/")) pthreadRequests.push(pathname);
});
const documentResponse = await page.goto("/");
expect(documentResponse).not.toBeNull();
const headers = await documentResponse!.allHeaders();
expect(headers["cross-origin-opener-policy"]).toBe("same-origin");
expect(headers["cross-origin-embedder-policy"]).toBe("require-corp");
const result = await page.evaluate(async () => {
const { detectBrowserCapabilities, selectWebEngineVariant } = await import("/src/platform/capabilities.ts");
const manifest = await fetch("/engine-manifest.json", { cache: "no-store" }).then((response) => response.json());
const selection = selectWebEngineVariant(manifest, "PTHREAD_REQUIRED", detectBrowserCapabilities());
if (!selection.selectedVariant) {
return { selected: null, gate: selection.pthreadGate, shared: false, handle: 0, liveAfterDestroy: -1 };
}
const variant = selection.selectedVariant;
const wasmResponse = await fetch(variant.resources.wasm.url, { cache: "no-store" });
if (!wasmResponse.ok) throw new Error(`pthread WASM request failed: ${wasmResponse.status}`);
const wasmBinary = await wasmResponse.arrayBuffer();
const digest = await crypto.subtle.digest("SHA-256", wasmBinary);
const actualHash = [...new Uint8Array(digest)]
.map((byte) => byte.toString(16).padStart(2, "0"))
.join("");
if (actualHash !== variant.resources.wasm.sha256) throw new Error("pthread WASM hash mismatch");
const imported = await import(/* @vite-ignore */ variant.resources.js.url) as {
default: (options: { wasmBinary: ArrayBuffer }) => Promise<{
HEAPU8: Uint8Array;
_web_engine_create(): number;
_web_engine_destroy(handle: number): void;
_web_engine_get_live_handles(): number;
PThread: {
unusedWorkers: Worker[];
runningWorkers: Worker[];
terminateAllThreads(): void;
};
}>;
};
const module = await imported.default({ wasmBinary });
const handle = module._web_engine_create();
const shared = module.HEAPU8.buffer instanceof SharedArrayBuffer;
const liveBeforeDestroy = module._web_engine_get_live_handles();
const poolWorkersBeforeDispose = module.PThread.unusedWorkers.length + module.PThread.runningWorkers.length;
module._web_engine_destroy(handle);
module.PThread.terminateAllThreads();
return {
selected: variant.id,
gate: selection.pthreadGate,
shared,
handle,
liveBeforeDestroy,
liveAfterDestroy: module._web_engine_get_live_handles(),
poolWorkersBeforeDispose,
poolWorkersAfterDispose: module.PThread.unusedWorkers.length + module.PThread.runningWorkers.length,
};
});
expect(result).toMatchObject({
selected: "pthread",
gate: { taskId: "M6-02", capability: "WASM_PTHREAD_ENGINE", status: "READY", issues: [] },
shared: true,
liveBeforeDestroy: 1,
liveAfterDestroy: 0,
poolWorkersBeforeDispose: 1,
poolWorkersAfterDispose: 0,
});
expect(result.handle).toBeGreaterThan(0);
expect(pthreadRequests.filter((url) => url.endsWith("/web_engine.wasm"))).toHaveLength(1);
expect(pthreadRequests.filter((url) => url.endsWith("/web_engine.js")).length).toBeGreaterThanOrEqual(2);
});