From 41bdf2df41a29f5c4da9d12da608aee63c68410f Mon Sep 17 00:00:00 2001 From: Josh Lehman Date: Mon, 2 Mar 2026 15:12:28 -0800 Subject: [PATCH] test: skip chmod-dependent backup rotation tests on Windows MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit chmod is a no-op on Windows — file permissions always report 0o666 regardless of what was set, so asserting 0o600 will never pass. --- src/config/config.backup-rotation.test.ts | 69 +++++++++++------------ 1 file changed, 33 insertions(+), 36 deletions(-) diff --git a/src/config/config.backup-rotation.test.ts b/src/config/config.backup-rotation.test.ts index 3e60b28a061..db8cbfe3b80 100644 --- a/src/config/config.backup-rotation.test.ts +++ b/src/config/config.backup-rotation.test.ts @@ -10,6 +10,8 @@ import { import { withTempHome } from "./test-helpers.js"; import type { OpenClawConfig } from "./types.js"; +const IS_WINDOWS = process.platform === "win32"; + describe("config backup rotation", () => { it("keeps a 5-deep backup ring for config writes", async () => { await withTempHome(async () => { @@ -55,7 +57,8 @@ describe("config backup rotation", () => { }); }); - it("hardenBackupPermissions sets 0o600 on all backup files", async () => { + // chmod is a no-op on Windows — 0o600 can never be observed there. + it.skipIf(IS_WINDOWS)("hardenBackupPermissions sets 0o600 on all backup files", async () => { await withTempHome(async () => { const stateDir = process.env.OPENCLAW_STATE_DIR?.trim(); if (!stateDir) { @@ -72,14 +75,8 @@ describe("config backup rotation", () => { const bakStat = await fs.stat(`${configPath}.bak`); const bak1Stat = await fs.stat(`${configPath}.bak.1`); - // Windows does not reliably honor POSIX chmod bits. - if (process.platform === "win32") { - expect(bakStat.mode & 0o777).toBeGreaterThan(0); - expect(bak1Stat.mode & 0o777).toBeGreaterThan(0); - } else { - expect(bakStat.mode & 0o777).toBe(0o600); - expect(bak1Stat.mode & 0o777).toBe(0o600); - } + expect(bakStat.mode & 0o777).toBe(0o600); + expect(bak1Stat.mode & 0o777).toBe(0o600); }); }); @@ -119,34 +116,34 @@ describe("config backup rotation", () => { }); }); - it("maintainConfigBackups composes rotate/copy/harden/prune flow", async () => { - await withTempHome(async () => { - const stateDir = process.env.OPENCLAW_STATE_DIR?.trim(); - if (!stateDir) { - throw new Error("Expected OPENCLAW_STATE_DIR to be set by withTempHome"); - } - const configPath = path.join(stateDir, "openclaw.json"); - await fs.writeFile(configPath, JSON.stringify({ token: "secret" }), { mode: 0o600 }); - await fs.writeFile(`${configPath}.bak`, "previous", { mode: 0o644 }); - await fs.writeFile(`${configPath}.bak.orphan`, "old"); + // chmod is a no-op on Windows — permission assertions will always fail. + it.skipIf(IS_WINDOWS)( + "maintainConfigBackups composes rotate/copy/harden/prune flow", + async () => { + await withTempHome(async () => { + const stateDir = process.env.OPENCLAW_STATE_DIR?.trim(); + if (!stateDir) { + throw new Error("Expected OPENCLAW_STATE_DIR to be set by withTempHome"); + } + const configPath = path.join(stateDir, "openclaw.json"); + await fs.writeFile(configPath, JSON.stringify({ token: "secret" }), { mode: 0o600 }); + await fs.writeFile(`${configPath}.bak`, "previous", { mode: 0o644 }); + await fs.writeFile(`${configPath}.bak.orphan`, "old"); - await maintainConfigBackups(configPath, fs); + await maintainConfigBackups(configPath, fs); - // A new primary backup is created from the current config. - await expect(fs.readFile(`${configPath}.bak`, "utf-8")).resolves.toBe( - JSON.stringify({ token: "secret" }), - ); - // Prior primary backup gets rotated into ring slot 1. - await expect(fs.readFile(`${configPath}.bak.1`, "utf-8")).resolves.toBe("previous"); - // Mode hardening still applies on POSIX systems. - const primaryBackupStat = await fs.stat(`${configPath}.bak`); - if (process.platform === "win32") { - expect(primaryBackupStat.mode & 0o777).toBeGreaterThan(0); - } else { + // A new primary backup is created from the current config. + await expect(fs.readFile(`${configPath}.bak`, "utf-8")).resolves.toBe( + JSON.stringify({ token: "secret" }), + ); + // Prior primary backup gets rotated into ring slot 1. + await expect(fs.readFile(`${configPath}.bak.1`, "utf-8")).resolves.toBe("previous"); + // Mode hardening still applies. + const primaryBackupStat = await fs.stat(`${configPath}.bak`); expect(primaryBackupStat.mode & 0o777).toBe(0o600); - } - // Out-of-ring orphan gets pruned. - await expect(fs.stat(`${configPath}.bak.orphan`)).rejects.toThrow(); - }); - }); + // Out-of-ring orphan gets pruned. + await expect(fs.stat(`${configPath}.bak.orphan`)).rejects.toThrow(); + }); + }, + ); });