mirror of
https://github.com/moltbot/moltbot.git
synced 2026-05-07 07:58:36 +00:00
100 lines
3.1 KiB
TypeScript
100 lines
3.1 KiB
TypeScript
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
import { captureEnv } from "../test-utils/env.js";
|
|
import { resetProcessRegistryForTests } from "./bash-process-registry.js";
|
|
import { createExecTool } from "./bash-tools.exec.js";
|
|
import { resolveShellFromPath } from "./shell-utils.js";
|
|
|
|
const isWin = process.platform === "win32";
|
|
const defaultShell = isWin
|
|
? undefined
|
|
: process.env.OPENCLAW_TEST_SHELL || resolveShellFromPath("bash") || process.env.SHELL || "sh";
|
|
const longDelayCmd = isWin ? "Start-Sleep -Seconds 5" : "sleep 5";
|
|
|
|
describe("exec foreground failures", () => {
|
|
let envSnapshot: ReturnType<typeof captureEnv>;
|
|
|
|
beforeEach(() => {
|
|
vi.useRealTimers();
|
|
envSnapshot = captureEnv(["SHELL"]);
|
|
if (!isWin && defaultShell) {
|
|
process.env.SHELL = defaultShell;
|
|
}
|
|
resetProcessRegistryForTests();
|
|
});
|
|
|
|
afterEach(() => {
|
|
vi.useRealTimers();
|
|
envSnapshot.restore();
|
|
});
|
|
|
|
it("returns a failed text result when the default timeout is exceeded", async () => {
|
|
const tool = createExecTool({
|
|
security: "full",
|
|
ask: "off",
|
|
timeoutSec: 0.05,
|
|
backgroundMs: 10,
|
|
allowBackground: false,
|
|
});
|
|
|
|
const result = await tool.execute("call-timeout", {
|
|
command: longDelayCmd,
|
|
});
|
|
|
|
expect(result.content[0]).toMatchObject({ type: "text" });
|
|
expect((result.content[0] as { text?: string }).text).toMatch(/timed out/i);
|
|
expect((result.content[0] as { text?: string }).text).toMatch(/re-run with a higher timeout/i);
|
|
expect(result.details).toMatchObject({
|
|
status: "failed",
|
|
exitCode: null,
|
|
aggregated: "",
|
|
});
|
|
expect((result.details as { durationMs?: number }).durationMs).toEqual(expect.any(Number));
|
|
});
|
|
|
|
it("keeps the background-disabled warning when exec actually runs synchronously", async () => {
|
|
const tool = createExecTool({
|
|
security: "full",
|
|
ask: "off",
|
|
allowBackground: false,
|
|
});
|
|
|
|
const result = await tool.execute("call-background-disabled-foreground", {
|
|
command: isWin ? "Write-Output ok" : "printf ok",
|
|
background: true,
|
|
});
|
|
|
|
expect(result.details.status).toBe("completed");
|
|
expect((result.content[0] as { text?: string }).text).toContain(
|
|
"Warning: background execution is disabled; running synchronously.",
|
|
);
|
|
});
|
|
|
|
it("rejects invalid host values before launching a command", async () => {
|
|
const tool = createExecTool({
|
|
security: "full",
|
|
ask: "off",
|
|
allowBackground: false,
|
|
});
|
|
for (const testCase of [
|
|
{
|
|
host: "spark-ff13",
|
|
message: 'Invalid exec host "spark-ff13". Allowed values: auto, sandbox, gateway, node.',
|
|
},
|
|
{
|
|
host: 42,
|
|
message:
|
|
"Invalid exec host value type number. Allowed values: auto, sandbox, gateway, node.",
|
|
},
|
|
]) {
|
|
const malformedArgs = {
|
|
command: "echo should-not-run",
|
|
host: testCase.host,
|
|
} as unknown as Parameters<typeof tool.execute>[1];
|
|
|
|
await expect(tool.execute("call-invalid-host", malformedArgs)).rejects.toThrow(
|
|
testCase.message,
|
|
);
|
|
}
|
|
});
|
|
});
|