From a7382ec5630063c284aeb92d64d810eec08fe717 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sun, 26 Apr 2026 06:18:37 +0100 Subject: [PATCH] test: cover older-binary service guard --- src/daemon/service.test.ts | 43 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/src/daemon/service.test.ts b/src/daemon/service.test.ts index 66b14b94fdf..07b3b8a82c7 100644 --- a/src/daemon/service.test.ts +++ b/src/daemon/service.test.ts @@ -1,4 +1,9 @@ +import fs from "node:fs/promises"; +import path from "node:path"; 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 type { GatewayService } from "./service.js"; import { describeGatewayServiceRestart, @@ -49,6 +54,44 @@ describe("resolveGatewayService", () => { expect(() => resolveGatewayService()).toThrow("Gateway service install not supported on aix"); }); + it("guards mutating service adapters when config was written by a newer OpenClaw", async () => { + const tempHome = await makeTempWorkspace("openclaw-service-future-config-"); + const stateDir = path.join(tempHome, ".openclaw"); + const configPath = path.join(stateDir, "openclaw.json"); + const envSnapshot = captureEnv(["HOME", "OPENCLAW_STATE_DIR", "OPENCLAW_CONFIG_PATH"]); + try { + await fs.mkdir(stateDir, { recursive: true }); + await fs.writeFile( + configPath, + JSON.stringify( + { + meta: { + lastTouchedVersion: "9999.1.1", + }, + }, + null, + 2, + ), + ); + process.env.HOME = tempHome; + process.env.OPENCLAW_STATE_DIR = stateDir; + process.env.OPENCLAW_CONFIG_PATH = configPath; + clearConfigCache(); + clearRuntimeConfigSnapshot(); + + const service = resolveGatewayService(); + + await expect(service.restart({ env: process.env, stdout: process.stdout })).rejects.toThrow( + "Refusing to restart the gateway service", + ); + } finally { + envSnapshot.restore(); + clearConfigCache(); + clearRuntimeConfigSnapshot(); + await fs.rm(tempHome, { recursive: true, force: true }); + } + }); + it("describes scheduled restart handoffs consistently", () => { expect(describeGatewayServiceRestart("Gateway", { outcome: "scheduled" })).toEqual({ scheduled: true,