mirror of https://github.com/openclaw/openclaw.git
86 lines
3.0 KiB
TypeScript
86 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("normalizes extended-length and UNC windows paths", () => {
|
|
expect(normalizeWindowsPathForComparison("\\\\?\\C:\\Users\\Peter/Repo")).toBe(
|
|
"c:\\users\\peter\\repo",
|
|
);
|
|
expect(normalizeWindowsPathForComparison("\\\\?\\UNC\\Server\\Share\\Folder")).toBe(
|
|
"\\\\server\\share\\folder",
|
|
);
|
|
expect(normalizeWindowsPathForComparison("\\\\?\\unc\\Server\\Share\\Folder")).toBe(
|
|
"\\\\server\\share\\folder",
|
|
);
|
|
});
|
|
});
|
|
|
|
describe("node path error helpers", () => {
|
|
it("recognizes node-style error objects and exact codes", () => {
|
|
const enoent = { code: "ENOENT" };
|
|
|
|
expect(isNodeError(enoent)).toBe(true);
|
|
expect(isNodeError({ message: "nope" })).toBe(false);
|
|
expect(hasNodeErrorCode(enoent, "ENOENT")).toBe(true);
|
|
expect(hasNodeErrorCode(enoent, "EACCES")).toBe(false);
|
|
});
|
|
|
|
it("classifies not-found and symlink-open error codes", () => {
|
|
expect(isNotFoundPathError({ code: "ENOENT" })).toBe(true);
|
|
expect(isNotFoundPathError({ code: "ENOTDIR" })).toBe(true);
|
|
expect(isNotFoundPathError({ code: "EACCES" })).toBe(false);
|
|
expect(isNotFoundPathError({ code: 404 })).toBe(false);
|
|
|
|
expect(isSymlinkOpenError({ code: "ELOOP" })).toBe(true);
|
|
expect(isSymlinkOpenError({ code: "EINVAL" })).toBe(true);
|
|
expect(isSymlinkOpenError({ code: "ENOTSUP" })).toBe(true);
|
|
expect(isSymlinkOpenError({ code: "ENOENT" })).toBe(false);
|
|
expect(isSymlinkOpenError({ code: null })).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe("isPathInside", () => {
|
|
it("accepts identical and nested paths but rejects escapes", () => {
|
|
expect(isPathInside("/workspace/root", "/workspace/root")).toBe(true);
|
|
expect(isPathInside("/workspace/root", "/workspace/root/nested/file.txt")).toBe(true);
|
|
expect(isPathInside("/workspace/root", "/workspace/root/../escape.txt")).toBe(false);
|
|
});
|
|
|
|
it("uses win32 path semantics for windows containment checks", () => {
|
|
setPlatform("win32");
|
|
|
|
expect(isPathInside(String.raw`C:\workspace\root`, String.raw`C:\workspace\root`)).toBe(true);
|
|
expect(
|
|
isPathInside(String.raw`C:\workspace\root`, String.raw`C:\workspace\root\Nested\File.txt`),
|
|
).toBe(true);
|
|
expect(
|
|
isPathInside(String.raw`C:\workspace\root`, String.raw`C:\workspace\root\..\escape.txt`),
|
|
).toBe(false);
|
|
expect(
|
|
isPathInside(String.raw`C:\workspace\root`, String.raw`D:\workspace\root\file.txt`),
|
|
).toBe(false);
|
|
});
|
|
});
|