mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-11-14 13:27:13 +00:00
WSL first-render success (34.7%) is dominated by a downloaded chrome-headless-shell that launches into `libnss3.so: cannot open shared object file` — doctor/preflight only checked the binary exists, never that it can load its libraries. - New linuxDeps.ts: /etc/os-release distro detection (Debian/Fedora/Arch/Alpine) + WSL detection, per-distro Chrome dep set, ldd-based shared-lib probe. - preflight.checkChrome downgrades a found-but-unlaunchable Chrome to a render-blocking error with the exact per-distro install command. - Distro-aware ffmpeg hints; launch failures converted to actionable guidance pointing at `hyperframes doctor` (skipped on ARM64). - Detect + print remediation (no auto-install). Render-reliability workstream P1-4. Success measured on PostHog dashboard 1783183. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
182 lines
6.3 KiB
TypeScript
182 lines
6.3 KiB
TypeScript
// fallow-ignore-file code-duplication
|
|
import { describe, it, expect } from "vitest";
|
|
import {
|
|
chromeDepsInstallCommand,
|
|
chromeLaunchRemediation,
|
|
distroFamilyFromOsRelease,
|
|
distroLabel,
|
|
ffmpegInstallCommand,
|
|
isSharedLibLaunchError,
|
|
parseLddMissingLibs,
|
|
parseOsRelease,
|
|
} from "./linuxDeps.js";
|
|
|
|
describe("parseOsRelease", () => {
|
|
it("parses quoted and unquoted key=value pairs", () => {
|
|
const parsed = parseOsRelease(
|
|
['NAME="Ubuntu"', "ID=ubuntu", 'ID_LIKE="debian"', 'PRETTY_NAME="Ubuntu 22.04.3 LTS"'].join(
|
|
"\n",
|
|
),
|
|
);
|
|
expect(parsed["ID"]).toBe("ubuntu");
|
|
expect(parsed["ID_LIKE"]).toBe("debian");
|
|
expect(parsed["PRETTY_NAME"]).toBe("Ubuntu 22.04.3 LTS");
|
|
});
|
|
|
|
it("ignores comments and blank lines", () => {
|
|
const parsed = parseOsRelease("# a comment\n\nID=fedora\n");
|
|
expect(parsed).toEqual({ ID: "fedora" });
|
|
});
|
|
});
|
|
|
|
describe("distroFamilyFromOsRelease", () => {
|
|
it("maps Ubuntu/Debian derivatives to debian", () => {
|
|
expect(distroFamilyFromOsRelease("ubuntu", "debian")).toBe("debian");
|
|
expect(distroFamilyFromOsRelease("debian")).toBe("debian");
|
|
expect(distroFamilyFromOsRelease("linuxmint", "ubuntu debian")).toBe("debian");
|
|
});
|
|
|
|
it("maps RHEL family to fedora", () => {
|
|
expect(distroFamilyFromOsRelease("fedora")).toBe("fedora");
|
|
expect(distroFamilyFromOsRelease("rocky", "rhel centos fedora")).toBe("fedora");
|
|
expect(distroFamilyFromOsRelease("amzn")).toBe("fedora");
|
|
});
|
|
|
|
it("maps Arch derivatives to arch", () => {
|
|
expect(distroFamilyFromOsRelease("arch")).toBe("arch");
|
|
expect(distroFamilyFromOsRelease("manjaro", "arch")).toBe("arch");
|
|
});
|
|
|
|
it("maps Alpine to alpine", () => {
|
|
expect(distroFamilyFromOsRelease("alpine")).toBe("alpine");
|
|
});
|
|
|
|
it("returns unknown for unrecognized ids", () => {
|
|
expect(distroFamilyFromOsRelease("void")).toBe("unknown");
|
|
expect(distroFamilyFromOsRelease(undefined, undefined)).toBe("unknown");
|
|
});
|
|
});
|
|
|
|
describe("chromeDepsInstallCommand", () => {
|
|
it("emits an apt-get line with libnss3 for debian", () => {
|
|
const cmd = chromeDepsInstallCommand("debian");
|
|
expect(cmd).toContain("apt-get install -y");
|
|
expect(cmd).toContain("libnss3");
|
|
expect(cmd).toContain("libatk1.0-0");
|
|
});
|
|
|
|
it("emits a dnf line with nss for fedora", () => {
|
|
const cmd = chromeDepsInstallCommand("fedora");
|
|
expect(cmd).toContain("dnf install -y");
|
|
expect(cmd).toContain("nss");
|
|
});
|
|
|
|
it("emits a pacman line for arch", () => {
|
|
expect(chromeDepsInstallCommand("arch")).toContain("pacman -S");
|
|
});
|
|
|
|
it("emits an apk line for alpine", () => {
|
|
expect(chromeDepsInstallCommand("alpine")).toContain("apk add");
|
|
});
|
|
|
|
it("gives generic guidance for unknown distros", () => {
|
|
expect(chromeDepsInstallCommand("unknown").toLowerCase()).toContain("nss");
|
|
});
|
|
});
|
|
|
|
describe("ffmpegInstallCommand", () => {
|
|
it("uses the distro package manager", () => {
|
|
expect(ffmpegInstallCommand("debian")).toBe(
|
|
"sudo apt-get update && sudo apt-get install -y ffmpeg",
|
|
);
|
|
expect(ffmpegInstallCommand("fedora")).toBe("sudo dnf install -y ffmpeg");
|
|
expect(ffmpegInstallCommand("arch")).toBe("sudo pacman -S --needed ffmpeg");
|
|
expect(ffmpegInstallCommand("alpine")).toBe("sudo apk add ffmpeg");
|
|
});
|
|
|
|
it("gives generic guidance for unknown distros", () => {
|
|
expect(ffmpegInstallCommand("unknown").toLowerCase()).toContain("ffmpeg");
|
|
});
|
|
});
|
|
|
|
describe("parseLddMissingLibs", () => {
|
|
it("collects libraries reported as not found", () => {
|
|
const output = [
|
|
"\tlinux-vdso.so.1 (0x00007fff...)",
|
|
"\tlibnss3.so => not found",
|
|
"\tlibatk-1.0.so.0 => not found",
|
|
"\tlibc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f...)",
|
|
].join("\n");
|
|
const result = parseLddMissingLibs(output);
|
|
expect(result.ok).toBe(false);
|
|
expect(result.missing).toEqual(["libnss3.so", "libatk-1.0.so.0"]);
|
|
expect(result.probeUnavailable).toBe(false);
|
|
});
|
|
|
|
it("reports ok when every library resolves", () => {
|
|
const output = "\tlibc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f...)";
|
|
const result = parseLddMissingLibs(output);
|
|
expect(result.ok).toBe(true);
|
|
expect(result.missing).toEqual([]);
|
|
});
|
|
|
|
it("does not false-positive on a resolved path containing 'not found'", () => {
|
|
// A directory literally named "not found" must not trip the missing-lib
|
|
// detection — only the `=> not found` marker counts.
|
|
const output = "\tlibfoo.so.1 => /opt/not found/libfoo.so.1 (0x00007f...)";
|
|
const result = parseLddMissingLibs(output);
|
|
expect(result.ok).toBe(true);
|
|
expect(result.missing).toEqual([]);
|
|
});
|
|
});
|
|
|
|
describe("distroLabel", () => {
|
|
it("returns WSL when running under WSL", () => {
|
|
expect(distroLabel({ family: "debian", prettyName: "Ubuntu", isWsl: true })).toBe("WSL");
|
|
});
|
|
|
|
it("returns the pretty name off WSL", () => {
|
|
expect(distroLabel({ family: "fedora", prettyName: "Fedora Linux 40", isWsl: false })).toBe(
|
|
"Fedora Linux 40",
|
|
);
|
|
});
|
|
|
|
it("falls back to Linux when no pretty name", () => {
|
|
expect(distroLabel({ family: "unknown", isWsl: false })).toBe("Linux");
|
|
});
|
|
});
|
|
|
|
describe("isSharedLibLaunchError", () => {
|
|
it("matches the libnss3 cannot-open message", () => {
|
|
expect(
|
|
isSharedLibLaunchError(
|
|
"libnss3.so: cannot open shared object file: No such file or directory",
|
|
),
|
|
).toBe(true);
|
|
});
|
|
|
|
it("matches the dynamic-linker phrasing", () => {
|
|
expect(isSharedLibLaunchError("error while loading shared libraries: libatk-1.0.so.0")).toBe(
|
|
true,
|
|
);
|
|
});
|
|
|
|
it("does not match unrelated errors", () => {
|
|
expect(isSharedLibLaunchError("Composition has zero duration")).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe("chromeLaunchRemediation", () => {
|
|
it("returns undefined for non-launch errors", () => {
|
|
expect(chromeLaunchRemediation("Composition HTML is empty")).toBeUndefined();
|
|
});
|
|
|
|
// Platform-dependent output (Linux distro detection) is covered by the
|
|
// preflight tests that mock `platform()`; here we only assert the non-Linux /
|
|
// non-launch short-circuits, which are deterministic on the macOS CI host.
|
|
it("returns undefined off Linux even for a launch failure", () => {
|
|
if (process.platform === "linux") return;
|
|
expect(chromeLaunchRemediation("Failed to launch the browser process")).toBeUndefined();
|
|
});
|
|
});
|