mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-14 18:01:20 +08:00
d8486a7c4d
Part of Phase 2 of the distributed rendering plan (determinism hardening).
See DISTRIBUTED-RENDERING-PLAN.md §5.2 (browserGpuMode row) and §9.3
(BROWSER_GPU_NOT_SOFTWARE typed failure).
Adds packages/engine/src/utils/assertSwiftShader.ts:
- assertSwiftShader(page, readInfo?) — navigates to chrome://gpu, reads
the GL_VENDOR / GL_RENDERER rows from browserBridge.gpuInfo_, throws
SwiftShaderAssertionError ({ code: "BROWSER_GPU_NOT_SOFTWARE" }) if
the active backend isn't SwiftShader.
- readWebGlVendorInfo(page) — extracted helper so tests can stub the
info read without spinning up real Chrome.
- SwiftShaderAssertionError + BROWSER_GPU_NOT_SOFTWARE constant exposed
so the Phase 3 distributed adapter can match typed non-retryable
failures.
Re-exported from packages/engine/src/index.ts. No caller invokes it yet;
Phase 3 renderChunk() will run it post-launch.
In-process behavior is unchanged — assertSwiftShader is a new pure utility.
Producer regression baselines remain byte-identical.
This is part of a stack of 10 PRs; this is PR 2 of 10.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
131 lines
4.9 KiB
TypeScript
131 lines
4.9 KiB
TypeScript
/**
|
|
* Tests for assertSwiftShader and its companion readWebGlVendorInfo helper.
|
|
*
|
|
* We don't spin up a real Chrome here — the assertion's contract is "given a
|
|
* WebGL info pair, accept SwiftShader and reject anything else." Tests inject
|
|
* the info pair through the optional `readInfo` override that the
|
|
* production code path leaves as a default.
|
|
*/
|
|
|
|
import { describe, expect, it } from "vitest";
|
|
import type { Page } from "puppeteer-core";
|
|
import {
|
|
BROWSER_GPU_NOT_SOFTWARE,
|
|
SwiftShaderAssertionError,
|
|
assertSwiftShader,
|
|
} from "./assertSwiftShader.js";
|
|
|
|
// Minimal Page stub. Only assertSwiftShader's default `readInfo` ever touches
|
|
// `page.goto` / `page.evaluate`; when we inject a custom `readInfo` the page
|
|
// object is never used, so an empty cast is safe.
|
|
const stubPage = {} as unknown as Page;
|
|
|
|
describe("assertSwiftShader", () => {
|
|
it("accepts the canonical SwiftShader vendor + renderer pair", async () => {
|
|
await assertSwiftShader(stubPage, async () => ({
|
|
vendor: "Google Inc. (Google)",
|
|
renderer:
|
|
"ANGLE (Google, Vulkan 1.3.0 (SwiftShader Device (Subzero) (0x0000C0DE)), SwiftShader driver)",
|
|
}));
|
|
});
|
|
|
|
it("accepts SwiftShader regardless of trailing whitespace on vendor", async () => {
|
|
await assertSwiftShader(stubPage, async () => ({
|
|
vendor: " Google Inc. (Google) ",
|
|
renderer: "SwiftShader",
|
|
}));
|
|
});
|
|
|
|
it("accepts case-insensitive renderer token", async () => {
|
|
await assertSwiftShader(stubPage, async () => ({
|
|
vendor: "Google Inc. (Google)",
|
|
renderer: "ANGLE (Google, swiftshader Device, swiftshader driver)",
|
|
}));
|
|
});
|
|
|
|
it("throws SwiftShaderAssertionError when vendor is hardware-accelerated", async () => {
|
|
let caught: unknown;
|
|
try {
|
|
await assertSwiftShader(stubPage, async () => ({
|
|
vendor: "Google Inc. (NVIDIA Corporation)",
|
|
renderer: "ANGLE (NVIDIA, NVIDIA GeForce RTX 4090, OpenGL 4.6)",
|
|
}));
|
|
} catch (err) {
|
|
caught = err;
|
|
}
|
|
expect(caught).toBeInstanceOf(SwiftShaderAssertionError);
|
|
expect((caught as SwiftShaderAssertionError).code).toBe(BROWSER_GPU_NOT_SOFTWARE);
|
|
expect((caught as Error).message).toContain("non-SwiftShader");
|
|
expect((caught as Error).message).toContain("--use-gl=swiftshader");
|
|
expect((caught as SwiftShaderAssertionError).vendor).toBe("Google Inc. (NVIDIA Corporation)");
|
|
});
|
|
|
|
it("throws when the renderer string lacks SwiftShader even if vendor matches", async () => {
|
|
// Google Inc. is the umbrella vendor for many ANGLE backends — vendor
|
|
// alone is not enough; the renderer must actually mention SwiftShader.
|
|
let caught: unknown;
|
|
try {
|
|
await assertSwiftShader(stubPage, async () => ({
|
|
vendor: "Google Inc. (Google)",
|
|
renderer: "ANGLE (Google, Vulkan 1.3.0 (Intel(R) UHD Graphics 630), OpenGL ES 3.0)",
|
|
}));
|
|
} catch (err) {
|
|
caught = err;
|
|
}
|
|
expect(caught).toBeInstanceOf(SwiftShaderAssertionError);
|
|
expect((caught as SwiftShaderAssertionError).code).toBe(BROWSER_GPU_NOT_SOFTWARE);
|
|
});
|
|
|
|
it("throws when both vendor and renderer are empty", async () => {
|
|
// Some chrome:// pages return empty strings before the GPU info table
|
|
// populates. We treat that as failure rather than silently passing.
|
|
let caught: unknown;
|
|
try {
|
|
await assertSwiftShader(stubPage, async () => ({ vendor: "", renderer: "" }));
|
|
} catch (err) {
|
|
caught = err;
|
|
}
|
|
expect(caught).toBeInstanceOf(SwiftShaderAssertionError);
|
|
expect((caught as SwiftShaderAssertionError).code).toBe(BROWSER_GPU_NOT_SOFTWARE);
|
|
});
|
|
|
|
it("propagates errors from the info reader without wrapping", async () => {
|
|
const upstream = new Error("simulated CDP failure");
|
|
let caught: unknown;
|
|
try {
|
|
await assertSwiftShader(stubPage, async () => {
|
|
throw upstream;
|
|
});
|
|
} catch (err) {
|
|
caught = err;
|
|
}
|
|
// Reader errors should not be masked by SwiftShaderAssertionError —
|
|
// they are a separate failure class (probably retryable).
|
|
expect(caught).toBe(upstream);
|
|
});
|
|
|
|
it("rejects an unrelated vendor that happens to contain the SwiftShader token in the renderer", async () => {
|
|
// Defensive: if some future ANGLE build uses a non-Google vendor string
|
|
// but still mentions SwiftShader in the renderer for some reason, we
|
|
// still want to require the exact Google vendor signature.
|
|
let caught: unknown;
|
|
try {
|
|
await assertSwiftShader(stubPage, async () => ({
|
|
vendor: "Mesa/X.org",
|
|
renderer: "llvmpipe (SwiftShader compatible)",
|
|
}));
|
|
} catch (err) {
|
|
caught = err;
|
|
}
|
|
expect(caught).toBeInstanceOf(SwiftShaderAssertionError);
|
|
});
|
|
});
|
|
|
|
describe("SwiftShaderAssertionError", () => {
|
|
it("exposes the BROWSER_GPU_NOT_SOFTWARE typed-failure code", () => {
|
|
const err = new SwiftShaderAssertionError("test", "v", "r");
|
|
expect(err.code).toBe(BROWSER_GPU_NOT_SOFTWARE);
|
|
expect(err.code).toBe("BROWSER_GPU_NOT_SOFTWARE");
|
|
});
|
|
});
|