mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-18 07:37:29 +00:00
refactor(daemon): dedupe systemd restart test scaffolding
This commit is contained in:
@@ -17,6 +17,38 @@ import {
|
||||
stopSystemdService,
|
||||
} from "./systemd.js";
|
||||
|
||||
type ExecFileError = Error & {
|
||||
stderr?: string;
|
||||
code?: string | number;
|
||||
};
|
||||
|
||||
const createExecFileError = (
|
||||
message: string,
|
||||
options: { stderr?: string; code?: string | number } = {},
|
||||
): ExecFileError => {
|
||||
const err = new Error(message) as ExecFileError;
|
||||
err.code = options.code ?? 1;
|
||||
if (options.stderr) {
|
||||
err.stderr = options.stderr;
|
||||
}
|
||||
return err;
|
||||
};
|
||||
|
||||
const createWritableStreamMock = () => {
|
||||
const write = vi.fn();
|
||||
return {
|
||||
write,
|
||||
stdout: { write } as unknown as NodeJS.WritableStream,
|
||||
};
|
||||
};
|
||||
|
||||
const assertRestartSuccess = async (env: NodeJS.ProcessEnv) => {
|
||||
const { write, stdout } = createWritableStreamMock();
|
||||
await restartSystemdService({ stdout, env });
|
||||
expect(write).toHaveBeenCalledTimes(1);
|
||||
expect(String(write.mock.calls[0]?.[0])).toContain("Restarted systemd service");
|
||||
};
|
||||
|
||||
describe("systemd availability", () => {
|
||||
beforeEach(() => {
|
||||
execFileMock.mockReset();
|
||||
@@ -46,15 +78,10 @@ describe("systemd availability", () => {
|
||||
execFileMock
|
||||
.mockImplementationOnce((_cmd, args, _opts, cb) => {
|
||||
expect(args).toEqual(["--user", "status"]);
|
||||
const err = new Error(
|
||||
"Failed to connect to user scope bus via local transport",
|
||||
) as Error & {
|
||||
stderr?: string;
|
||||
code?: number;
|
||||
};
|
||||
err.stderr =
|
||||
"Failed to connect to user scope bus via local transport: $DBUS_SESSION_BUS_ADDRESS and $XDG_RUNTIME_DIR not defined";
|
||||
err.code = 1;
|
||||
const err = createExecFileError("Failed to connect to user scope bus via local transport", {
|
||||
stderr:
|
||||
"Failed to connect to user scope bus via local transport: $DBUS_SESSION_BUS_ADDRESS and $XDG_RUNTIME_DIR not defined",
|
||||
});
|
||||
cb(err, "", "");
|
||||
})
|
||||
.mockImplementationOnce((_cmd, args, _opts, cb) => {
|
||||
@@ -271,6 +298,10 @@ describe("parseSystemdExecStart", () => {
|
||||
});
|
||||
|
||||
describe("systemd service control", () => {
|
||||
const assertMachineRestartArgs = (args: string[]) => {
|
||||
expect(args).toEqual(["--machine", "debian@", "--user", "restart", "openclaw-gateway.service"]);
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
execFileMock.mockReset();
|
||||
});
|
||||
@@ -298,13 +329,7 @@ describe("systemd service control", () => {
|
||||
expect(args).toEqual(["--user", "restart", "openclaw-gateway-work.service"]);
|
||||
cb(null, "", "");
|
||||
});
|
||||
const write = vi.fn();
|
||||
const stdout = { write } as unknown as NodeJS.WritableStream;
|
||||
|
||||
await restartSystemdService({ stdout, env: { OPENCLAW_PROFILE: "work" } });
|
||||
|
||||
expect(write).toHaveBeenCalledTimes(1);
|
||||
expect(String(write.mock.calls[0]?.[0])).toContain("Restarted systemd service");
|
||||
await assertRestartSuccess({ OPENCLAW_PROFILE: "work" });
|
||||
});
|
||||
|
||||
it("surfaces stop failures with systemctl detail", async () => {
|
||||
@@ -331,22 +356,10 @@ describe("systemd service control", () => {
|
||||
cb(null, "", "");
|
||||
})
|
||||
.mockImplementationOnce((_cmd, args, _opts, cb) => {
|
||||
expect(args).toEqual([
|
||||
"--machine",
|
||||
"debian@",
|
||||
"--user",
|
||||
"restart",
|
||||
"openclaw-gateway.service",
|
||||
]);
|
||||
assertMachineRestartArgs(args);
|
||||
cb(null, "", "");
|
||||
});
|
||||
const write = vi.fn();
|
||||
const stdout = { write } as unknown as NodeJS.WritableStream;
|
||||
|
||||
await restartSystemdService({ stdout, env: { SUDO_USER: "debian" } });
|
||||
|
||||
expect(write).toHaveBeenCalledTimes(1);
|
||||
expect(String(write.mock.calls[0]?.[0])).toContain("Restarted systemd service");
|
||||
await assertRestartSuccess({ SUDO_USER: "debian" });
|
||||
});
|
||||
|
||||
it("keeps direct --user scope when SUDO_USER is root", async () => {
|
||||
@@ -359,26 +372,17 @@ describe("systemd service control", () => {
|
||||
expect(args).toEqual(["--user", "restart", "openclaw-gateway.service"]);
|
||||
cb(null, "", "");
|
||||
});
|
||||
const write = vi.fn();
|
||||
const stdout = { write } as unknown as NodeJS.WritableStream;
|
||||
|
||||
await restartSystemdService({ stdout, env: { SUDO_USER: "root", USER: "root" } });
|
||||
|
||||
expect(write).toHaveBeenCalledTimes(1);
|
||||
expect(String(write.mock.calls[0]?.[0])).toContain("Restarted systemd service");
|
||||
await assertRestartSuccess({ SUDO_USER: "root", USER: "root" });
|
||||
});
|
||||
|
||||
it("falls back to machine user scope for restart when user bus env is missing", async () => {
|
||||
execFileMock
|
||||
.mockImplementationOnce((_cmd, args, _opts, cb) => {
|
||||
expect(args).toEqual(["--user", "status"]);
|
||||
const err = new Error("Failed to connect to user scope bus") as Error & {
|
||||
stderr?: string;
|
||||
code?: number;
|
||||
};
|
||||
err.stderr =
|
||||
"Failed to connect to user scope bus via local transport: $DBUS_SESSION_BUS_ADDRESS and $XDG_RUNTIME_DIR not defined";
|
||||
err.code = 1;
|
||||
const err = createExecFileError("Failed to connect to user scope bus", {
|
||||
stderr:
|
||||
"Failed to connect to user scope bus via local transport: $DBUS_SESSION_BUS_ADDRESS and $XDG_RUNTIME_DIR not defined",
|
||||
});
|
||||
cb(err, "", "");
|
||||
})
|
||||
.mockImplementationOnce((_cmd, args, _opts, cb) => {
|
||||
@@ -387,30 +391,15 @@ describe("systemd service control", () => {
|
||||
})
|
||||
.mockImplementationOnce((_cmd, args, _opts, cb) => {
|
||||
expect(args).toEqual(["--user", "restart", "openclaw-gateway.service"]);
|
||||
const err = new Error("Failed to connect to user scope bus") as Error & {
|
||||
stderr?: string;
|
||||
code?: number;
|
||||
};
|
||||
err.stderr = "Failed to connect to user scope bus";
|
||||
err.code = 1;
|
||||
const err = createExecFileError("Failed to connect to user scope bus", {
|
||||
stderr: "Failed to connect to user scope bus",
|
||||
});
|
||||
cb(err, "", "");
|
||||
})
|
||||
.mockImplementationOnce((_cmd, args, _opts, cb) => {
|
||||
expect(args).toEqual([
|
||||
"--machine",
|
||||
"debian@",
|
||||
"--user",
|
||||
"restart",
|
||||
"openclaw-gateway.service",
|
||||
]);
|
||||
assertMachineRestartArgs(args);
|
||||
cb(null, "", "");
|
||||
});
|
||||
const write = vi.fn();
|
||||
const stdout = { write } as unknown as NodeJS.WritableStream;
|
||||
|
||||
await restartSystemdService({ stdout, env: { USER: "debian" } });
|
||||
|
||||
expect(write).toHaveBeenCalledTimes(1);
|
||||
expect(String(write.mock.calls[0]?.[0])).toContain("Restarted systemd service");
|
||||
await assertRestartSuccess({ USER: "debian" });
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user