Files
reverse-engineering-anything/src/browser/CdpCaptureEvents.eventBudget.test.ts
T
morluto d23dc5d188 fix(browser): admit JSON shape expansion against shared retention
Require explicit shape output admission before allocating expanded paths. Share capture retention across console entries, WebSocket frames and selected request/response shapes, with exact shape replacement and removal receipts.

Preserve malformed-input versus capacity outcomes and peer facts. Validated deep, wide, Unicode, repeated-row, replacement, redirect, reset and mixed-retention regressions.
2026-10-25 09:49:26 +08:00

147 lines
4.7 KiB
TypeScript

import { expect, it } from "vitest";
import { inspectWebPageInputSchema } from "../domain/browserObservation.js";
import { WEB_RUNTIME_LIMITS } from "../domain/webRuntime.js";
import { CdpCaptureEvents } from "./CdpCaptureEvents.js";
const origin = "http://127.0.0.1:43127";
const createEvents = (extra: Record<string, unknown> = {}): CdpCaptureEvents =>
new CdpCaptureEvents(
inspectWebPageInputSchema.parse({
cdp_endpoint: origin,
allowed_origins: [origin],
target_id: "page",
include_console_text: true,
include_websocket_shapes: true,
...extra,
}),
new Set([origin]),
);
it("admits console events until the shared retained-event budget and reports the dropped count", () => {
const events = createEvents();
const text = "x".repeat(1024 * 1024);
const total =
Math.ceil(WEB_RUNTIME_LIMITS.retainedEventBytes / text.length) + 2;
for (let index = 0; index < total; index += 1)
events.ingest({
method: "Runtime.consoleAPICalled",
params: {
type: "log",
timestamp: index,
args: [{ type: "string", value: text }],
stackTrace: {
callFrames: [
{ url: `${origin}/app.js`, lineNumber: 0, columnNumber: 0 },
],
},
},
});
expect(events.console.length).toBeLessThan(total);
expect(events.console.length).toBeGreaterThan(0);
const snapshot = events.completeness.snapshot();
const dropped = total - events.console.length;
expect(snapshot.dropped_events.console_events).toBe(dropped);
expect(snapshot.dropped_events.total).toBe(dropped);
});
it("keeps a small console inventory admitted under the budget untouched", () => {
const events = createEvents();
for (let index = 0; index < 16; index += 1)
events.ingest({
method: "Runtime.consoleAPICalled",
params: {
type: "log",
timestamp: index,
args: [{ type: "string", value: `entry ${String(index)}` }],
stackTrace: {
callFrames: [
{ url: `${origin}/app.js`, lineNumber: 0, columnNumber: 0 },
],
},
},
});
expect(events.console).toHaveLength(16);
expect(events.completeness.snapshot().dropped_events.total).toBe(0);
});
it("drops a websocket frame whose retained shape alone exceeds the shared budget", () => {
const events = createEvents();
events.ingest({
method: "Network.webSocketCreated",
params: { requestId: "socket", url: `ws://${origin.slice(7)}/live` },
});
events.ingest({
method: "Network.webSocketFrameReceived",
params: {
requestId: "socket",
response: { opcode: 1, payloadData: '{"small":"frame"}' },
},
});
const keys = Array.from(
{ length: 120_000 },
(_value, index) => `key${String(index)}`,
);
events.ingest({
method: "Network.webSocketFrameReceived",
params: {
requestId: "socket",
response: {
opcode: 1,
payloadData: `{${keys.map((key) => `"${key}":"v"`).join(",")}}`,
},
},
});
const connection = events.webSocketConnectionsById.get("socket");
expect(connection?.events).toHaveLength(1);
const snapshot = events.completeness.snapshot();
expect(snapshot.dropped_events.websocket_frames).toBe(1);
expect(snapshot.dropped_events.total).toBe(1);
});
it("spends one shared allowance across console entries and websocket frames", () => {
const events = createEvents();
const text = "x".repeat(1024 * 1024);
// Seven megabyte console entries leave roughly one megabyte of the shared
// allowance, so a shape that fits an empty allowance no longer fits.
for (let index = 0; index < 7; index += 1)
events.ingest({
method: "Runtime.consoleAPICalled",
params: {
type: "log",
timestamp: index,
args: [{ type: "string", value: text }],
stackTrace: {
callFrames: [
{ url: `${origin}/app.js`, lineNumber: 0, columnNumber: 0 },
],
},
},
});
expect(events.console).toHaveLength(7);
events.ingest({
method: "Network.webSocketCreated",
params: { requestId: "socket", url: `ws://${origin.slice(7)}/live` },
});
const keys = Array.from(
{ length: 20_000 },
(_value, index) => `key${String(index)}`,
);
events.ingest({
method: "Network.webSocketFrameReceived",
params: {
requestId: "socket",
response: {
opcode: 1,
payloadData: `{${keys.map((key) => `"${key}":"v"`).join(",")}}`,
},
},
});
expect(events.webSocketConnectionsById.get("socket")?.events).toHaveLength(0);
const snapshot = events.completeness.snapshot();
expect(snapshot.dropped_events.console_events).toBe(0);
expect(snapshot.dropped_events.websocket_frames).toBe(1);
expect(snapshot.dropped_events.total).toBe(1);
});