From 456bc8df65bf4ff33719a68cf3b755242e0f8246 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Mon, 20 Apr 2026 18:35:25 +0100 Subject: [PATCH] test: share launchd integration helpers --- src/daemon/launchd.integration.e2e.test.ts | 104 +++++++++------------ 1 file changed, 44 insertions(+), 60 deletions(-) diff --git a/src/daemon/launchd.integration.e2e.test.ts b/src/daemon/launchd.integration.e2e.test.ts index 0e1535322f5..f834a6972e1 100644 --- a/src/daemon/launchd.integration.e2e.test.ts +++ b/src/daemon/launchd.integration.e2e.test.ts @@ -111,6 +111,41 @@ async function waitForNotRunningRuntime(params: { ); } +function launchEnvOrThrow(env: GatewayServiceEnv | undefined): GatewayServiceEnv { + if (!env) { + throw new Error("launchd integration env was not initialized"); + } + return env; +} + +async function initializeLaunchdRuntime(launchEnv: GatewayServiceEnv, stdout: PassThrough) { + await withTimeout({ + run: async () => { + await installLaunchAgent({ + env: launchEnv, + stdout, + programArguments: [process.execPath, "-e", "setInterval(() => {}, 1000);"], + }); + await waitForRunningRuntime({ env: launchEnv }); + }, + timeoutMs: STARTUP_TIMEOUT_MS, + message: "Timed out initializing launchd integration runtime", + }); +} + +async function expectRuntimePidReplaced(params: { + env: GatewayServiceEnv; + previousPid: number; +}): Promise { + const after = await waitForRunningRuntime({ + env: params.env, + pidNot: params.previousPid, + }); + expect(after.pid).toBeGreaterThan(1); + expect(after.pid).not.toBe(params.previousPid); + await fs.access(resolveLaunchAgentPlistPath(params.env)); +} + describeLaunchdIntegration("launchd integration", () => { let env: GatewayServiceEnv | undefined; let homeDir = ""; @@ -140,53 +175,22 @@ describeLaunchdIntegration("launchd integration", () => { }, 60_000); it("restarts launchd service and keeps it running with a new pid", async () => { - if (!env) { - throw new Error("launchd integration env was not initialized"); - } - const launchEnv = env; + const launchEnv = launchEnvOrThrow(env); try { - await withTimeout({ - run: async () => { - await installLaunchAgent({ - env: launchEnv, - stdout, - programArguments: [process.execPath, "-e", "setInterval(() => {}, 1000);"], - }); - await waitForRunningRuntime({ env: launchEnv }); - }, - timeoutMs: STARTUP_TIMEOUT_MS, - message: "Timed out initializing launchd integration runtime", - }); + await initializeLaunchdRuntime(launchEnv, stdout); } catch { // Best-effort integration check only; skip when launchctl is unstable in CI. return; } const before = await waitForRunningRuntime({ env: launchEnv }); await restartLaunchAgent({ env: launchEnv, stdout }); - const after = await waitForRunningRuntime({ env: launchEnv, pidNot: before.pid }); - expect(after.pid).toBeGreaterThan(1); - expect(after.pid).not.toBe(before.pid); - await fs.access(resolveLaunchAgentPlistPath(launchEnv)); + await expectRuntimePidReplaced({ env: launchEnv, previousPid: before.pid }); }, 60_000); it("stops persistently without reinstall and starts later", async () => { - if (!env) { - throw new Error("launchd integration env was not initialized"); - } - const launchEnv = env; + const launchEnv = launchEnvOrThrow(env); try { - await withTimeout({ - run: async () => { - await installLaunchAgent({ - env: launchEnv, - stdout, - programArguments: [process.execPath, "-e", "setInterval(() => {}, 1000);"], - }); - await waitForRunningRuntime({ env: launchEnv }); - }, - timeoutMs: STARTUP_TIMEOUT_MS, - message: "Timed out initializing launchd integration runtime", - }); + await initializeLaunchdRuntime(launchEnv, stdout); } catch { return; } @@ -197,30 +201,13 @@ describeLaunchdIntegration("launchd integration", () => { const service = resolveGatewayService(); const startResult = await startGatewayService(service, { env: launchEnv, stdout }); expect(startResult.outcome).toBe("started"); - const after = await waitForRunningRuntime({ env: launchEnv, pidNot: before.pid }); - expect(after.pid).toBeGreaterThan(1); - expect(after.pid).not.toBe(before.pid); - await fs.access(resolveLaunchAgentPlistPath(launchEnv)); + await expectRuntimePidReplaced({ env: launchEnv, previousPid: before.pid }); }, 60_000); it("stops persistently without reinstall and restarts later", async () => { - if (!env) { - throw new Error("launchd integration env was not initialized"); - } - const launchEnv = env; + const launchEnv = launchEnvOrThrow(env); try { - await withTimeout({ - run: async () => { - await installLaunchAgent({ - env: launchEnv, - stdout, - programArguments: [process.execPath, "-e", "setInterval(() => {}, 1000);"], - }); - await waitForRunningRuntime({ env: launchEnv }); - }, - timeoutMs: STARTUP_TIMEOUT_MS, - message: "Timed out initializing launchd integration runtime", - }); + await initializeLaunchdRuntime(launchEnv, stdout); } catch { return; } @@ -229,9 +216,6 @@ describeLaunchdIntegration("launchd integration", () => { await stopLaunchAgent({ env: launchEnv, stdout }); await waitForNotRunningRuntime({ env: launchEnv }); await restartLaunchAgent({ env: launchEnv, stdout }); - const after = await waitForRunningRuntime({ env: launchEnv, pidNot: before.pid }); - expect(after.pid).toBeGreaterThan(1); - expect(after.pid).not.toBe(before.pid); - await fs.access(resolveLaunchAgentPlistPath(launchEnv)); + await expectRuntimePidReplaced({ env: launchEnv, previousPid: before.pid }); }, 60_000); });