mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 16:10:49 +00:00
refactor(qa): add shared QA channel contract and harden worker startup (#64562)
* refactor(qa): add shared transport contract and suite migration * refactor(qa): harden worker gateway startup * fix(qa): scope waits and sanitize shutdown artifacts * fix(qa): confine artifacts and redact preserved logs * fix(qa): block symlink escapes in artifact paths * fix(gateway): clear shutdown race timers * fix(qa): harden shutdown cleanup paths * fix(qa): sanitize gateway logs in thrown errors * fix(qa): harden suite startup and artifact paths * fix(qa): stage bundled plugins from mutated config * fix(qa): broaden gateway log bearer redaction * fix(qa-channel): restore runtime export * fix(qa): stop failed gateway startups as a process tree * fix(qa-channel): load runtime hook from api surface
This commit is contained in:
@@ -193,6 +193,68 @@ describe("server-channels auto restart", () => {
|
||||
expect(startAccount).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it("consumes rejected stop tasks during manual abort", async () => {
|
||||
const unhandledRejection = vi.fn();
|
||||
process.on("unhandledRejection", unhandledRejection);
|
||||
try {
|
||||
const startAccount = vi.fn(
|
||||
async ({ abortSignal }: { abortSignal: AbortSignal }) =>
|
||||
await new Promise<void>((_resolve, reject) => {
|
||||
abortSignal.addEventListener(
|
||||
"abort",
|
||||
() => {
|
||||
reject(new Error("aborted"));
|
||||
},
|
||||
{ once: true },
|
||||
);
|
||||
}),
|
||||
);
|
||||
installTestRegistry(
|
||||
createTestPlugin({
|
||||
startAccount,
|
||||
}),
|
||||
);
|
||||
const manager = createManager();
|
||||
|
||||
await manager.startChannels();
|
||||
vi.runAllTicks();
|
||||
await manager.stopChannel("discord", DEFAULT_ACCOUNT_ID);
|
||||
await Promise.resolve();
|
||||
|
||||
expect(unhandledRejection).not.toHaveBeenCalled();
|
||||
} finally {
|
||||
process.off("unhandledRejection", unhandledRejection);
|
||||
}
|
||||
});
|
||||
|
||||
it("does not allow a second account task to start when stop times out", async () => {
|
||||
const startAccount = vi.fn(
|
||||
async ({ abortSignal }: { abortSignal: AbortSignal }) =>
|
||||
await new Promise<void>(() => {
|
||||
abortSignal.addEventListener("abort", () => {}, { once: true });
|
||||
}),
|
||||
);
|
||||
installTestRegistry(
|
||||
createTestPlugin({
|
||||
startAccount,
|
||||
}),
|
||||
);
|
||||
const manager = createManager();
|
||||
|
||||
await manager.startChannels();
|
||||
const stopTask = manager.stopChannel("discord", DEFAULT_ACCOUNT_ID);
|
||||
await vi.advanceTimersByTimeAsync(5_000);
|
||||
await stopTask;
|
||||
await manager.startChannel("discord", DEFAULT_ACCOUNT_ID);
|
||||
|
||||
const snapshot = manager.getRuntimeSnapshot();
|
||||
const account = snapshot.channelAccounts.discord?.[DEFAULT_ACCOUNT_ID];
|
||||
expect(startAccount).toHaveBeenCalledTimes(1);
|
||||
expect(account?.running).toBe(true);
|
||||
expect(account?.restartPending).toBe(false);
|
||||
expect(account?.lastError).toContain("channel stop timed out");
|
||||
});
|
||||
|
||||
it("marks enabled/configured when account descriptors omit them", () => {
|
||||
installTestRegistry(
|
||||
createTestPlugin({
|
||||
|
||||
Reference in New Issue
Block a user