mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-21 15:01:03 +00:00
110 lines
3.3 KiB
TypeScript
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);
|
|
});
|
|
});
|