agent-orchestrator/ui-electrobun/tests/unit/hardening/backpressure.test.ts
Hibryda 1995f03682 test: complete test suite — 166 new tests (stores + hardening + agent)
@agor/stores (37 tests):
- theme: 6 (17 themes, 3 groups, no duplicates)
- notifications: 11 (types, rate limiter, window expiry)
- health: 20 (scoring, burn rate, context pressure, tool tracking)

Electrobun stores (90 tests):
- agent-store: 27 (seqId, dedup, double-start guard, persistence)
- workspace-store: 17 (CRUD, derived state, aggregates)
- plugin-store: 14 (commands, events, permissions, meta)
- keybinding-store: 18 (defaults, chords, conflicts, capture)

Hardening (39 tests):
- durable-sequencing: 10 (monotonic, dedup, restore)
- file-conflict: 10 (mtime, atomic write, workflows)
- backpressure: 7 (paste 64KB, buffer 50MB, line 10MB)
- retention: 7 (count, age, running protected)
- channel-acl: 9 (join/leave, rejection, isolation)

Total across all suites: 1,020+ tests
2026-03-22 05:07:40 +01:00

103 lines
3.9 KiB
TypeScript

// Tests for backpressure guards — paste truncation and stdout buffer limits.
// Uses bun:test. Tests the logic from Terminal.svelte and sidecar-manager.ts.
import { describe, it, expect } from 'bun:test';
// ── Constants (replicated from source) ──────────────────────────────────────
const MAX_PASTE_CHUNK = 64 * 1024; // 64 KB (Terminal.svelte)
const MAX_LINE_SIZE = 10 * 1024 * 1024; // 10 MB (sidecar-manager.ts)
const MAX_PENDING_BUFFER = 50 * 1024 * 1024; // 50 MB (sidecar-manager.ts)
// ── Replicated truncation logic ──────────────────────────────────────────────
function truncatePaste(payload: string): { text: string; wasTruncated: boolean } {
if (payload.length > MAX_PASTE_CHUNK) {
return { text: payload.slice(0, MAX_PASTE_CHUNK), wasTruncated: true };
}
return { text: payload, wasTruncated: false };
}
function applyBufferBackpressure(buffer: string): string {
// If buffer exceeds MAX_PENDING_BUFFER, keep only last MAX_LINE_SIZE bytes
if (buffer.length > MAX_PENDING_BUFFER) {
return buffer.slice(-MAX_LINE_SIZE);
}
return buffer;
}
function shouldTruncateLine(buffer: string): boolean {
// If buffer exceeds MAX_LINE_SIZE without a newline, truncate
return buffer.length > MAX_LINE_SIZE && !buffer.includes('\n');
}
// ── Tests ───────────────────────────────────────────────────────────────────
describe('paste truncation', () => {
it('passes through text under 64KB', () => {
const text = 'hello world';
const result = truncatePaste(text);
expect(result.wasTruncated).toBe(false);
expect(result.text).toBe(text);
});
it('passes through text exactly at 64KB', () => {
const text = 'x'.repeat(MAX_PASTE_CHUNK);
const result = truncatePaste(text);
expect(result.wasTruncated).toBe(false);
expect(result.text.length).toBe(MAX_PASTE_CHUNK);
});
it('truncates text over 64KB', () => {
const text = 'x'.repeat(MAX_PASTE_CHUNK + 1000);
const result = truncatePaste(text);
expect(result.wasTruncated).toBe(true);
expect(result.text.length).toBe(MAX_PASTE_CHUNK);
});
it('preserves first 64KB of content on truncation', () => {
const prefix = 'START-';
const text = prefix + 'x'.repeat(MAX_PASTE_CHUNK + 1000);
const result = truncatePaste(text);
expect(result.text.startsWith('START-')).toBe(true);
});
});
describe('stdout buffer backpressure', () => {
it('leaves buffer unchanged under 50MB', () => {
const buffer = 'x'.repeat(1000);
expect(applyBufferBackpressure(buffer)).toBe(buffer);
});
it('truncates buffer over 50MB to last 10MB', () => {
const buffer = 'x'.repeat(MAX_PENDING_BUFFER + 1000);
const result = applyBufferBackpressure(buffer);
expect(result.length).toBe(MAX_LINE_SIZE);
});
it('keeps tail of buffer (most recent data)', () => {
const head = 'H'.repeat(MAX_PENDING_BUFFER);
const tail = 'T'.repeat(MAX_LINE_SIZE);
const buffer = head + tail;
const result = applyBufferBackpressure(buffer);
// Result should be the last MAX_LINE_SIZE chars, which is all T's
expect(result).toBe(tail);
});
});
describe('line size guard', () => {
it('no truncation for buffer with newlines', () => {
const buffer = 'x'.repeat(MAX_LINE_SIZE + 100) + '\nmore data';
expect(shouldTruncateLine(buffer)).toBe(false);
});
it('truncates when buffer exceeds MAX_LINE_SIZE without newline', () => {
const buffer = 'x'.repeat(MAX_LINE_SIZE + 1);
expect(shouldTruncateLine(buffer)).toBe(true);
});
it('no truncation at exactly MAX_LINE_SIZE', () => {
const buffer = 'x'.repeat(MAX_LINE_SIZE);
expect(shouldTruncateLine(buffer)).toBe(false);
});
});