mirror of https://github.com/openclaw/openclaw.git
test: add direct infra helper coverage
This commit is contained in:
parent
3e77263b4c
commit
a423b1d936
|
|
@ -0,0 +1,34 @@
|
|||
import { describe, expect, it } from "vitest";
|
||||
import { isGatewayArgv, parseProcCmdline } from "./gateway-process-argv.js";
|
||||
|
||||
describe("parseProcCmdline", () => {
|
||||
it("splits null-delimited argv and trims empty entries", () => {
|
||||
expect(parseProcCmdline(" node \0 gateway \0\0 --port \0 18789 \0")).toEqual([
|
||||
"node",
|
||||
"gateway",
|
||||
"--port",
|
||||
"18789",
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("isGatewayArgv", () => {
|
||||
it("requires a gateway token", () => {
|
||||
expect(isGatewayArgv(["node", "dist/index.js", "--port", "18789"])).toBe(false);
|
||||
});
|
||||
|
||||
it("matches known entrypoints across slash and case variants", () => {
|
||||
expect(isGatewayArgv(["NODE", "C:\\OpenClaw\\DIST\\ENTRY.JS", "gateway"])).toBe(true);
|
||||
expect(isGatewayArgv(["bun", "/srv/openclaw/scripts/run-node.mjs", "gateway"])).toBe(true);
|
||||
});
|
||||
|
||||
it("matches the openclaw executable but gates the gateway binary behind the opt-in flag", () => {
|
||||
expect(isGatewayArgv(["C:\\bin\\openclaw.cmd", "gateway"])).toBe(true);
|
||||
expect(isGatewayArgv(["/usr/local/bin/openclaw-gateway", "gateway"])).toBe(false);
|
||||
expect(
|
||||
isGatewayArgv(["/usr/local/bin/openclaw-gateway", "gateway"], {
|
||||
allowGatewayBinary: true,
|
||||
}),
|
||||
).toBe(true);
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
import fs from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { withTempDir } from "../test-helpers/temp-dir.js";
|
||||
import { readPackageName, readPackageVersion } from "./package-json.js";
|
||||
|
||||
describe("package-json helpers", () => {
|
||||
it("reads package version and trims package name", async () => {
|
||||
await withTempDir({ prefix: "openclaw-package-json-" }, async (root) => {
|
||||
await fs.writeFile(
|
||||
path.join(root, "package.json"),
|
||||
JSON.stringify({ version: "1.2.3", name: " @openclaw/demo " }),
|
||||
"utf8",
|
||||
);
|
||||
|
||||
await expect(readPackageVersion(root)).resolves.toBe("1.2.3");
|
||||
await expect(readPackageName(root)).resolves.toBe("@openclaw/demo");
|
||||
});
|
||||
});
|
||||
|
||||
it("returns null for missing or invalid package.json data", async () => {
|
||||
await withTempDir({ prefix: "openclaw-package-json-" }, async (root) => {
|
||||
await expect(readPackageVersion(root)).resolves.toBeNull();
|
||||
await expect(readPackageName(root)).resolves.toBeNull();
|
||||
|
||||
await fs.writeFile(path.join(root, "package.json"), "{", "utf8");
|
||||
await expect(readPackageVersion(root)).resolves.toBeNull();
|
||||
await expect(readPackageName(root)).resolves.toBeNull();
|
||||
|
||||
await fs.writeFile(
|
||||
path.join(root, "package.json"),
|
||||
JSON.stringify({ version: 123, name: " " }),
|
||||
"utf8",
|
||||
);
|
||||
await expect(readPackageVersion(root)).resolves.toBeNull();
|
||||
await expect(readPackageName(root)).resolves.toBeNull();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
import { describe, expect, it } from "vitest";
|
||||
import {
|
||||
hasNodeErrorCode,
|
||||
isNodeError,
|
||||
isNotFoundPathError,
|
||||
isPathInside,
|
||||
isSymlinkOpenError,
|
||||
normalizeWindowsPathForComparison,
|
||||
} from "./path-guards.js";
|
||||
|
||||
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",
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
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(isSymlinkOpenError({ code: "ELOOP" })).toBe(true);
|
||||
expect(isSymlinkOpenError({ code: "EINVAL" })).toBe(true);
|
||||
expect(isSymlinkOpenError({ code: "ENOTSUP" })).toBe(true);
|
||||
expect(isSymlinkOpenError({ code: "ENOENT" })).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);
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
import { describe, expect, it } from "vitest";
|
||||
import { isBlockedObjectKey } from "./prototype-keys.js";
|
||||
|
||||
describe("isBlockedObjectKey", () => {
|
||||
it("blocks prototype-pollution keys and allows ordinary keys", () => {
|
||||
for (const key of ["__proto__", "prototype", "constructor"]) {
|
||||
expect(isBlockedObjectKey(key)).toBe(true);
|
||||
}
|
||||
|
||||
for (const key of ["toString", "value", "constructorName"]) {
|
||||
expect(isBlockedObjectKey(key)).toBe(false);
|
||||
}
|
||||
});
|
||||
});
|
||||
Loading…
Reference in New Issue