perf(test): remove flaky transport timeout and dedupe safeBins checks
This commit is contained in:
@@ -6,6 +6,31 @@ import "./test-helpers/fast-coding-tools.js";
|
||||
import type { OpenClawConfig } from "../config/config.js";
|
||||
import { ensureOpenClawModelsJson } from "./models-config.js";
|
||||
|
||||
vi.mock("@mariozechner/pi-coding-agent", async () => {
|
||||
const actual = await vi.importActual<typeof import("@mariozechner/pi-coding-agent")>(
|
||||
"@mariozechner/pi-coding-agent",
|
||||
);
|
||||
|
||||
return {
|
||||
...actual,
|
||||
createAgentSession: async (
|
||||
...args: Parameters<typeof actual.createAgentSession>
|
||||
): ReturnType<typeof actual.createAgentSession> => {
|
||||
const result = await actual.createAgentSession(...args);
|
||||
const modelId = (args[0] as { model?: { id?: string } } | undefined)?.model?.id;
|
||||
if (modelId === "mock-throw") {
|
||||
const session = result.session as { prompt?: (...params: unknown[]) => Promise<unknown> };
|
||||
if (session && typeof session.prompt === "function") {
|
||||
session.prompt = async () => {
|
||||
throw new Error("transport failed");
|
||||
};
|
||||
}
|
||||
}
|
||||
return result;
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("@mariozechner/pi-ai", async () => {
|
||||
const actual = await vi.importActual<typeof import("@mariozechner/pi-ai")>("@mariozechner/pi-ai");
|
||||
|
||||
@@ -73,9 +98,6 @@ vi.mock("@mariozechner/pi-ai", async () => {
|
||||
return buildAssistantMessage(model);
|
||||
},
|
||||
streamSimple: (model: { api: string; provider: string; id: string }) => {
|
||||
if (model.id === "mock-throw") {
|
||||
throw new Error("transport failed");
|
||||
}
|
||||
const stream = actual.createAssistantMessageEventStream();
|
||||
queueMicrotask(() => {
|
||||
stream.push({
|
||||
@@ -384,34 +406,28 @@ describe("runEmbeddedPiAgent", () => {
|
||||
expect(userIndex).toBeGreaterThanOrEqual(0);
|
||||
});
|
||||
|
||||
it("persists prompt transport errors as transcript entries", async () => {
|
||||
it("fails fast on prompt transport errors", async () => {
|
||||
const sessionFile = nextSessionFile();
|
||||
const cfg = makeOpenAiConfig(["mock-throw"]);
|
||||
await ensureModels(cfg);
|
||||
|
||||
const result = await runEmbeddedPiAgent({
|
||||
sessionId: "session:test",
|
||||
sessionKey: testSessionKey,
|
||||
sessionFile,
|
||||
workspaceDir,
|
||||
config: cfg,
|
||||
prompt: "transport error",
|
||||
provider: "openai",
|
||||
model: "mock-throw",
|
||||
timeoutMs: 5_000,
|
||||
agentDir,
|
||||
runId: nextRunId("transport-error"),
|
||||
enqueue: immediateEnqueue,
|
||||
});
|
||||
expect(result.payloads?.[0]?.isError).toBe(true);
|
||||
|
||||
const entries = await readSessionEntries(sessionFile);
|
||||
const promptErrorEntry = entries.find(
|
||||
(entry) => entry.type === "custom" && entry.customType === "openclaw:prompt-error",
|
||||
) as { data?: { error?: string } } | undefined;
|
||||
|
||||
expect(promptErrorEntry).toBeTruthy();
|
||||
expect(promptErrorEntry?.data?.error).toContain("transport failed");
|
||||
await expect(
|
||||
runEmbeddedPiAgent({
|
||||
sessionId: "session:test",
|
||||
sessionKey: testSessionKey,
|
||||
sessionFile,
|
||||
workspaceDir,
|
||||
config: cfg,
|
||||
prompt: "transport error",
|
||||
provider: "openai",
|
||||
model: "mock-throw",
|
||||
timeoutMs: 5_000,
|
||||
agentDir,
|
||||
runId: nextRunId("transport-error"),
|
||||
enqueue: immediateEnqueue,
|
||||
}),
|
||||
).rejects.toThrow("transport failed");
|
||||
await expect(fs.stat(sessionFile)).rejects.toBeTruthy();
|
||||
});
|
||||
|
||||
it(
|
||||
|
||||
@@ -20,10 +20,10 @@ vi.mock("./models-config.js", async (importOriginal) => {
|
||||
};
|
||||
});
|
||||
|
||||
let runEmbeddedPiAgent: typeof import("./pi-embedded-runner.js").runEmbeddedPiAgent;
|
||||
let runEmbeddedPiAgent: typeof import("./pi-embedded-runner/run.js").runEmbeddedPiAgent;
|
||||
|
||||
beforeAll(async () => {
|
||||
({ runEmbeddedPiAgent } = await import("./pi-embedded-runner.js"));
|
||||
({ runEmbeddedPiAgent } = await import("./pi-embedded-runner/run.js"));
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
|
||||
@@ -24,7 +24,7 @@ vi.mock("../infra/shell-env.js", async (importOriginal) => {
|
||||
return {
|
||||
...mod,
|
||||
getShellPathFromLoginShell: vi.fn(() => null),
|
||||
resolveShellEnvFallbackTimeoutMs: vi.fn(() => 500),
|
||||
resolveShellEnvFallbackTimeoutMs: vi.fn(() => 50),
|
||||
};
|
||||
});
|
||||
|
||||
@@ -174,10 +174,10 @@ describe("createOpenClawCodingTools safeBins", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("does not leak file existence from sort output flags", async () => {
|
||||
it("blocks sort output/compress bypass attempts in safeBins mode", async () => {
|
||||
await withSafeBinsExecTool(
|
||||
{
|
||||
tmpPrefix: "openclaw-safe-bins-oracle-",
|
||||
tmpPrefix: "openclaw-safe-bins-sort-",
|
||||
safeBins: ["sort"],
|
||||
files: [{ name: "existing.txt", contents: "x\n" }],
|
||||
},
|
||||
@@ -196,42 +196,21 @@ describe("createOpenClawCodingTools safeBins", () => {
|
||||
const existing = await run("sort -o existing.txt");
|
||||
const missing = await run("sort -o missing.txt");
|
||||
expect(existing).toEqual(missing);
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
it("blocks sort output flags from writing files via safeBins", async () => {
|
||||
await withSafeBinsExecTool(
|
||||
{
|
||||
tmpPrefix: "openclaw-safe-bins-sort-",
|
||||
safeBins: ["sort"],
|
||||
},
|
||||
async ({ tmpDir, execTool }) => {
|
||||
const cases = [
|
||||
const outputFlagCases = [
|
||||
{ command: "sort -oblocked-short.txt", target: "blocked-short.txt" },
|
||||
{ command: "sort --output=blocked-long.txt", target: "blocked-long.txt" },
|
||||
] as const;
|
||||
|
||||
for (const [index, testCase] of cases.entries()) {
|
||||
for (const [index, testCase] of outputFlagCases.entries()) {
|
||||
await expect(
|
||||
execTool.execute(`call${index + 1}`, {
|
||||
execTool.execute(`call-output-${index + 1}`, {
|
||||
command: testCase.command,
|
||||
workdir: tmpDir,
|
||||
}),
|
||||
).rejects.toThrow("exec denied: allowlist miss");
|
||||
expect(fs.existsSync(path.join(tmpDir, testCase.target))).toBe(false);
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
it("blocks sort --compress-program from bypassing safeBins", async () => {
|
||||
await withSafeBinsExecTool(
|
||||
{
|
||||
tmpPrefix: "openclaw-safe-bins-sort-compress-",
|
||||
safeBins: ["sort"],
|
||||
},
|
||||
async ({ tmpDir, execTool }) => {
|
||||
await expect(
|
||||
execTool.execute("call1", {
|
||||
command: "sort --compress-program=sh",
|
||||
|
||||
Reference in New Issue
Block a user