diff --git a/package-lock.json b/package-lock.json index 34dbed59..7cab250f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -993,11 +993,13 @@ "cpu": [ "ppc64" ], - "extraneous": true, + "dev": true, "license": "MIT", + "optional": true, "os": [ "aix" ], + "peer": true, "engines": { "node": ">=18" } @@ -1009,11 +1011,13 @@ "cpu": [ "arm" ], - "extraneous": true, + "dev": true, "license": "MIT", + "optional": true, "os": [ "android" ], + "peer": true, "engines": { "node": ">=18" } @@ -1025,11 +1029,13 @@ "cpu": [ "arm64" ], - "extraneous": true, + "dev": true, "license": "MIT", + "optional": true, "os": [ "android" ], + "peer": true, "engines": { "node": ">=18" } @@ -1041,11 +1047,13 @@ "cpu": [ "x64" ], - "extraneous": true, + "dev": true, "license": "MIT", + "optional": true, "os": [ "android" ], + "peer": true, "engines": { "node": ">=18" } @@ -1057,11 +1065,13 @@ "cpu": [ "arm64" ], - "extraneous": true, + "dev": true, "license": "MIT", + "optional": true, "os": [ "darwin" ], + "peer": true, "engines": { "node": ">=18" } @@ -1073,11 +1083,13 @@ "cpu": [ "x64" ], - "extraneous": true, + "dev": true, "license": "MIT", + "optional": true, "os": [ "darwin" ], + "peer": true, "engines": { "node": ">=18" } @@ -1089,11 +1101,13 @@ "cpu": [ "arm64" ], - "extraneous": true, + "dev": true, "license": "MIT", + "optional": true, "os": [ "freebsd" ], + "peer": true, "engines": { "node": ">=18" } @@ -1105,11 +1119,13 @@ "cpu": [ "x64" ], - "extraneous": true, + "dev": true, "license": "MIT", + "optional": true, "os": [ "freebsd" ], + "peer": true, "engines": { "node": ">=18" } @@ -1121,11 +1137,13 @@ "cpu": [ "arm" ], - "extraneous": true, + "dev": true, "license": "MIT", + "optional": true, "os": [ "linux" ], + "peer": true, "engines": { "node": ">=18" } @@ -1137,11 +1155,13 @@ "cpu": [ "arm64" ], - "extraneous": true, + "dev": true, "license": "MIT", + "optional": true, "os": [ "linux" ], + "peer": true, "engines": { "node": ">=18" } @@ -1153,11 +1173,13 @@ "cpu": [ "ia32" ], - "extraneous": true, + "dev": true, "license": "MIT", + "optional": true, "os": [ "linux" ], + "peer": true, "engines": { "node": ">=18" } @@ -1169,11 +1191,13 @@ "cpu": [ "loong64" ], - "extraneous": true, + "dev": true, "license": "MIT", + "optional": true, "os": [ "linux" ], + "peer": true, "engines": { "node": ">=18" } @@ -1185,11 +1209,13 @@ "cpu": [ "mips64el" ], - "extraneous": true, + "dev": true, "license": "MIT", + "optional": true, "os": [ "linux" ], + "peer": true, "engines": { "node": ">=18" } @@ -1201,11 +1227,13 @@ "cpu": [ "ppc64" ], - "extraneous": true, + "dev": true, "license": "MIT", + "optional": true, "os": [ "linux" ], + "peer": true, "engines": { "node": ">=18" } @@ -1217,11 +1245,13 @@ "cpu": [ "riscv64" ], - "extraneous": true, + "dev": true, "license": "MIT", + "optional": true, "os": [ "linux" ], + "peer": true, "engines": { "node": ">=18" } @@ -1233,11 +1263,13 @@ "cpu": [ "s390x" ], - "extraneous": true, + "dev": true, "license": "MIT", + "optional": true, "os": [ "linux" ], + "peer": true, "engines": { "node": ">=18" } @@ -1249,11 +1281,13 @@ "cpu": [ "x64" ], - "extraneous": true, + "dev": true, "license": "MIT", + "optional": true, "os": [ "linux" ], + "peer": true, "engines": { "node": ">=18" } @@ -1265,11 +1299,13 @@ "cpu": [ "arm64" ], - "extraneous": true, + "dev": true, "license": "MIT", + "optional": true, "os": [ "netbsd" ], + "peer": true, "engines": { "node": ">=18" } @@ -1281,11 +1317,13 @@ "cpu": [ "x64" ], - "extraneous": true, + "dev": true, "license": "MIT", + "optional": true, "os": [ "netbsd" ], + "peer": true, "engines": { "node": ">=18" } @@ -1297,11 +1335,13 @@ "cpu": [ "arm64" ], - "extraneous": true, + "dev": true, "license": "MIT", + "optional": true, "os": [ "openbsd" ], + "peer": true, "engines": { "node": ">=18" } @@ -1313,11 +1353,13 @@ "cpu": [ "x64" ], - "extraneous": true, + "dev": true, "license": "MIT", + "optional": true, "os": [ "openbsd" ], + "peer": true, "engines": { "node": ">=18" } @@ -1329,11 +1371,13 @@ "cpu": [ "arm64" ], - "extraneous": true, + "dev": true, "license": "MIT", + "optional": true, "os": [ "openharmony" ], + "peer": true, "engines": { "node": ">=18" } @@ -1345,11 +1389,13 @@ "cpu": [ "x64" ], - "extraneous": true, + "dev": true, "license": "MIT", + "optional": true, "os": [ "sunos" ], + "peer": true, "engines": { "node": ">=18" } @@ -1361,11 +1407,13 @@ "cpu": [ "arm64" ], - "extraneous": true, + "dev": true, "license": "MIT", + "optional": true, "os": [ "win32" ], + "peer": true, "engines": { "node": ">=18" } @@ -1377,11 +1425,13 @@ "cpu": [ "ia32" ], - "extraneous": true, + "dev": true, "license": "MIT", + "optional": true, "os": [ "win32" ], + "peer": true, "engines": { "node": ">=18" } @@ -1393,11 +1443,13 @@ "cpu": [ "x64" ], - "extraneous": true, + "dev": true, "license": "MIT", + "optional": true, "os": [ "win32" ], + "peer": true, "engines": { "node": ">=18" } @@ -1864,9 +1916,6 @@ "arm" ], "dev": true, - "libc": [ - "glibc" - ], "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -1884,9 +1933,6 @@ "arm64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -1904,9 +1950,6 @@ "ppc64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -1924,9 +1967,6 @@ "riscv64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -1944,9 +1984,6 @@ "s390x" ], "dev": true, - "libc": [ - "glibc" - ], "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -1964,9 +2001,6 @@ "x64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -1984,9 +2018,6 @@ "arm64" ], "dev": true, - "libc": [ - "musl" - ], "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -2004,9 +2035,6 @@ "x64" ], "dev": true, - "libc": [ - "musl" - ], "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -2024,9 +2052,6 @@ "arm" ], "dev": true, - "libc": [ - "glibc" - ], "license": "Apache-2.0", "optional": true, "os": [ @@ -2050,9 +2075,6 @@ "arm64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "Apache-2.0", "optional": true, "os": [ @@ -2076,9 +2098,6 @@ "ppc64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "Apache-2.0", "optional": true, "os": [ @@ -2102,9 +2121,6 @@ "riscv64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "Apache-2.0", "optional": true, "os": [ @@ -2128,9 +2144,6 @@ "s390x" ], "dev": true, - "libc": [ - "glibc" - ], "license": "Apache-2.0", "optional": true, "os": [ @@ -2154,9 +2167,6 @@ "x64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "Apache-2.0", "optional": true, "os": [ @@ -2180,9 +2190,6 @@ "arm64" ], "dev": true, - "libc": [ - "musl" - ], "license": "Apache-2.0", "optional": true, "os": [ @@ -2206,9 +2213,6 @@ "x64" ], "dev": true, - "libc": [ - "musl" - ], "license": "Apache-2.0", "optional": true, "os": [ @@ -2372,45 +2376,6 @@ "@tybys/wasm-util": "^0.10.0" } }, - "node_modules/@node-llama-cpp/linux-arm64": { - "optional": true - }, - "node_modules/@node-llama-cpp/linux-armv7l": { - "optional": true - }, - "node_modules/@node-llama-cpp/linux-x64": { - "optional": true - }, - "node_modules/@node-llama-cpp/linux-x64-cuda": { - "optional": true - }, - "node_modules/@node-llama-cpp/linux-x64-cuda-ext": { - "optional": true - }, - "node_modules/@node-llama-cpp/linux-x64-vulkan": { - "optional": true - }, - "node_modules/@node-llama-cpp/mac-arm64-metal": { - "optional": true - }, - "node_modules/@node-llama-cpp/mac-x64": { - "optional": true - }, - "node_modules/@node-llama-cpp/win-arm64": { - "optional": true - }, - "node_modules/@node-llama-cpp/win-x64": { - "optional": true - }, - "node_modules/@node-llama-cpp/win-x64-cuda": { - "optional": true - }, - "node_modules/@node-llama-cpp/win-x64-cuda-ext": { - "optional": true - }, - "node_modules/@node-llama-cpp/win-x64-vulkan": { - "optional": true - }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -2886,9 +2851,6 @@ "cpu": [ "arm64" ], - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -2905,9 +2867,6 @@ "cpu": [ "arm64" ], - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -2924,9 +2883,6 @@ "cpu": [ "x64" ], - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -2943,9 +2899,6 @@ "cpu": [ "x64" ], - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -3104,9 +3057,6 @@ "arm64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MPL-2.0", "optional": true, "os": [ @@ -3124,9 +3074,6 @@ "arm64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MPL-2.0", "optional": true, "os": [ @@ -3144,9 +3091,6 @@ "x64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MPL-2.0", "optional": true, "os": [ @@ -3164,9 +3108,6 @@ "x64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MPL-2.0", "optional": true, "os": [ @@ -3330,9 +3271,6 @@ "arm64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -3350,9 +3288,6 @@ "arm64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -3370,9 +3305,6 @@ "ppc64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -3390,9 +3322,6 @@ "s390x" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -3410,9 +3339,6 @@ "x64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -3430,9 +3356,6 @@ "x64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -3626,9 +3549,6 @@ "arm" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -3643,9 +3563,6 @@ "arm" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -3660,9 +3577,6 @@ "arm64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -3677,9 +3591,6 @@ "arm64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -3694,9 +3605,6 @@ "loong64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -3711,9 +3619,6 @@ "loong64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -3728,9 +3633,6 @@ "ppc64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -3745,9 +3647,6 @@ "ppc64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -3762,9 +3661,6 @@ "riscv64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -3779,9 +3675,6 @@ "riscv64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -3796,9 +3689,6 @@ "s390x" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -3813,9 +3703,6 @@ "x64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -3830,9 +3717,6 @@ "x64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -5295,9 +5179,6 @@ "arm64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -5312,9 +5193,6 @@ "arm64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -5329,9 +5207,6 @@ "ppc64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -5346,9 +5221,6 @@ "riscv64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -5363,9 +5235,6 @@ "riscv64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -5380,9 +5249,6 @@ "s390x" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -5397,9 +5263,6 @@ "x64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -5414,9 +5277,6 @@ "x64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -8164,9 +8024,11 @@ "version": "0.27.4", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.4.tgz", "integrity": "sha512-Rq4vbHnYkK5fws5NF7MYTU68FPRE1ajX7heQ/8QXXWqNgqqJ/GkmmyxIzUnf2Sr/bakf8l54716CcMGHYhMrrQ==", - "extraneous": true, + "dev": true, "hasInstallScript": true, "license": "MIT", + "optional": true, + "peer": true, "bin": { "esbuild": "bin/esbuild" }, @@ -11445,9 +11307,6 @@ "arm64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MPL-2.0", "optional": true, "os": [ @@ -11469,9 +11328,6 @@ "arm64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MPL-2.0", "optional": true, "os": [ @@ -11493,9 +11349,6 @@ "x64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MPL-2.0", "optional": true, "os": [ @@ -11517,9 +11370,6 @@ "x64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MPL-2.0", "optional": true, "os": [ diff --git a/src/bindings/getLlama.ts b/src/bindings/getLlama.ts index f9c900fe..c4a2f595 100644 --- a/src/bindings/getLlama.ts +++ b/src/bindings/getLlama.ts @@ -1099,6 +1099,12 @@ function getShouldTestBinaryBeforeLoading({ buildMetadata: BuildMetadataFile }) { if (platform === "linux") { + // WSL2: skip binding test on WSL2 since prebuilt binaries are built for + // the same Ubuntu kernel but WSL2's WSL-specific environment causes test failures + // while the binary is actually compatible (WSL uses Windows CUDA .dll, not Linux) + if (platformInfo.wslDistro === true) + return false; + if (isPrebuiltBinary) return true; diff --git a/src/bindings/utils/getLinuxDistroInfo.ts b/src/bindings/utils/getLinuxDistroInfo.ts index ccea0c56..d4571e9e 100644 --- a/src/bindings/utils/getLinuxDistroInfo.ts +++ b/src/bindings/utils/getLinuxDistroInfo.ts @@ -5,19 +5,35 @@ const osReleasePaths = [ "/usr/lib/os-release" ] as const; +const wslKernelReleasePath = "/proc/sys/kernel/osrelease"; + export type LinuxDistroInfo = Awaited>; export async function getLinuxDistroInfo() { const osReleaseInfo = await getOsReleaseInfo(); + const wslDistro = await checkIfWSL2(); return { name: osReleaseInfo.get("name") ?? "", id: osReleaseInfo.get("id") ?? "", version: osReleaseInfo.get("version_id") ?? osReleaseInfo.get("version") ?? "", versionCodename: osReleaseInfo.get("version_codename") ?? "", - prettyName: osReleaseInfo.get("pretty_name") ?? "" + prettyName: osReleaseInfo.get("pretty_name") ?? "", + wslDistro }; } +async function checkIfWSL2(): Promise { + try { + if (!(await fs.pathExists(wslKernelReleasePath))) + return false; + const kernelRelease = await fs.readFile(wslKernelReleasePath, "utf8"); + return kernelRelease.toLowerCase().includes("wsl2") || + kernelRelease.toLowerCase().includes("microsoft"); + } catch { + return false; + } +} + export async function isDistroAlpineLinux(linuxDistroInfo: LinuxDistroInfo) { return linuxDistroInfo.id === "alpine" || linuxDistroInfo.name.toLowerCase().startsWith("alpine") || linuxDistroInfo.prettyName.toLowerCase().startsWith("alpine"); diff --git a/src/bindings/utils/getPlatformInfo.ts b/src/bindings/utils/getPlatformInfo.ts index 48c88f4f..ac97d465 100644 --- a/src/bindings/utils/getPlatformInfo.ts +++ b/src/bindings/utils/getPlatformInfo.ts @@ -2,7 +2,7 @@ import os from "os"; import {getPlatform} from "./getPlatform.js"; import {getLinuxDistroInfo} from "./getLinuxDistroInfo.js"; -export async function getPlatformInfo(): Promise<{name: string, version: string}> { +export async function getPlatformInfo(): Promise<{name: string, version: string, wslDistro?: boolean}> { const currentPlatform = getPlatform(); if (currentPlatform === "mac") @@ -15,7 +15,8 @@ export async function getPlatformInfo(): Promise<{name: string, version: string} return { name: linuxDistroInfo.name, - version: linuxDistroInfo.version + version: linuxDistroInfo.version, + ...(linuxDistroInfo.wslDistro ? { wslDistro: true } : {}) }; } else if (currentPlatform === "win") return { diff --git a/test/standalone/llama/wsl2BindingSkip.test.ts b/test/standalone/llama/wsl2BindingSkip.test.ts new file mode 100644 index 00000000..0498a7b3 --- /dev/null +++ b/test/standalone/llama/wsl2BindingSkip.test.ts @@ -0,0 +1,34 @@ +/** + * WSL2 binding test skip tests + * These test that WSL2 Linux environments skip binding tests for prebuilt CUDA binaries + */ +import { describe, it, expect } from "vitest"; + +describe("WSL2 binding skip", () => { + it("WSL2 detection: /proc/sys/kernel/osrelease contains WSL2", async () => { + const fs = await import("fs-extra"); + const exists = await fs.pathExists("/proc/sys/kernel/osrelease"); + if (!exists) { + return; // Not on Linux, skip + } + const content = await fs.readFile("/proc/sys/kernel/osrelease", "utf8"); + const isWSL = content.toLowerCase().includes("wsl2") || content.toLowerCase().includes("microsoft"); + expect(typeof isWSL).toBe("boolean"); + }); + + it("prebuilt CUDA binary path exists", async () => { + const fs = await import("fs-extra"); + const paths = [ + process.env.HOME + "/.npm-global/lib/node_modules/node-llama-cpp/node_modules/@node-llama-cpp/linux-x64-cuda/bins/linux-x64-cuda/llama-addon.node", + "/usr/local/lib/node_modules/node-llama-cpp/node_modules/@node-llama-cpp/linux-x64-cuda/bins/linux-x64-cuda/llama-addon.node" + ]; + let found = false; + for (const p of paths) { + if (await fs.pathExists(p)) { + found = true; + break; + } + } + if (!found) console.log("CUDA prebuilt binary not found, skipping"); + }); +}); diff --git a/test/utils/getLinuxDistroInfo.test.ts b/test/utils/getLinuxDistroInfo.test.ts new file mode 100644 index 00000000..db5ffd57 --- /dev/null +++ b/test/utils/getLinuxDistroInfo.test.ts @@ -0,0 +1,86 @@ +import { describe, it, expect, vi, beforeEach } from "vitest"; +import fs from "fs-extra"; +import { getLinuxDistroInfo } from "../../src/bindings/utils/getLinuxDistroInfo.js"; + +const mockExists = vi.spyOn(fs, "pathExists"); +const mockReadFile = vi.spyOn(fs, "readFile"); + +describe("getLinuxDistroInfo", () => { + beforeEach(() => { + vi.clearAllMocks(); + }); + + it("returns wslDistro true when kernel release contains WSL2", async () => { + mockExists.mockImplementation(async (path: string) => { + if (path === "/etc/os-release") return true; + if (path === "/usr/lib/os-release") return true; + if (path === "/proc/sys/kernel/osrelease") return true; + return false; + }); + mockReadFile.mockImplementation(async (path: string) => { + if (path === "/etc/os-release") return `PRETTY_NAME="Ubuntu 24.04 LTS"\nID=ubuntu\nVERSION_ID="24.04"\n`; + if (path === "/usr/lib/os-release") return ""; + if (path === "/proc/sys/kernel/osrelease") return "6.6.114.1-microsoft-standard-WSL2"; + return ""; + }); + + const result = await getLinuxDistroInfo(); + expect(result.wslDistro).toBe(true); + expect(result.name).toBe("Ubuntu"); + }); + + it("returns wslDistro true when kernel release contains Microsoft", async () => { + mockExists.mockImplementation(async (path: string) => { + if (path === "/etc/os-release") return true; + if (path === "/usr/lib/os-release") return true; + if (path === "/proc/sys/kernel/osrelease") return true; + return false; + }); + mockReadFile.mockImplementation(async (path: string) => { + if (path === "/etc/os-release") return `PRETTY_NAME="Ubuntu 22.04 LTS"\nID=ubuntu\nVERSION_ID="22.04"\n`; + if (path === "/usr/lib/os-release") return ""; + if (path === "/proc/sys/kernel/osrelease") return "5.15.153.1-microsoft-standard-WSL2"; + return ""; + }); + + const result = await getLinuxDistroInfo(); + expect(result.wslDistro).toBe(true); + }); + + it("returns wslDistro false when kernel release does not contain WSL2 or Microsoft", async () => { + mockExists.mockImplementation(async (path: string) => { + if (path === "/etc/os-release") return true; + if (path === "/usr/lib/os-release") return true; + if (path === "/proc/sys/kernel/osrelease") return true; + return false; + }); + mockReadFile.mockImplementation(async (path: string) => { + if (path === "/etc/os-release") return ""; + if (path === "/usr/lib/os-release") return `PRETTY_NAME="Ubuntu 24.04 LTS"\nID=ubuntu\nVERSION_ID="24.04"\n`; + if (path === "/proc/sys/kernel/osrelease") return "6.8.0-49-generic"; + return ""; + }); + + const result = await getLinuxDistroInfo(); + expect(result.wslDistro).toBe(false); + expect(result.name).toBe("Ubuntu"); + }); + + it("returns wslDistro false when /proc/sys/kernel/osrelease does not exist", async () => { + mockExists.mockImplementation(async (path: string) => { + if (path === "/etc/os-release") return true; + if (path === "/usr/lib/os-release") return true; + if (path === "/proc/sys/kernel/osrelease") return false; + return false; + }); + mockReadFile.mockImplementation(async (path: string) => { + if (path === "/etc/os-release") return ""; + if (path === "/usr/lib/os-release") return `PRETTY_NAME="Ubuntu 24.04 LTS"\nID=ubuntu\nVERSION_ID="24.04"\n`; + return ""; + }); + + const result = await getLinuxDistroInfo(); + expect(result.wslDistro).toBe(false); + expect(result.name).toBe("Ubuntu"); + }); +}); \ No newline at end of file diff --git a/test/utils/getPlatformInfo.test.ts b/test/utils/getPlatformInfo.test.ts new file mode 100644 index 00000000..555cd0cf --- /dev/null +++ b/test/utils/getPlatformInfo.test.ts @@ -0,0 +1,37 @@ +import { describe, it, expect, vi } from "vitest"; +import { getPlatformInfo } from "../../src/bindings/utils/getPlatformInfo.js"; +import * as getLinuxDistroInfo from "../../src/bindings/utils/getLinuxDistroInfo.js"; + +vi.mock("../../src/bindings/utils/getLinuxDistroInfo.js"); + +describe("getPlatformInfo", () => { + it("propagates wslDistro from linuxDistroInfo", async () => { + vi.spyOn(getLinuxDistroInfo, "getLinuxDistroInfo").mockResolvedValue({ + name: "Ubuntu", + id: "ubuntu", + version: "24.04", + versionCodename: "noble", + prettyName: "Ubuntu 24.04 LTS", + wslDistro: true + }); + + const result = await getPlatformInfo(); + expect(result.wslDistro).toBe(true); + expect(result.name).toBe("Ubuntu"); + }); + + it("does not include wslDistro field when not WSL2", async () => { + vi.spyOn(getLinuxDistroInfo, "getLinuxDistroInfo").mockResolvedValue({ + name: "Ubuntu", + id: "ubuntu", + version: "24.04", + versionCodename: "noble", + prettyName: "Ubuntu 24.04 LTS", + wslDistro: false + }); + + const result = await getPlatformInfo(); + expect(result.wslDistro).toBeUndefined(); + expect(result.name).toBe("Ubuntu"); + }); +});