Files
openclaw/src/infra/exec-host.test.ts
2026-03-13 20:12:04 +00:00

110 lines
3.3 KiB
TypeScript

import { beforeEach, describe, expect, it, vi } from "vitest";
const requestJsonlSocketMock = vi.hoisted(() => vi.fn());
vi.mock("./jsonl-socket.js", () => ({
requestJsonlSocket: (...args: unknown[]) => requestJsonlSocketMock(...args),
}));
import { requestExecHostViaSocket } from "./exec-host.js";
describe("requestExecHostViaSocket", () => {
beforeEach(() => {
requestJsonlSocketMock.mockReset();
});
it("returns null when socket credentials are missing", async () => {
await expect(
requestExecHostViaSocket({
socketPath: "",
token: "secret",
request: { command: ["echo", "hi"] },
}),
).resolves.toBeNull();
await expect(
requestExecHostViaSocket({
socketPath: "/tmp/socket",
token: "",
request: { command: ["echo", "hi"] },
}),
).resolves.toBeNull();
expect(requestJsonlSocketMock).not.toHaveBeenCalled();
});
it("builds an exec payload and forwards the default timeout", async () => {
requestJsonlSocketMock.mockResolvedValueOnce({ ok: true, payload: { success: true } });
await expect(
requestExecHostViaSocket({
socketPath: "/tmp/socket",
token: "secret",
request: {
command: ["echo", "hi"],
cwd: "/tmp",
},
}),
).resolves.toEqual({ ok: true, payload: { success: true } });
const call = requestJsonlSocketMock.mock.calls[0]?.[0] as
| {
socketPath: string;
payload: string;
timeoutMs: number;
accept: (msg: unknown) => unknown;
}
| undefined;
if (!call) {
throw new Error("expected requestJsonlSocket call");
}
expect(call.socketPath).toBe("/tmp/socket");
expect(call.timeoutMs).toBe(20_000);
const payload = JSON.parse(call.payload) as {
type: string;
id: string;
nonce: string;
ts: number;
hmac: string;
requestJson: string;
};
expect(payload.type).toBe("exec");
expect(payload.id).toMatch(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i);
expect(payload.nonce).toMatch(/^[0-9a-f]{32}$/);
expect(typeof payload.ts).toBe("number");
expect(payload.hmac).toMatch(/^[0-9a-f]{64}$/);
expect(JSON.parse(payload.requestJson)).toEqual({
command: ["echo", "hi"],
cwd: "/tmp",
});
});
it("accepts only exec response messages and maps malformed matches to null", async () => {
requestJsonlSocketMock.mockImplementationOnce(async ({ accept }) => {
expect(accept({ type: "ignore" })).toBeUndefined();
expect(accept({ type: "exec-res", ok: true, payload: { success: true } })).toEqual({
ok: true,
payload: { success: true },
});
expect(accept({ type: "exec-res", ok: false, error: { code: "DENIED" } })).toEqual({
ok: false,
error: { code: "DENIED" },
});
expect(accept({ type: "exec-res", ok: true })).toBeNull();
return null;
});
await expect(
requestExecHostViaSocket({
socketPath: "/tmp/socket",
token: "secret",
timeoutMs: 123,
request: { command: ["echo", "hi"] },
}),
).resolves.toBeNull();
expect(
(requestJsonlSocketMock.mock.calls[0]?.[0] as { timeoutMs?: number } | undefined)?.timeoutMs,
).toBe(123);
});
});