mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-22 15:31:07 +00:00
106 lines
3.6 KiB
TypeScript
106 lines
3.6 KiB
TypeScript
import path from "node:path";
|
|
import { describe, expect, it } from "vitest";
|
|
import {
|
|
buildSandboxFsMounts,
|
|
parseSandboxBindMount,
|
|
resolveSandboxFsPathWithMounts,
|
|
} from "./fs-paths.js";
|
|
import { createSandboxTestContext } from "./test-fixtures.js";
|
|
import type { SandboxContext } from "./types.js";
|
|
|
|
function createSandbox(overrides?: Partial<SandboxContext>): SandboxContext {
|
|
return createSandboxTestContext({ overrides });
|
|
}
|
|
|
|
describe("parseSandboxBindMount", () => {
|
|
it("parses bind mode and writeability", () => {
|
|
expect(parseSandboxBindMount("/tmp/a:/workspace-a:ro")).toEqual({
|
|
hostRoot: path.resolve("/tmp/a"),
|
|
containerRoot: "/workspace-a",
|
|
writable: false,
|
|
});
|
|
expect(parseSandboxBindMount("/tmp/b:/workspace-b:rw")).toEqual({
|
|
hostRoot: path.resolve("/tmp/b"),
|
|
containerRoot: "/workspace-b",
|
|
writable: true,
|
|
});
|
|
});
|
|
|
|
it("parses Windows drive-letter host paths", () => {
|
|
expect(parseSandboxBindMount("C:\\Users\\kai\\workspace:/workspace:ro")).toEqual({
|
|
hostRoot: path.resolve("C:\\Users\\kai\\workspace"),
|
|
containerRoot: "/workspace",
|
|
writable: false,
|
|
});
|
|
expect(parseSandboxBindMount("D:/data:/workspace-data:rw")).toEqual({
|
|
hostRoot: path.resolve("D:/data"),
|
|
containerRoot: "/workspace-data",
|
|
writable: true,
|
|
});
|
|
});
|
|
|
|
it("parses UNC-style host paths", () => {
|
|
expect(parseSandboxBindMount("//server/share:/workspace:ro")).toEqual({
|
|
hostRoot: path.resolve("//server/share"),
|
|
containerRoot: "/workspace",
|
|
writable: false,
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("resolveSandboxFsPathWithMounts", () => {
|
|
it("maps mounted container absolute paths to host paths", () => {
|
|
const sandbox = createSandbox({
|
|
docker: {
|
|
...createSandbox().docker,
|
|
binds: ["/tmp/workspace-two:/workspace-two:ro"],
|
|
},
|
|
});
|
|
const mounts = buildSandboxFsMounts(sandbox);
|
|
const resolved = resolveSandboxFsPathWithMounts({
|
|
filePath: "/workspace-two/docs/AGENTS.md",
|
|
cwd: sandbox.workspaceDir,
|
|
defaultWorkspaceRoot: sandbox.workspaceDir,
|
|
defaultContainerRoot: sandbox.containerWorkdir,
|
|
mounts,
|
|
});
|
|
|
|
expect(resolved.hostPath).toBe(
|
|
path.join(path.resolve("/tmp/workspace-two"), "docs", "AGENTS.md"),
|
|
);
|
|
expect(resolved.containerPath).toBe("/workspace-two/docs/AGENTS.md");
|
|
expect(resolved.relativePath).toBe("/workspace-two/docs/AGENTS.md");
|
|
expect(resolved.writable).toBe(false);
|
|
});
|
|
|
|
it("keeps workspace-relative display paths for default workspace files", () => {
|
|
const sandbox = createSandbox();
|
|
const mounts = buildSandboxFsMounts(sandbox);
|
|
const resolved = resolveSandboxFsPathWithMounts({
|
|
filePath: "src/index.ts",
|
|
cwd: sandbox.workspaceDir,
|
|
defaultWorkspaceRoot: sandbox.workspaceDir,
|
|
defaultContainerRoot: sandbox.containerWorkdir,
|
|
mounts,
|
|
});
|
|
expect(resolved.hostPath).toBe(path.join(path.resolve("/tmp/workspace"), "src", "index.ts"));
|
|
expect(resolved.containerPath).toBe("/workspace/src/index.ts");
|
|
expect(resolved.relativePath).toBe("src/index.ts");
|
|
expect(resolved.writable).toBe(true);
|
|
});
|
|
|
|
it("preserves legacy sandbox-root error for outside paths", () => {
|
|
const sandbox = createSandbox();
|
|
const mounts = buildSandboxFsMounts(sandbox);
|
|
expect(() =>
|
|
resolveSandboxFsPathWithMounts({
|
|
filePath: "/etc/passwd",
|
|
cwd: sandbox.workspaceDir,
|
|
defaultWorkspaceRoot: sandbox.workspaceDir,
|
|
defaultContainerRoot: sandbox.containerWorkdir,
|
|
mounts,
|
|
}),
|
|
).toThrow(/Path escapes sandbox root/);
|
|
});
|
|
});
|