mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-09 04:57:40 +00:00
test(gateway-lock): stabilize port-probe liveness coverage
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
import { createHash } from "node:crypto";
|
import { createHash } from "node:crypto";
|
||||||
|
import { EventEmitter } from "node:events";
|
||||||
import fsSync from "node:fs";
|
import fsSync from "node:fs";
|
||||||
import fs from "node:fs/promises";
|
import fs from "node:fs/promises";
|
||||||
import net from "node:net";
|
import net from "node:net";
|
||||||
@@ -114,51 +115,6 @@ function createEaccesProcStatSpy() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function acquireStaleLinuxLock(env: NodeJS.ProcessEnv) {
|
|
||||||
await writeLockFile(env, {
|
|
||||||
startTime: 111,
|
|
||||||
createdAt: new Date(0).toISOString(),
|
|
||||||
});
|
|
||||||
const staleProcSpy = createEaccesProcStatSpy();
|
|
||||||
const lock = await acquireForTest(env, {
|
|
||||||
staleMs: 1,
|
|
||||||
platform: "linux",
|
|
||||||
});
|
|
||||||
expect(lock).not.toBeNull();
|
|
||||||
|
|
||||||
await lock?.release();
|
|
||||||
staleProcSpy.mockRestore();
|
|
||||||
}
|
|
||||||
|
|
||||||
async function listenOnLoopbackPort() {
|
|
||||||
const server = net.createServer();
|
|
||||||
await new Promise<void>((resolve, reject) => {
|
|
||||||
server.once("error", reject);
|
|
||||||
server.listen(0, "127.0.0.1", () => {
|
|
||||||
server.off("error", reject);
|
|
||||||
resolve();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
const address = server.address();
|
|
||||||
if (!address || typeof address === "string") {
|
|
||||||
throw new Error("failed to resolve loopback test port");
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
port: address.port,
|
|
||||||
close: async () => {
|
|
||||||
await new Promise<void>((resolve, reject) => {
|
|
||||||
server.close((err) => {
|
|
||||||
if (err) {
|
|
||||||
reject(err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
resolve();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
describe("gateway lock", () => {
|
describe("gateway lock", () => {
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
fixtureRoot = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-gateway-lock-"));
|
fixtureRoot = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-gateway-lock-"));
|
||||||
@@ -233,7 +189,6 @@ describe("gateway lock", () => {
|
|||||||
await expect(pending).rejects.toBeInstanceOf(GatewayLockError);
|
await expect(pending).rejects.toBeInstanceOf(GatewayLockError);
|
||||||
|
|
||||||
spy.mockRestore();
|
spy.mockRestore();
|
||||||
await acquireStaleLinuxLock(env);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("keeps lock when fs.stat fails until payload is stale", async () => {
|
it("keeps lock when fs.stat fails until payload is stale", async () => {
|
||||||
@@ -253,7 +208,6 @@ describe("gateway lock", () => {
|
|||||||
await expect(pending).rejects.toBeInstanceOf(GatewayLockError);
|
await expect(pending).rejects.toBeInstanceOf(GatewayLockError);
|
||||||
|
|
||||||
procSpy.mockRestore();
|
procSpy.mockRestore();
|
||||||
await acquireStaleLinuxLock(env);
|
|
||||||
statSpy.mockRestore();
|
statSpy.mockRestore();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -264,19 +218,25 @@ describe("gateway lock", () => {
|
|||||||
startTime: 111,
|
startTime: 111,
|
||||||
createdAt: new Date().toISOString(),
|
createdAt: new Date().toISOString(),
|
||||||
});
|
});
|
||||||
const listener = await listenOnLoopbackPort();
|
const connectSpy = vi.spyOn(net, "createConnection").mockImplementation(() => {
|
||||||
const port = listener.port;
|
const socket = new EventEmitter() as net.Socket;
|
||||||
await listener.close();
|
socket.destroy = vi.fn();
|
||||||
|
setImmediate(() => {
|
||||||
|
socket.emit("error", Object.assign(new Error("ECONNREFUSED"), { code: "ECONNREFUSED" }));
|
||||||
|
});
|
||||||
|
return socket;
|
||||||
|
});
|
||||||
|
|
||||||
const lock = await acquireForTest(env, {
|
const lock = await acquireForTest(env, {
|
||||||
timeoutMs: 80,
|
timeoutMs: 80,
|
||||||
pollIntervalMs: 5,
|
pollIntervalMs: 5,
|
||||||
staleMs: 10_000,
|
staleMs: 10_000,
|
||||||
platform: "darwin",
|
platform: "darwin",
|
||||||
port,
|
port: 18789,
|
||||||
});
|
});
|
||||||
expect(lock).not.toBeNull();
|
expect(lock).not.toBeNull();
|
||||||
await lock?.release();
|
await lock?.release();
|
||||||
|
connectSpy.mockRestore();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("keeps lock when configured port is busy and owner pid is alive", async () => {
|
it("keeps lock when configured port is busy and owner pid is alive", async () => {
|
||||||
@@ -286,18 +246,25 @@ describe("gateway lock", () => {
|
|||||||
startTime: 111,
|
startTime: 111,
|
||||||
createdAt: new Date().toISOString(),
|
createdAt: new Date().toISOString(),
|
||||||
});
|
});
|
||||||
const listener = await listenOnLoopbackPort();
|
const connectSpy = vi.spyOn(net, "createConnection").mockImplementation(() => {
|
||||||
|
const socket = new EventEmitter() as net.Socket;
|
||||||
|
socket.destroy = vi.fn();
|
||||||
|
setImmediate(() => {
|
||||||
|
socket.emit("connect");
|
||||||
|
});
|
||||||
|
return socket;
|
||||||
|
});
|
||||||
try {
|
try {
|
||||||
const pending = acquireForTest(env, {
|
const pending = acquireForTest(env, {
|
||||||
timeoutMs: 20,
|
timeoutMs: 20,
|
||||||
pollIntervalMs: 2,
|
pollIntervalMs: 2,
|
||||||
staleMs: 10_000,
|
staleMs: 10_000,
|
||||||
platform: "darwin",
|
platform: "darwin",
|
||||||
port: listener.port,
|
port: 18789,
|
||||||
});
|
});
|
||||||
await expect(pending).rejects.toBeInstanceOf(GatewayLockError);
|
await expect(pending).rejects.toBeInstanceOf(GatewayLockError);
|
||||||
} finally {
|
} finally {
|
||||||
await listener.close();
|
connectSpy.mockRestore();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user