mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-26 04:15:48 -06:00
fix(test): stabilize tooling guard probes (#95114)
* fix(test): release kitchen sink probe readers * test(github): follow shared guard membership helper
This commit is contained in:
@@ -996,25 +996,31 @@ export async function readBoundedResponseText(response, byteLimit, timeoutPromis
|
||||
}
|
||||
const chunks = [];
|
||||
let totalBytes = 0;
|
||||
for (;;) {
|
||||
const read = reader.read();
|
||||
const { done, value } = await withOptionalTimeout(
|
||||
read,
|
||||
timeoutPromise?.catch((error) => {
|
||||
cancelReaderSoon(reader);
|
||||
throw error;
|
||||
}),
|
||||
);
|
||||
if (done) {
|
||||
break;
|
||||
try {
|
||||
for (;;) {
|
||||
const read = reader.read();
|
||||
const { done, value } = await withOptionalTimeout(
|
||||
read,
|
||||
timeoutPromise?.catch((error) => {
|
||||
cancelReaderSoon(reader);
|
||||
throw error;
|
||||
}),
|
||||
);
|
||||
if (done) {
|
||||
break;
|
||||
}
|
||||
const chunk = Buffer.from(value);
|
||||
totalBytes += chunk.byteLength;
|
||||
if (totalBytes > resolvedByteLimit) {
|
||||
await reader.cancel().catch(() => undefined);
|
||||
throw createFetchBodyTooLargeError(resolvedByteLimit);
|
||||
}
|
||||
chunks.push(chunk);
|
||||
}
|
||||
const chunk = Buffer.from(value);
|
||||
totalBytes += chunk.byteLength;
|
||||
if (totalBytes > resolvedByteLimit) {
|
||||
await reader.cancel().catch(() => undefined);
|
||||
throw createFetchBodyTooLargeError(resolvedByteLimit);
|
||||
}
|
||||
chunks.push(chunk);
|
||||
} finally {
|
||||
try {
|
||||
reader.releaseLock?.();
|
||||
} catch {}
|
||||
}
|
||||
return Buffer.concat(chunks, totalBytes).toString("utf8");
|
||||
}
|
||||
|
||||
@@ -1976,6 +1976,30 @@ describe("kitchen-sink RPC process sampling", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("releases HTTP probe response stream readers after bounded reads", async () => {
|
||||
const releaseLock = vi.fn();
|
||||
const response = {
|
||||
headers: new Headers(),
|
||||
body: {
|
||||
getReader() {
|
||||
return {
|
||||
read: vi
|
||||
.fn()
|
||||
.mockResolvedValueOnce({ done: false, value: new TextEncoder().encode("ok") })
|
||||
.mockResolvedValueOnce({ done: true }),
|
||||
releaseLock,
|
||||
};
|
||||
},
|
||||
},
|
||||
text: vi.fn(async () => "not read"),
|
||||
};
|
||||
|
||||
await expect(readBoundedResponseText(response, 1024)).resolves.toBe("ok");
|
||||
|
||||
expect(releaseLock).toHaveBeenCalledOnce();
|
||||
expect(response.text).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("cancels stalled HTTP probe response streams when the timeout wins", async () => {
|
||||
let canceled = false;
|
||||
const timeoutError = Object.assign(new Error("fetch probe timed out"), {
|
||||
|
||||
@@ -136,6 +136,8 @@ describe("security-sensitive guard workflow", () => {
|
||||
it("uses a dedicated checked-in script and detects the intended file surfaces", () => {
|
||||
const workflow = readFileSync(WORKFLOW, "utf8");
|
||||
const script = readFileSync("scripts/github/security-sensitive-guard.mjs", "utf8");
|
||||
const sharedScript = readFileSync("scripts/github/guard-shared.mjs", "utf8");
|
||||
const guardSources = `${script}\n${sharedScript}`;
|
||||
|
||||
expect(workflow).toContain("scripts/github/security-sensitive-guard.mjs");
|
||||
expect(script).toContain('"security-sensitive-changed"');
|
||||
@@ -143,7 +145,7 @@ describe("security-sensitive guard workflow", () => {
|
||||
expect(script).toContain(".env");
|
||||
expect(script).toContain("/allow-security-sensitive-change");
|
||||
expect(script).toContain("openclaw-secops");
|
||||
expect(script).toContain("/memberships/");
|
||||
expect(guardSources).toContain("/memberships/");
|
||||
expect(script).toContain("A later push requires a fresh approval.");
|
||||
expect(script).toContain("process.exitCode = 1");
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user