mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 08:51:36 +00:00
perf(test): consolidate daemon test entrypoints
This commit is contained in:
@@ -1,36 +0,0 @@
|
|||||||
import { describe, expect, it } from "vitest";
|
|
||||||
import { splitArgsPreservingQuotes } from "./arg-split.js";
|
|
||||||
|
|
||||||
describe("splitArgsPreservingQuotes", () => {
|
|
||||||
it("splits on whitespace outside quotes", () => {
|
|
||||||
expect(splitArgsPreservingQuotes('/usr/bin/openclaw gateway start --name "My Bot"')).toEqual([
|
|
||||||
"/usr/bin/openclaw",
|
|
||||||
"gateway",
|
|
||||||
"start",
|
|
||||||
"--name",
|
|
||||||
"My Bot",
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("supports systemd-style backslash escaping", () => {
|
|
||||||
expect(
|
|
||||||
splitArgsPreservingQuotes('openclaw --name "My \\"Bot\\"" --foo bar', {
|
|
||||||
escapeMode: "backslash",
|
|
||||||
}),
|
|
||||||
).toEqual(["openclaw", "--name", 'My "Bot"', "--foo", "bar"]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("supports schtasks-style escaped quotes while preserving other backslashes", () => {
|
|
||||||
expect(
|
|
||||||
splitArgsPreservingQuotes('openclaw --path "C:\\\\Program Files\\\\OpenClaw"', {
|
|
||||||
escapeMode: "backslash-quote-only",
|
|
||||||
}),
|
|
||||||
).toEqual(["openclaw", "--path", "C:\\\\Program Files\\\\OpenClaw"]);
|
|
||||||
|
|
||||||
expect(
|
|
||||||
splitArgsPreservingQuotes('openclaw --label "My \\"Quoted\\" Name"', {
|
|
||||||
escapeMode: "backslash-quote-only",
|
|
||||||
}),
|
|
||||||
).toEqual(["openclaw", "--label", 'My "Quoted" Name']);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
import path from "node:path";
|
|
||||||
import { describe, expect, it } from "vitest";
|
|
||||||
import { resolveGatewayStateDir } from "./paths.js";
|
|
||||||
|
|
||||||
describe("resolveGatewayStateDir", () => {
|
|
||||||
it("uses the default state dir when no overrides are set", () => {
|
|
||||||
const env = { HOME: "/Users/test" };
|
|
||||||
expect(resolveGatewayStateDir(env)).toBe(path.join("/Users/test", ".openclaw"));
|
|
||||||
});
|
|
||||||
|
|
||||||
it("appends the profile suffix when set", () => {
|
|
||||||
const env = { HOME: "/Users/test", OPENCLAW_PROFILE: "rescue" };
|
|
||||||
expect(resolveGatewayStateDir(env)).toBe(path.join("/Users/test", ".openclaw-rescue"));
|
|
||||||
});
|
|
||||||
|
|
||||||
it("treats default profiles as the base state dir", () => {
|
|
||||||
const env = { HOME: "/Users/test", OPENCLAW_PROFILE: "Default" };
|
|
||||||
expect(resolveGatewayStateDir(env)).toBe(path.join("/Users/test", ".openclaw"));
|
|
||||||
});
|
|
||||||
|
|
||||||
it("uses OPENCLAW_STATE_DIR when provided", () => {
|
|
||||||
const env = { HOME: "/Users/test", OPENCLAW_STATE_DIR: "/var/lib/openclaw" };
|
|
||||||
expect(resolveGatewayStateDir(env)).toBe(path.resolve("/var/lib/openclaw"));
|
|
||||||
});
|
|
||||||
|
|
||||||
it("expands ~ in OPENCLAW_STATE_DIR", () => {
|
|
||||||
const env = { HOME: "/Users/test", OPENCLAW_STATE_DIR: "~/openclaw-state" };
|
|
||||||
expect(resolveGatewayStateDir(env)).toBe(path.resolve("/Users/test/openclaw-state"));
|
|
||||||
});
|
|
||||||
|
|
||||||
it("preserves Windows absolute paths without HOME", () => {
|
|
||||||
const env = { OPENCLAW_STATE_DIR: "C:\\State\\openclaw" };
|
|
||||||
expect(resolveGatewayStateDir(env)).toBe("C:\\State\\openclaw");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from "vitest";
|
||||||
|
import { resolveGatewayStateDir } from "./paths.js";
|
||||||
import {
|
import {
|
||||||
buildMinimalServicePath,
|
buildMinimalServicePath,
|
||||||
buildNodeServiceEnvironment,
|
buildNodeServiceEnvironment,
|
||||||
@@ -254,3 +255,35 @@ describe("buildNodeServiceEnvironment", () => {
|
|||||||
expect(env.HOME).toBe("/home/user");
|
expect(env.HOME).toBe("/home/user");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("resolveGatewayStateDir", () => {
|
||||||
|
it("uses the default state dir when no overrides are set", () => {
|
||||||
|
const env = { HOME: "/Users/test" };
|
||||||
|
expect(resolveGatewayStateDir(env)).toBe(path.join("/Users/test", ".openclaw"));
|
||||||
|
});
|
||||||
|
|
||||||
|
it("appends the profile suffix when set", () => {
|
||||||
|
const env = { HOME: "/Users/test", OPENCLAW_PROFILE: "rescue" };
|
||||||
|
expect(resolveGatewayStateDir(env)).toBe(path.join("/Users/test", ".openclaw-rescue"));
|
||||||
|
});
|
||||||
|
|
||||||
|
it("treats default profiles as the base state dir", () => {
|
||||||
|
const env = { HOME: "/Users/test", OPENCLAW_PROFILE: "Default" };
|
||||||
|
expect(resolveGatewayStateDir(env)).toBe(path.join("/Users/test", ".openclaw"));
|
||||||
|
});
|
||||||
|
|
||||||
|
it("uses OPENCLAW_STATE_DIR when provided", () => {
|
||||||
|
const env = { HOME: "/Users/test", OPENCLAW_STATE_DIR: "/var/lib/openclaw" };
|
||||||
|
expect(resolveGatewayStateDir(env)).toBe(path.resolve("/var/lib/openclaw"));
|
||||||
|
});
|
||||||
|
|
||||||
|
it("expands ~ in OPENCLAW_STATE_DIR", () => {
|
||||||
|
const env = { HOME: "/Users/test", OPENCLAW_STATE_DIR: "~/openclaw-state" };
|
||||||
|
expect(resolveGatewayStateDir(env)).toBe(path.resolve("/Users/test/openclaw-state"));
|
||||||
|
});
|
||||||
|
|
||||||
|
it("preserves Windows absolute paths without HOME", () => {
|
||||||
|
const env = { OPENCLAW_STATE_DIR: "C:\\State\\openclaw" };
|
||||||
|
expect(resolveGatewayStateDir(env)).toBe("C:\\State\\openclaw");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
@@ -1,35 +0,0 @@
|
|||||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
||||||
|
|
||||||
const execFileMock = vi.hoisted(() => vi.fn());
|
|
||||||
|
|
||||||
vi.mock("node:child_process", () => ({
|
|
||||||
execFile: execFileMock,
|
|
||||||
}));
|
|
||||||
|
|
||||||
import { isSystemdUserServiceAvailable } from "./systemd.js";
|
|
||||||
|
|
||||||
describe("systemd availability", () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
execFileMock.mockReset();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("returns true when systemctl --user succeeds", async () => {
|
|
||||||
execFileMock.mockImplementation((_cmd, _args, _opts, cb) => {
|
|
||||||
cb(null, "", "");
|
|
||||||
});
|
|
||||||
await expect(isSystemdUserServiceAvailable()).resolves.toBe(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("returns false when systemd user bus is unavailable", async () => {
|
|
||||||
execFileMock.mockImplementation((_cmd, _args, _opts, cb) => {
|
|
||||||
const err = new Error("Failed to connect to bus") as Error & {
|
|
||||||
stderr?: string;
|
|
||||||
code?: number;
|
|
||||||
};
|
|
||||||
err.stderr = "Failed to connect to bus";
|
|
||||||
err.code = 1;
|
|
||||||
cb(err, "", "");
|
|
||||||
});
|
|
||||||
await expect(isSystemdUserServiceAvailable()).resolves.toBe(false);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
import { describe, expect, it } from "vitest";
|
|
||||||
import { parseSystemdExecStart } from "./systemd-unit.js";
|
|
||||||
|
|
||||||
describe("parseSystemdExecStart", () => {
|
|
||||||
it("splits on whitespace outside quotes", () => {
|
|
||||||
const execStart = "/usr/bin/openclaw gateway start --foo bar";
|
|
||||||
expect(parseSystemdExecStart(execStart)).toEqual([
|
|
||||||
"/usr/bin/openclaw",
|
|
||||||
"gateway",
|
|
||||||
"start",
|
|
||||||
"--foo",
|
|
||||||
"bar",
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("preserves quoted arguments", () => {
|
|
||||||
const execStart = '/usr/bin/openclaw gateway start --name "My Bot"';
|
|
||||||
expect(parseSystemdExecStart(execStart)).toEqual([
|
|
||||||
"/usr/bin/openclaw",
|
|
||||||
"gateway",
|
|
||||||
"start",
|
|
||||||
"--name",
|
|
||||||
"My Bot",
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("parses path arguments", () => {
|
|
||||||
const execStart = "/usr/bin/openclaw gateway start --path /tmp/openclaw";
|
|
||||||
expect(parseSystemdExecStart(execStart)).toEqual([
|
|
||||||
"/usr/bin/openclaw",
|
|
||||||
"gateway",
|
|
||||||
"start",
|
|
||||||
"--path",
|
|
||||||
"/tmp/openclaw",
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,5 +1,44 @@
|
|||||||
import { describe, expect, it } from "vitest";
|
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||||
import { parseSystemdShow, resolveSystemdUserUnitPath } from "./systemd.js";
|
|
||||||
|
const execFileMock = vi.hoisted(() => vi.fn());
|
||||||
|
|
||||||
|
vi.mock("node:child_process", () => ({
|
||||||
|
execFile: execFileMock,
|
||||||
|
}));
|
||||||
|
|
||||||
|
import { splitArgsPreservingQuotes } from "./arg-split.js";
|
||||||
|
import { parseSystemdExecStart } from "./systemd-unit.js";
|
||||||
|
import {
|
||||||
|
isSystemdUserServiceAvailable,
|
||||||
|
parseSystemdShow,
|
||||||
|
resolveSystemdUserUnitPath,
|
||||||
|
} from "./systemd.js";
|
||||||
|
|
||||||
|
describe("systemd availability", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
execFileMock.mockReset();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("returns true when systemctl --user succeeds", async () => {
|
||||||
|
execFileMock.mockImplementation((_cmd, _args, _opts, cb) => {
|
||||||
|
cb(null, "", "");
|
||||||
|
});
|
||||||
|
await expect(isSystemdUserServiceAvailable()).resolves.toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("returns false when systemd user bus is unavailable", async () => {
|
||||||
|
execFileMock.mockImplementation((_cmd, _args, _opts, cb) => {
|
||||||
|
const err = new Error("Failed to connect to bus") as Error & {
|
||||||
|
stderr?: string;
|
||||||
|
code?: number;
|
||||||
|
};
|
||||||
|
err.stderr = "Failed to connect to bus";
|
||||||
|
err.code = 1;
|
||||||
|
cb(err, "", "");
|
||||||
|
});
|
||||||
|
await expect(isSystemdUserServiceAvailable()).resolves.toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe("systemd runtime parsing", () => {
|
describe("systemd runtime parsing", () => {
|
||||||
it("parses active state details", () => {
|
it("parses active state details", () => {
|
||||||
@@ -93,3 +132,72 @@ describe("resolveSystemdUserUnitPath", () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("splitArgsPreservingQuotes", () => {
|
||||||
|
it("splits on whitespace outside quotes", () => {
|
||||||
|
expect(splitArgsPreservingQuotes('/usr/bin/openclaw gateway start --name "My Bot"')).toEqual([
|
||||||
|
"/usr/bin/openclaw",
|
||||||
|
"gateway",
|
||||||
|
"start",
|
||||||
|
"--name",
|
||||||
|
"My Bot",
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("supports systemd-style backslash escaping", () => {
|
||||||
|
expect(
|
||||||
|
splitArgsPreservingQuotes('openclaw --name "My \\"Bot\\"" --foo bar', {
|
||||||
|
escapeMode: "backslash",
|
||||||
|
}),
|
||||||
|
).toEqual(["openclaw", "--name", 'My "Bot"', "--foo", "bar"]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("supports schtasks-style escaped quotes while preserving other backslashes", () => {
|
||||||
|
expect(
|
||||||
|
splitArgsPreservingQuotes('openclaw --path "C:\\\\Program Files\\\\OpenClaw"', {
|
||||||
|
escapeMode: "backslash-quote-only",
|
||||||
|
}),
|
||||||
|
).toEqual(["openclaw", "--path", "C:\\\\Program Files\\\\OpenClaw"]);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
splitArgsPreservingQuotes('openclaw --label "My \\"Quoted\\" Name"', {
|
||||||
|
escapeMode: "backslash-quote-only",
|
||||||
|
}),
|
||||||
|
).toEqual(["openclaw", "--label", 'My "Quoted" Name']);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("parseSystemdExecStart", () => {
|
||||||
|
it("splits on whitespace outside quotes", () => {
|
||||||
|
const execStart = "/usr/bin/openclaw gateway start --foo bar";
|
||||||
|
expect(parseSystemdExecStart(execStart)).toEqual([
|
||||||
|
"/usr/bin/openclaw",
|
||||||
|
"gateway",
|
||||||
|
"start",
|
||||||
|
"--foo",
|
||||||
|
"bar",
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("preserves quoted arguments", () => {
|
||||||
|
const execStart = '/usr/bin/openclaw gateway start --name "My Bot"';
|
||||||
|
expect(parseSystemdExecStart(execStart)).toEqual([
|
||||||
|
"/usr/bin/openclaw",
|
||||||
|
"gateway",
|
||||||
|
"start",
|
||||||
|
"--name",
|
||||||
|
"My Bot",
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("parses path arguments", () => {
|
||||||
|
const execStart = "/usr/bin/openclaw gateway start --path /tmp/openclaw";
|
||||||
|
expect(parseSystemdExecStart(execStart)).toEqual([
|
||||||
|
"/usr/bin/openclaw",
|
||||||
|
"gateway",
|
||||||
|
"start",
|
||||||
|
"--path",
|
||||||
|
"/tmp/openclaw",
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user