Files
OmniRoute/tests/unit/compression/mcpAccessibility-clamp.test.ts
Diego Rodrigues de Sa e Souza 3c9883bb73 Release v3.8.29 (#4126)
OmniRoute v3.8.29 — 115 commits since v3.8.28. Full CHANGELOG + 41 i18n mirrors. All content quality gates green (build, unit 8/8, vitest 188/188, PR test policy, quality gates extended, docs sync, quality ratchet). Remaining red CI checks are pre-existing release flakes (coverage-shard/integration/node-compat teardown), a new transitive undici advisory in electron devDeps, and a workflow-level CodeQL fail (0 open alerts). VPS-validated by the operator.
2026-06-19 06:49:01 -03:00

47 lines
2.3 KiB
TypeScript

import { test } from "node:test";
import assert from "node:assert/strict";
import { smartFilterText } from "../../../open-sse/services/compression/engines/mcpAccessibility/index.ts";
import { DEFAULT_MCP_ACCESSIBILITY_CONFIG } from "../../../open-sse/services/compression/engines/mcpAccessibility/constants.ts";
// F5.3: `headSize = config.maxTextChars - 300` goes negative when maxTextChars is below the
// 300-char tail reservation, and `out.slice(0, negative)` counts from the END — silently
// keeping a wrong (and oversized) fragment instead of the intended head. maxTextChars is
// only floored to > 0 on the write path, so a stored value in [1,300] reaches this code.
test("clamps head to >=0 when maxTextChars is below the tail reservation (≤300)", () => {
const config = {
...DEFAULT_MCP_ACCESSIBILITY_CONFIG,
maxTextChars: 50,
minLengthToProcess: 1,
};
const input = "A".repeat(500);
const out = smartFilterText(input, config);
// Bug: headSize = -250 → slice(0,-250) keeps the first 250 chars → output leaks a long
// run of 'A' and is far larger than maxTextChars. Fixed: headSize clamps to 0 → empty
// head → output is just the truncation notice (which contains no capital 'A').
assert.ok(!out.includes("A"), "head must be empty (clamped) — no leaked content from a negative slice");
assert.ok(out.includes("truncated"), "still emits the truncation notice");
});
test("reports omitted chars relative to the filtered text, not the raw input", () => {
// Noise lines get stripped before truncation, so `omitted` must be measured against the
// filtered text (`out`), not the longer raw `text`.
const noise = "- generic:\n".repeat(10); // stripped by NOISE_PATTERNS
const input = noise + "B".repeat(1000);
const config = {
...DEFAULT_MCP_ACCESSIBILITY_CONFIG,
maxTextChars: 400,
minLengthToProcess: 1,
};
const out = smartFilterText(input, config);
const match = out.match(/truncated (\d+) chars/);
assert.ok(match, "emits a truncation notice with an omitted count");
const omitted = Number(match[1]);
// Filtered text is ~1010 chars; head keeps 100 → omitted ~910. The raw input is 1110, so
// the buggy `text.length - head.length` would report ~1010 (> filtered length).
assert.ok(
omitted <= 1000,
`omitted must reflect the filtered text (<=1000), got ${omitted}`
);
});