diff --git a/src/daemon/service.test.ts b/src/daemon/service.test.ts index 435aaf1c196..bce7c41d866 100644 --- a/src/daemon/service.test.ts +++ b/src/daemon/service.test.ts @@ -4,6 +4,7 @@ import { afterEach, describe, expect, it, vi } from "vitest"; import { clearConfigCache, clearRuntimeConfigSnapshot } from "../config/config.js"; import { makeTempWorkspace } from "../test-helpers/workspace.js"; import { captureEnv } from "../test-utils/env.js"; +import { mockProcessPlatform } from "../test-utils/vitest-spies.js"; import type { GatewayService } from "./service.js"; import { describeGatewayServiceRestart, @@ -14,24 +15,12 @@ import { } from "./service.js"; import { createMockGatewayService } from "./service.test-helpers.js"; -const originalPlatformDescriptor = Object.getOwnPropertyDescriptor(process, "platform"); - -function setPlatform(value: NodeJS.Platform | "aix") { - if (!originalPlatformDescriptor) { - throw new Error("missing process.platform descriptor"); - } - Object.defineProperty(process, "platform", { - configurable: true, - enumerable: originalPlatformDescriptor.enumerable ?? false, - value, - }); +function setPlatform(value: NodeJS.Platform) { + mockProcessPlatform(value); } afterEach(() => { - if (!originalPlatformDescriptor) { - return; - } - Object.defineProperty(process, "platform", originalPlatformDescriptor); + vi.restoreAllMocks(); }); function createService(overrides: Partial = {}): GatewayService { diff --git a/src/infra/gateway-processes.test.ts b/src/infra/gateway-processes.test.ts index 90a26c7190a..39d933d8fdd 100644 --- a/src/infra/gateway-processes.test.ts +++ b/src/infra/gateway-processes.test.ts @@ -1,4 +1,5 @@ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; +import { mockProcessPlatform } from "../test-utils/vitest-spies.js"; const spawnSyncMock = vi.hoisted(() => vi.fn()); const readFileSyncMock = vi.hoisted(() => vi.fn()); @@ -63,13 +64,8 @@ const { signalVerifiedGatewayPidSync, } = await import("./gateway-processes.js"); -const originalPlatformDescriptor = Object.getOwnPropertyDescriptor(process, "platform"); - function setPlatform(platform: NodeJS.Platform): void { - Object.defineProperty(process, "platform", { - value: platform, - configurable: true, - }); + mockProcessPlatform(platform); } describe("gateway-processes", () => { @@ -84,9 +80,6 @@ describe("gateway-processes", () => { afterEach(() => { vi.restoreAllMocks(); - if (originalPlatformDescriptor) { - Object.defineProperty(process, "platform", originalPlatformDescriptor); - } }); it("reads linux process args from /proc and parses cmdlines", () => { diff --git a/src/infra/path-guards.test.ts b/src/infra/path-guards.test.ts index ce2941e62a4..af32ebb00d8 100644 --- a/src/infra/path-guards.test.ts +++ b/src/infra/path-guards.test.ts @@ -1,4 +1,5 @@ -import { afterEach, describe, expect, it } from "vitest"; +import { afterEach, describe, expect, it, vi } from "vitest"; +import { mockProcessPlatform } from "../test-utils/vitest-spies.js"; import { hasNodeErrorCode, isNodeError, @@ -8,19 +9,12 @@ import { normalizeWindowsPathForComparison, } from "./path-guards.js"; -const originalPlatformDescriptor = Object.getOwnPropertyDescriptor(process, "platform"); - function setPlatform(platform: NodeJS.Platform): void { - Object.defineProperty(process, "platform", { - value: platform, - configurable: true, - }); + mockProcessPlatform(platform); } afterEach(() => { - if (originalPlatformDescriptor) { - Object.defineProperty(process, "platform", originalPlatformDescriptor); - } + vi.restoreAllMocks(); }); describe("normalizeWindowsPathForComparison", () => { diff --git a/src/infra/ports.test.ts b/src/infra/ports.test.ts index 873e7a03cec..04a78885b59 100644 --- a/src/infra/ports.test.ts +++ b/src/infra/ports.test.ts @@ -1,5 +1,6 @@ import net from "node:net"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; +import { mockProcessPlatform } from "../test-utils/vitest-spies.js"; import { stripAnsi } from "../terminal/ansi.js"; const runCommandWithTimeoutMock = vi.hoisted(() => vi.fn()); @@ -15,13 +16,9 @@ let handlePortError: typeof import("./ports.js").handlePortError; let PortInUseError: typeof import("./ports.js").PortInUseError; const describeUnix = process.platform === "win32" ? describe.skip : describe; -const originalPlatformDescriptor = Object.getOwnPropertyDescriptor(process, "platform"); function setPlatform(platform: NodeJS.Platform): void { - Object.defineProperty(process, "platform", { - value: platform, - configurable: true, - }); + mockProcessPlatform(platform); } async function listenServer( @@ -63,9 +60,7 @@ beforeEach(() => { }); afterEach(() => { - if (originalPlatformDescriptor) { - Object.defineProperty(process, "platform", originalPlatformDescriptor); - } + vi.restoreAllMocks(); }); describe("ports helpers", () => { diff --git a/src/shared/config-eval.test.ts b/src/shared/config-eval.test.ts index 199c22a3462..3c16f2fa9f1 100644 --- a/src/shared/config-eval.test.ts +++ b/src/shared/config-eval.test.ts @@ -1,6 +1,7 @@ import fs from "node:fs"; import path from "node:path"; import { afterEach, describe, expect, it, vi } from "vitest"; +import { mockProcessPlatform } from "../test-utils/vitest-spies.js"; import { evaluateRuntimeEligibility, evaluateRuntimeRequires, @@ -11,15 +12,11 @@ import { resolveRuntimePlatform, } from "./config-eval.js"; -const originalPlatformDescriptor = Object.getOwnPropertyDescriptor(process, "platform"); const originalPath = process.env.PATH; const originalPathExt = process.env.PATHEXT; function setPlatform(platform: NodeJS.Platform): void { - Object.defineProperty(process, "platform", { - value: platform, - configurable: true, - }); + mockProcessPlatform(platform); } afterEach(() => { @@ -30,9 +27,6 @@ afterEach(() => { } else { process.env.PATHEXT = originalPathExt; } - if (originalPlatformDescriptor) { - Object.defineProperty(process, "platform", originalPlatformDescriptor); - } }); describe("config-eval helpers", () => { diff --git a/src/shared/entry-status.test.ts b/src/shared/entry-status.test.ts index 687c82ff42c..da493db0a50 100644 --- a/src/shared/entry-status.test.ts +++ b/src/shared/entry-status.test.ts @@ -1,23 +1,17 @@ -import { afterEach, describe, expect, it } from "vitest"; +import { afterEach, describe, expect, it, vi } from "vitest"; +import { mockProcessPlatform } from "../test-utils/vitest-spies.js"; import { evaluateEntryMetadataRequirements, evaluateEntryMetadataRequirementsForCurrentPlatform, evaluateEntryRequirementsForCurrentPlatform, } from "./entry-status.js"; -const originalPlatformDescriptor = Object.getOwnPropertyDescriptor(process, "platform"); - function setPlatform(platform: NodeJS.Platform): void { - Object.defineProperty(process, "platform", { - value: platform, - configurable: true, - }); + mockProcessPlatform(platform); } afterEach(() => { - if (originalPlatformDescriptor) { - Object.defineProperty(process, "platform", originalPlatformDescriptor); - } + vi.restoreAllMocks(); }); describe("shared/entry-status", () => { diff --git a/src/shared/pid-alive.test.ts b/src/shared/pid-alive.test.ts index f26cd7f5b6c..8ab0600b7bf 100644 --- a/src/shared/pid-alive.test.ts +++ b/src/shared/pid-alive.test.ts @@ -1,5 +1,6 @@ import fsSync from "node:fs"; import { afterEach, describe, expect, it, vi } from "vitest"; +import { withMockedPlatform } from "../test-utils/vitest-spies.js"; import { getProcessStartTime, isPidAlive, isPidDefinitelyDead } from "./pid-alive.js"; afterEach(() => { @@ -17,30 +18,6 @@ function mockProcReads(entries: Record) { }); } -async function withLinuxProcessPlatform(run: () => Promise): Promise { - return withProcessPlatform("linux", run); -} - -async function withProcessPlatform( - platform: NodeJS.Platform, - run: () => Promise, -): Promise { - const originalPlatformDescriptor = Object.getOwnPropertyDescriptor(process, "platform"); - if (!originalPlatformDescriptor) { - throw new Error("missing process.platform descriptor"); - } - Object.defineProperty(process, "platform", { - ...originalPlatformDescriptor, - value: platform, - }); - try { - return await run(); - } finally { - Object.defineProperty(process, "platform", originalPlatformDescriptor); - vi.restoreAllMocks(); - } -} - describe("isPidAlive", () => { it("returns true for the current running process", () => { expect(isPidAlive(process.pid)).toBe(true); @@ -64,7 +41,7 @@ describe("isPidAlive", () => { mockProcReads({ [`/proc/${zombiePid}/status`]: `Name:\tnode\nUmask:\t0022\nState:\tZ (zombie)\nTgid:\t${zombiePid}\nPid:\t${zombiePid}\n`, }); - await withLinuxProcessPlatform(async () => { + await withMockedPlatform("linux", async () => { expect(isPidAlive(zombiePid)).toBe(false); }); }); @@ -75,7 +52,7 @@ describe("isPidAlive", () => { }); const killSpy = vi.spyOn(process, "kill").mockImplementation(() => true); - await withLinuxProcessPlatform(async () => { + await withMockedPlatform("linux", async () => { expect(isPidAlive(42)).toBe(true); }); @@ -120,7 +97,7 @@ describe("isPidDefinitelyDead", () => { [`/proc/${zombiePid}/status`]: `Name:\tnode\nUmask:\t0022\nState:\tZ (zombie)\nTgid:\t${zombiePid}\nPid:\t${zombiePid}\n`, }); - await withLinuxProcessPlatform(async () => { + await withMockedPlatform("linux", async () => { expect(isPidDefinitelyDead(zombiePid)).toBe(true); }); }); @@ -132,7 +109,7 @@ describe("isPidDefinitelyDead", () => { [`/proc/${livePid}/status`]: `Name:\tnode\nUmask:\t0022\nState:\tS (sleeping)\nTgid:\t${livePid}\nPid:\t${livePid}\n`, }); - await withLinuxProcessPlatform(async () => { + await withMockedPlatform("linux", async () => { expect(isPidDefinitelyDead(livePid)).toBe(false); }); }); @@ -152,7 +129,7 @@ describe("getProcessStartTime", () => { "/proc/46/stat": `${fakeStatPrefix}1.5${fakeStatSuffix}`, }); - await withLinuxProcessPlatform(async () => { + await withMockedPlatform("linux", async () => { expect(getProcessStartTime(process.pid)).toBe(98765); expect(getProcessStartTime(42)).toBe(55555); expect(getProcessStartTime(43)).toBeNull(); @@ -163,7 +140,7 @@ describe("getProcessStartTime", () => { }); it("returns null on non-Linux platforms", () => { - return withProcessPlatform("darwin", async () => { + return withMockedPlatform("darwin", async () => { expect(getProcessStartTime(process.pid)).toBeNull(); }); }); diff --git a/src/test-utils/vitest-spies.ts b/src/test-utils/vitest-spies.ts index 0745531b6e1..6554ce51c13 100644 --- a/src/test-utils/vitest-spies.ts +++ b/src/test-utils/vitest-spies.ts @@ -40,13 +40,17 @@ export function withRestoredMocks( } } +export function mockProcessPlatform(platform: NodeJS.Platform): RestorableMock { + return vi.spyOn(process, "platform", "get").mockReturnValue(platform); +} + export function withMockedPlatform(platform: NodeJS.Platform, run: () => Promise): Promise; export function withMockedPlatform(platform: NodeJS.Platform, run: () => T): T; export function withMockedPlatform( platform: NodeJS.Platform, run: () => T | Promise, ): T | Promise { - return withRestoredMocks([vi.spyOn(process, "platform", "get").mockReturnValue(platform)], run); + return withRestoredMocks([mockProcessPlatform(platform)], run); } export function withMockedWindowsPlatform(run: () => Promise): Promise;