mirror of
https://github.com/morluto/rea.git
synced 2026-10-26 17:35:11 +00:00
Merge pull request #1293 from morluto/fix/process-capture-terminal-byte-accounting
fix(process): validate terminal byte totals against retained frames
This commit is contained in:
2 files changed
+48
-2
No files matched your search
@@ -140,17 +140,39 @@ const validateCoverage = (
|
||||
hasCaptureTruncation(
|
||||
details,
|
||||
), "truncation_details", "aggregate truncation must match producer coverage");
|
||||
for (const [name, retention, count] of [
|
||||
["raw_terminal", details.raw_terminal, capture.frames.length],
|
||||
for (const [name, retention, count, bytes] of [
|
||||
[
|
||||
"raw_terminal",
|
||||
details.raw_terminal,
|
||||
capture.frames.length,
|
||||
capture.frames.reduce(
|
||||
(total, frame) =>
|
||||
total + Buffer.byteLength(frame.raw_data ?? frame.data),
|
||||
0,
|
||||
),
|
||||
],
|
||||
[
|
||||
"rendered_terminal",
|
||||
details.rendered_terminal,
|
||||
capture.rendered_frames.length,
|
||||
capture.rendered_frames.reduce(
|
||||
(total, frame) =>
|
||||
frame.lines.reduce(
|
||||
(sum, line) => sum + Buffer.byteLength(line),
|
||||
total + Buffer.byteLength(frame.serialized_state),
|
||||
),
|
||||
0,
|
||||
),
|
||||
],
|
||||
] as const) {
|
||||
// Whole frames are retained or omitted, so retained bytes are exactly the
|
||||
// retained frames' bytes, and nothing is unretained when no frame was omitted.
|
||||
require(retention.retained_frames === count &&
|
||||
retention.observed_frames >= count &&
|
||||
retention.retained_bytes === bytes &&
|
||||
retention.observed_bytes >= retention.retained_bytes &&
|
||||
(retention.observed_frames > count ||
|
||||
retention.observed_bytes === retention.retained_bytes) &&
|
||||
retention.retained_bytes <=
|
||||
retention.budget_bytes, `truncation_details.${name}`, "retained observations and budget accounting do not agree");
|
||||
}
|
||||
|
||||
@@ -133,6 +133,30 @@ itWithCaptureCapability.each(["cli", "mcp"] as const)(
|
||||
expect(
|
||||
processCaptureSchema.safeParse({ ...result, truncated: false }).success,
|
||||
).toBe(false);
|
||||
const withTerminal = (
|
||||
name: "raw_terminal" | "rendered_terminal",
|
||||
change: Partial<typeof details.raw_terminal>,
|
||||
) =>
|
||||
processCaptureSchema.safeParse({
|
||||
...result,
|
||||
truncation_details: {
|
||||
...details,
|
||||
[name]: { ...details[name], ...change },
|
||||
},
|
||||
}).success;
|
||||
// Byte totals must match the retained frames, and with no omitted frame
|
||||
// nothing observed can be missing from retention.
|
||||
expect(withTerminal("raw_terminal", { retained_bytes: 0 })).toBe(false);
|
||||
expect(
|
||||
withTerminal("raw_terminal", {
|
||||
observed_bytes: details.raw_terminal.observed_bytes + 1,
|
||||
}),
|
||||
).toBe(false);
|
||||
expect(
|
||||
withTerminal("rendered_terminal", {
|
||||
retained_bytes: details.rendered_terminal.retained_bytes - 1,
|
||||
}),
|
||||
).toBe(false);
|
||||
},
|
||||
20_000,
|
||||
);
|
||||
|
||||
Reference in new issue
Block a user