mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-08 01:31:23 +00:00
test: collapse duplicate unhandled rejection fatal cases
This commit is contained in:
@@ -38,93 +38,71 @@ describe("installUnhandledRejectionHandler - fatal detection", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe("fatal errors", () => {
|
describe("fatal errors", () => {
|
||||||
it("exits on ERR_OUT_OF_MEMORY", () => {
|
it("exits on fatal runtime codes", () => {
|
||||||
const oomErr = Object.assign(new Error("Out of memory"), {
|
const fatalCases = [
|
||||||
code: "ERR_OUT_OF_MEMORY",
|
{ code: "ERR_OUT_OF_MEMORY", message: "Out of memory" },
|
||||||
});
|
{ code: "ERR_SCRIPT_EXECUTION_TIMEOUT", message: "Script execution timeout" },
|
||||||
|
{ code: "ERR_WORKER_OUT_OF_MEMORY", message: "Worker out of memory" },
|
||||||
|
] as const;
|
||||||
|
|
||||||
process.emit("unhandledRejection", oomErr, Promise.resolve());
|
for (const { code, message } of fatalCases) {
|
||||||
|
exitCalls = [];
|
||||||
|
const err = Object.assign(new Error(message), { code });
|
||||||
|
process.emit("unhandledRejection", err, Promise.resolve());
|
||||||
|
expect(exitCalls).toEqual([1]);
|
||||||
|
}
|
||||||
|
|
||||||
expect(exitCalls).toEqual([1]);
|
|
||||||
expect(consoleErrorSpy).toHaveBeenCalledWith(
|
expect(consoleErrorSpy).toHaveBeenCalledWith(
|
||||||
"[openclaw] FATAL unhandled rejection:",
|
"[openclaw] FATAL unhandled rejection:",
|
||||||
expect.stringContaining("Out of memory"),
|
expect.stringContaining("Out of memory"),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("exits on ERR_SCRIPT_EXECUTION_TIMEOUT", () => {
|
|
||||||
const timeoutErr = Object.assign(new Error("Script execution timeout"), {
|
|
||||||
code: "ERR_SCRIPT_EXECUTION_TIMEOUT",
|
|
||||||
});
|
|
||||||
|
|
||||||
process.emit("unhandledRejection", timeoutErr, Promise.resolve());
|
|
||||||
|
|
||||||
expect(exitCalls).toEqual([1]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("exits on ERR_WORKER_OUT_OF_MEMORY", () => {
|
|
||||||
const workerOomErr = Object.assign(new Error("Worker out of memory"), {
|
|
||||||
code: "ERR_WORKER_OUT_OF_MEMORY",
|
|
||||||
});
|
|
||||||
|
|
||||||
process.emit("unhandledRejection", workerOomErr, Promise.resolve());
|
|
||||||
|
|
||||||
expect(exitCalls).toEqual([1]);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("configuration errors", () => {
|
describe("configuration errors", () => {
|
||||||
it("exits on INVALID_CONFIG", () => {
|
it("exits on configuration error codes", () => {
|
||||||
const configErr = Object.assign(new Error("Invalid config"), {
|
const configurationCases = [
|
||||||
code: "INVALID_CONFIG",
|
{ code: "INVALID_CONFIG", message: "Invalid config" },
|
||||||
});
|
{ code: "MISSING_API_KEY", message: "Missing API key" },
|
||||||
|
] as const;
|
||||||
|
|
||||||
process.emit("unhandledRejection", configErr, Promise.resolve());
|
for (const { code, message } of configurationCases) {
|
||||||
|
exitCalls = [];
|
||||||
|
const err = Object.assign(new Error(message), { code });
|
||||||
|
process.emit("unhandledRejection", err, Promise.resolve());
|
||||||
|
expect(exitCalls).toEqual([1]);
|
||||||
|
}
|
||||||
|
|
||||||
expect(exitCalls).toEqual([1]);
|
|
||||||
expect(consoleErrorSpy).toHaveBeenCalledWith(
|
expect(consoleErrorSpy).toHaveBeenCalledWith(
|
||||||
"[openclaw] CONFIGURATION ERROR - requires fix:",
|
"[openclaw] CONFIGURATION ERROR - requires fix:",
|
||||||
expect.stringContaining("Invalid config"),
|
expect.stringContaining("Invalid config"),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("exits on MISSING_API_KEY", () => {
|
|
||||||
const missingKeyErr = Object.assign(new Error("Missing API key"), {
|
|
||||||
code: "MISSING_API_KEY",
|
|
||||||
});
|
|
||||||
|
|
||||||
process.emit("unhandledRejection", missingKeyErr, Promise.resolve());
|
|
||||||
|
|
||||||
expect(exitCalls).toEqual([1]);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("non-fatal errors", () => {
|
describe("non-fatal errors", () => {
|
||||||
it("does NOT exit on undici fetch failures", () => {
|
it("does not exit on known transient network errors", () => {
|
||||||
const fetchErr = Object.assign(new TypeError("fetch failed"), {
|
const transientCases = [
|
||||||
cause: { code: "UND_ERR_CONNECT_TIMEOUT", syscall: "connect" },
|
Object.assign(new TypeError("fetch failed"), {
|
||||||
});
|
cause: { code: "UND_ERR_CONNECT_TIMEOUT", syscall: "connect" },
|
||||||
|
}),
|
||||||
|
Object.assign(new Error("DNS resolve failed"), { code: "UND_ERR_DNS_RESOLVE_FAILED" }),
|
||||||
|
Object.assign(new Error("Connection reset"), { code: "ECONNRESET" }),
|
||||||
|
Object.assign(new Error("Timeout"), { code: "ETIMEDOUT" }),
|
||||||
|
];
|
||||||
|
|
||||||
process.emit("unhandledRejection", fetchErr, Promise.resolve());
|
for (const transientErr of transientCases) {
|
||||||
|
exitCalls = [];
|
||||||
|
process.emit("unhandledRejection", transientErr, Promise.resolve());
|
||||||
|
expect(exitCalls).toEqual([]);
|
||||||
|
}
|
||||||
|
|
||||||
expect(exitCalls).toEqual([]);
|
|
||||||
expect(consoleWarnSpy).toHaveBeenCalledWith(
|
expect(consoleWarnSpy).toHaveBeenCalledWith(
|
||||||
"[openclaw] Non-fatal unhandled rejection (continuing):",
|
"[openclaw] Non-fatal unhandled rejection (continuing):",
|
||||||
expect.stringContaining("fetch failed"),
|
expect.stringContaining("fetch failed"),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("does NOT exit on DNS resolution failures", () => {
|
|
||||||
const dnsErr = Object.assign(new Error("DNS resolve failed"), {
|
|
||||||
code: "UND_ERR_DNS_RESOLVE_FAILED",
|
|
||||||
});
|
|
||||||
|
|
||||||
process.emit("unhandledRejection", dnsErr, Promise.resolve());
|
|
||||||
|
|
||||||
expect(exitCalls).toEqual([]);
|
|
||||||
expect(consoleWarnSpy).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("exits on generic errors without code", () => {
|
it("exits on generic errors without code", () => {
|
||||||
const genericErr = new Error("Something went wrong");
|
const genericErr = new Error("Something went wrong");
|
||||||
|
|
||||||
@@ -136,27 +114,5 @@ describe("installUnhandledRejectionHandler - fatal detection", () => {
|
|||||||
expect.stringContaining("Something went wrong"),
|
expect.stringContaining("Something went wrong"),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("does NOT exit on connection reset errors", () => {
|
|
||||||
const connResetErr = Object.assign(new Error("Connection reset"), {
|
|
||||||
code: "ECONNRESET",
|
|
||||||
});
|
|
||||||
|
|
||||||
process.emit("unhandledRejection", connResetErr, Promise.resolve());
|
|
||||||
|
|
||||||
expect(exitCalls).toEqual([]);
|
|
||||||
expect(consoleWarnSpy).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("does NOT exit on timeout errors", () => {
|
|
||||||
const timeoutErr = Object.assign(new Error("Timeout"), {
|
|
||||||
code: "ETIMEDOUT",
|
|
||||||
});
|
|
||||||
|
|
||||||
process.emit("unhandledRejection", timeoutErr, Promise.resolve());
|
|
||||||
|
|
||||||
expect(exitCalls).toEqual([]);
|
|
||||||
expect(consoleWarnSpy).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user