refactor: share system run plan test fixtures

This commit is contained in:
Peter Steinberger
2026-03-13 18:42:34 +00:00
parent c2096897bb
commit 07e5fc19bd

View File

@@ -68,20 +68,36 @@ function createScriptOperandFixture(tmp: string, fixture?: RuntimeFixture): Scri
}; };
} }
function withFakeRuntimeBin<T>(params: { binName: string; run: () => T }): T { function writeFakeRuntimeBin(binDir: string, binName: string) {
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), `openclaw-${params.binName}-bin-`));
const binDir = path.join(tmp, "bin");
fs.mkdirSync(binDir, { recursive: true });
const runtimePath = const runtimePath =
process.platform === "win32" process.platform === "win32" ? path.join(binDir, `${binName}.cmd`) : path.join(binDir, binName);
? path.join(binDir, `${params.binName}.cmd`)
: path.join(binDir, params.binName);
const runtimeBody = const runtimeBody =
process.platform === "win32" ? "@echo off\r\nexit /b 0\r\n" : "#!/bin/sh\nexit 0\n"; process.platform === "win32" ? "@echo off\r\nexit /b 0\r\n" : "#!/bin/sh\nexit 0\n";
fs.writeFileSync(runtimePath, runtimeBody, { mode: 0o755 }); fs.writeFileSync(runtimePath, runtimeBody, { mode: 0o755 });
if (process.platform !== "win32") { if (process.platform !== "win32") {
fs.chmodSync(runtimePath, 0o755); fs.chmodSync(runtimePath, 0o755);
} }
}
function withFakeRuntimeBin<T>(params: { binName: string; run: () => T }): T {
return withFakeRuntimeBins({
binNames: [params.binName],
tmpPrefix: `openclaw-${params.binName}-bin-`,
run: params.run,
});
}
function withFakeRuntimeBins<T>(params: {
binNames: string[];
tmpPrefix?: string;
run: () => T;
}): T {
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), params.tmpPrefix ?? "openclaw-runtime-bins-"));
const binDir = path.join(tmp, "bin");
fs.mkdirSync(binDir, { recursive: true });
for (const binName of params.binNames) {
writeFakeRuntimeBin(binDir, binName);
}
const oldPath = process.env.PATH; const oldPath = process.env.PATH;
process.env.PATH = `${binDir}${path.delimiter}${oldPath ?? ""}`; process.env.PATH = `${binDir}${path.delimiter}${oldPath ?? ""}`;
try { try {
@@ -96,32 +112,44 @@ function withFakeRuntimeBin<T>(params: { binName: string; run: () => T }): T {
} }
} }
function withFakeRuntimeBins<T>(params: { binNames: string[]; run: () => T }): T { function expectMutableFileOperandApprovalPlan(fixture: ScriptOperandFixture, cwd: string) {
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-runtime-bins-")); const prepared = buildSystemRunApprovalPlan({
const binDir = path.join(tmp, "bin"); command: fixture.command,
fs.mkdirSync(binDir, { recursive: true }); cwd,
for (const binName of params.binNames) { });
const runtimePath = expect(prepared.ok).toBe(true);
process.platform === "win32" if (!prepared.ok) {
? path.join(binDir, `${binName}.cmd`) throw new Error("unreachable");
: path.join(binDir, binName);
const runtimeBody =
process.platform === "win32" ? "@echo off\r\nexit /b 0\r\n" : "#!/bin/sh\nexit 0\n";
fs.writeFileSync(runtimePath, runtimeBody, { mode: 0o755 });
if (process.platform !== "win32") {
fs.chmodSync(runtimePath, 0o755);
}
} }
const oldPath = process.env.PATH; expect(prepared.plan.mutableFileOperand).toEqual({
process.env.PATH = `${binDir}${path.delimiter}${oldPath ?? ""}`; argvIndex: fixture.expectedArgvIndex,
path: fs.realpathSync(fixture.scriptPath),
sha256: expect.any(String),
});
}
function writeScriptOperandFixture(fixture: ScriptOperandFixture) {
fs.writeFileSync(fixture.scriptPath, fixture.initialBody);
if (process.platform !== "win32") {
fs.chmodSync(fixture.scriptPath, 0o755);
}
}
function withScriptOperandPlanFixture<T>(
params: {
tmpPrefix: string;
fixture?: RuntimeFixture;
afterWrite?: (fixture: ScriptOperandFixture, tmp: string) => void;
},
run: (fixture: ScriptOperandFixture, tmp: string) => T,
) {
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), params.tmpPrefix));
const fixture = createScriptOperandFixture(tmp, params.fixture);
writeScriptOperandFixture(fixture);
params.afterWrite?.(fixture, tmp);
try { try {
return params.run(); return run(fixture, tmp);
} finally { } finally {
if (oldPath === undefined) {
delete process.env.PATH;
} else {
process.env.PATH = oldPath;
}
fs.rmSync(tmp, { recursive: true, force: true }); fs.rmSync(tmp, { recursive: true, force: true });
} }
} }
@@ -432,61 +460,37 @@ describe("hardenApprovedExecutionPaths", () => {
withFakeRuntimeBins({ withFakeRuntimeBins({
binNames, binNames,
run: () => { run: () => {
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-approval-script-plan-")); withScriptOperandPlanFixture(
const fixture = createScriptOperandFixture(tmp, runtimeCase); {
fs.writeFileSync(fixture.scriptPath, fixture.initialBody); tmpPrefix: "openclaw-approval-script-plan-",
const executablePath = fixture.command[0]; fixture: runtimeCase,
if (executablePath?.endsWith("pnpm.js")) { afterWrite: (fixture, tmp) => {
const shimPath = path.join(tmp, "pnpm.js"); const executablePath = fixture.command[0];
fs.writeFileSync(shimPath, "#!/usr/bin/env node\nconsole.log('shim')\n"); if (executablePath?.endsWith("pnpm.js")) {
fs.chmodSync(shimPath, 0o755); const shimPath = path.join(tmp, "pnpm.js");
} fs.writeFileSync(shimPath, "#!/usr/bin/env node\nconsole.log('shim')\n");
try { fs.chmodSync(shimPath, 0o755);
const prepared = buildSystemRunApprovalPlan({ }
command: fixture.command, },
cwd: tmp, },
}); (fixture, tmp) => {
expect(prepared.ok).toBe(true); expectMutableFileOperandApprovalPlan(fixture, tmp);
if (!prepared.ok) { },
throw new Error("unreachable"); );
}
expect(prepared.plan.mutableFileOperand).toEqual({
argvIndex: fixture.expectedArgvIndex,
path: fs.realpathSync(fixture.scriptPath),
sha256: expect.any(String),
});
} finally {
fs.rmSync(tmp, { recursive: true, force: true });
}
}, },
}); });
}); });
} }
it("captures mutable shell script operands in approval plans", () => { it("captures mutable shell script operands in approval plans", () => {
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-approval-script-plan-")); withScriptOperandPlanFixture(
const fixture = createScriptOperandFixture(tmp); {
fs.writeFileSync(fixture.scriptPath, fixture.initialBody); tmpPrefix: "openclaw-approval-script-plan-",
if (process.platform !== "win32") { },
fs.chmodSync(fixture.scriptPath, 0o755); (fixture, tmp) => {
} expectMutableFileOperandApprovalPlan(fixture, tmp);
try { },
const prepared = buildSystemRunApprovalPlan({ );
command: fixture.command,
cwd: tmp,
});
expect(prepared.ok).toBe(true);
if (!prepared.ok) {
throw new Error("unreachable");
}
expect(prepared.plan.mutableFileOperand).toEqual({
argvIndex: fixture.expectedArgvIndex,
path: fs.realpathSync(fixture.scriptPath),
sha256: expect.any(String),
});
} finally {
fs.rmSync(tmp, { recursive: true, force: true });
}
}); });
it("rejects bun package script names that do not bind a concrete file", () => { it("rejects bun package script names that do not bind a concrete file", () => {