openclaw/src/infra/path-guards.test.ts

93 lines
3.0 KiB
TypeScript

import { afterEach, describe, expect, it } from "vitest";
import {
hasNodeErrorCode,
isNodeError,
isNotFoundPathError,
isPathInside,
isSymlinkOpenError,
normalizeWindowsPathForComparison,
} from "./path-guards.js";
const originalPlatformDescriptor = Object.getOwnPropertyDescriptor(process, "platform");
function setPlatform(platform: NodeJS.Platform): void {
Object.defineProperty(process, "platform", {
value: platform,
configurable: true,
});
}
afterEach(() => {
if (originalPlatformDescriptor) {
Object.defineProperty(process, "platform", originalPlatformDescriptor);
}
});
describe("normalizeWindowsPathForComparison", () => {
it.each([
["\\\\?\\C:\\Users\\Peter/Repo", "c:\\users\\peter\\repo"],
["\\\\?\\UNC\\Server\\Share\\Folder", "\\\\server\\share\\folder"],
["\\\\?\\unc\\Server\\Share\\Folder", "\\\\server\\share\\folder"],
])("normalizes windows path %s", (input, expected) => {
expect(normalizeWindowsPathForComparison(input)).toBe(expected);
});
});
describe("node path error helpers", () => {
it.each([
[{ code: "ENOENT" }, true],
[{ message: "nope" }, false],
])("detects node-style error %j", (value, expected) => {
expect(isNodeError(value)).toBe(expected);
});
it.each([
[{ code: "ENOENT" }, "ENOENT", true],
[{ code: "ENOENT" }, "EACCES", false],
])("matches node error code for %j", (value, code, expected) => {
expect(hasNodeErrorCode(value, code)).toBe(expected);
});
it.each([
[{ code: "ENOENT" }, true],
[{ code: "ENOTDIR" }, true],
[{ code: "EACCES" }, false],
[{ code: 404 }, false],
])("classifies not-found path error for %j", (value, expected) => {
expect(isNotFoundPathError(value)).toBe(expected);
});
it.each([
[{ code: "ELOOP" }, true],
[{ code: "EINVAL" }, true],
[{ code: "ENOTSUP" }, true],
[{ code: "ENOENT" }, false],
[{ code: null }, false],
])("classifies symlink-open error for %j", (value, expected) => {
expect(isSymlinkOpenError(value)).toBe(expected);
});
});
describe("isPathInside", () => {
it.each([
["/workspace/root", "/workspace/root", true],
["/workspace/root", "/workspace/root/nested/file.txt", true],
["/workspace/root", "/workspace/root/../escape.txt", false],
])("checks posix containment %s -> %s", (basePath, targetPath, expected) => {
expect(isPathInside(basePath, targetPath)).toBe(expected);
});
it("uses win32 path semantics for windows containment checks", () => {
setPlatform("win32");
for (const [basePath, targetPath, expected] of [
[String.raw`C:\workspace\root`, String.raw`C:\workspace\root`, true],
[String.raw`C:\workspace\root`, String.raw`C:\workspace\root\Nested\File.txt`, true],
[String.raw`C:\workspace\root`, String.raw`C:\workspace\root\..\escape.txt`, false],
[String.raw`C:\workspace\root`, String.raw`D:\workspace\root\file.txt`, false],
] as const) {
expect(isPathInside(basePath, targetPath)).toBe(expected);
}
});
});