test(desktop): harden terminal engine gates

Co-authored-by: tlongwell-block <109685178+tlongwell-block@users.noreply.github.com>
Signed-off-by: tlongwell-block <109685178+tlongwell-block@users.noreply.github.com>
This commit is contained in:
npub1t2tgm7d8f995uqvmnm8h88sg3wnpp9a5xysjf6dg3tjmgt3ltulqdp8ehr
2026-08-01 20:10:30 -04:00
parent 1768d3c435
commit 59648f0706
3 changed files with 114 additions and 118 deletions

View File

@@ -202,6 +202,12 @@ desktop-tauri-check: _ensure-sidecar-stubs
desktop-tauri-test: _ensure-sidecar-stubs
cd desktop/src-tauri && cargo test --workspace
# Run the native terminal latency gate explicitly on a known-idle host.
# This is intentionally excluded from shared CI: scheduler contention makes a
# wall-clock assertion flaky, and the release profile is the shipped shape.
desktop-terminal-performance-test:
cargo test --manifest-path desktop/src-tauri/crates/buzz-terminal/Cargo.toml --release --test latency g3_renderer_acquire_stays_within_frame_budget -- --ignored --exact --nocapture
# Verify compiled-flag behavior under both compile states (clean + internal).
# Runs the observer_archive focused test twice with independently supplied
# expected values; build.rs rerun-if-env-changed triggers recompilation.

View File

@@ -1,14 +1,19 @@
//! Fence behaviour against byte fixtures. No PTY, no process, no window --
//! these are pure functions of input bytes and run identically on every
//! platform.
//! Mutation-sensitive byte fixtures for the two parser fences.
//!
//! Per the mutation law, arms that can be masked by the *other* fence run with
//! that fence disabled. F1's abort releases a synchronized buffer in 64 KiB
//! pieces, which hides an F2 that charges the wrong bytes.
//! These use the shipping `Terminal::feed` path. Arms that could be masked by
//! the other fence disable it explicitly; the switches are runtime values, not
//! cargo features, so the default test binary always contains every arm.
use alacritty_terminal::grid::Dimensions;
use alacritty_terminal::index::{Column, Line, Point};
use buzz_terminal::fences::{Fences, OSC_BUDGET, SYNC_CAP};
use buzz_terminal::{Size, Terminal};
const CHUNK: usize = 8192;
const G1_BYTES: usize = 2 << 20;
const G2_FRAMES: usize = 40;
const G2_FRAME_BYTES: usize = 1_900 * 1024;
fn size() -> Size {
Size {
columns: 120,
@@ -17,37 +22,21 @@ fn size() -> Size {
}
}
/// A hostile stream: open a synchronized update, then never close it.
fn unterminated_sync(total: usize, chunk: usize) -> Vec<Vec<u8>> {
let mut chunks = vec![b"\x1b[?2026h".to_vec()];
let mut sent = 0;
while sent < total {
chunks.push(vec![b'A'; chunk]);
sent += chunk;
fn feed_synchronized(term: &mut Terminal, payload: &[u8], close: bool) {
term.feed(b"\x1b[?2026h");
for chunk in payload.chunks(CHUNK) {
term.feed(chunk);
}
if close {
term.feed(b"\x1b[?2026l");
}
chunks
}
/// A legitimate frame: one synchronized update carrying `markers` findable
/// markers, closed properly.
fn legit_frame(markers: usize, per_marker: usize) -> Vec<u8> {
let mut payload = Vec::new();
payload.extend_from_slice(b"\x1b[?2026h\x1b[2J\x1b[H");
for marker in 0..markers {
payload.extend_from_slice(format!("MK{marker:03}\r\n").as_bytes());
let target = payload.len() + per_marker;
while payload.len() < target {
payload.extend_from_slice(b"\x1b[1;32mx\x1b[0m");
}
payload.extend_from_slice(b"\r\n");
}
payload.extend_from_slice(b"\x1b[?2026l");
payload
fn repeated(pattern: &[u8], bytes: usize) -> Vec<u8> {
pattern.iter().copied().cycle().take(bytes).collect()
}
fn count_markers(term: &Terminal, markers: usize) -> usize {
use alacritty_terminal::grid::Dimensions;
use alacritty_terminal::index::{Column, Line, Point};
let grid = term.term().grid();
let mut text = String::new();
let top = -(grid.history_size() as i32);
@@ -62,119 +51,119 @@ fn count_markers(term: &Terminal, markers: usize) -> usize {
.count()
}
/// G1: a synchronized update may not buffer without bound.
#[test]
fn g1_sync_abort_bounds_one_release() {
let (mut term, _actions) = Terminal::new(size(), Fences::ALL);
for chunk in unterminated_sync(8 << 20, 8192) {
term.feed(&chunk);
fn legitimate_frame(markers: usize, bytes: usize) -> Vec<u8> {
let mut payload = Vec::with_capacity(bytes);
for marker in 0..markers {
payload.extend_from_slice(format!("MK{marker:03}\r\n").as_bytes());
let target = bytes * (marker + 1) / markers;
while payload.len() < target {
payload.extend_from_slice(b"\x1b[1;32mx\x1b[0m");
}
payload.extend_from_slice(b"\r\n");
}
let stats = term.stats();
assert!(
stats.sync_aborts > 0,
"F1 never fired on an unterminated update"
);
// One chunk may arrive after the cap is reached but before the abort, so
// the bound is the cap plus one read.
assert!(
stats.max_release <= SYNC_CAP + 8192,
"single release of {} B exceeds the F1 bound",
stats.max_release
);
payload.truncate(bytes);
payload
}
/// The unfenced control: without F1 the same stream releases in ~2 MiB gulps.
/// If this stops holding, `g1_sync_abort_bounds_one_release` proves nothing.
///
/// Note what is asserted: **peak release**, not the trailing buffer. vte caps
/// its own sync buffer at `SYNC_BUFFER_SIZE` (2 MiB, `vte-0.15.0` ansi.rs:39)
/// and self-flushes there, so the buffer is near-empty when the stream stops.
/// That upstream cap is the ~2 MiB residual the plan scopes to "F1 absent or
/// ineffective" -- it is a backstop 32x above our bound, not a substitute.
/// G1: every hostile content shape must remain below the deterministic byte
/// bound, and the same shape with F1 deleted must cross it. Keeping both arms
/// adjacent prevents a simplified fixture from becoming vacuously cheap.
#[test]
fn g1_control_unfenced_releases_in_megabyte_gulps() {
let (mut term, _actions) = Terminal::new(size(), Fences::NONE);
for chunk in unterminated_sync(8 << 20, 8192) {
term.feed(&chunk);
fn g1_sync_abort_bounds_all_hostile_shapes() {
let shapes: [(&str, &[u8]); 5] = [
("sgr", b"\x1b[1;32mbuzz\x1b[0m\r\n"),
("ascii", b"buzz substrate output\r\n"),
("emoji", "🐝🚀✨\r\n".as_bytes()),
("zalgo", "z\u{0301}\u{0302}\u{0303}\u{0304}\r\n".as_bytes()),
("truecolor", b"\x1b[38;2;255;0;128mRGB\x1b[0m\r\n"),
];
for (name, pattern) in shapes {
let payload = repeated(pattern, G1_BYTES);
let (mut fenced, _) = Terminal::new(size(), Fences::ALL);
feed_synchronized(&mut fenced, &payload, false);
let fenced_stats = fenced.stats();
assert!(fenced_stats.sync_aborts > 0, "{name}: F1 never fired");
assert!(
fenced_stats.max_release <= 2 * SYNC_CAP,
"{name}: fenced release {} exceeds 128 KiB",
fenced_stats.max_release
);
let (mut unfenced, _) = Terminal::new(size(), Fences::NONE);
feed_synchronized(&mut unfenced, &payload, false);
let unfenced_stats = unfenced.stats();
assert_eq!(unfenced_stats.sync_aborts, 0, "{name}: control enabled F1");
assert!(
unfenced_stats.max_release > 2 * SYNC_CAP,
"{name}: unfenced release {} stayed inside the gate; fixture is vacuous",
unfenced_stats.max_release
);
}
let stats = term.stats();
assert_eq!(stats.sync_aborts, 0);
assert!(
stats.max_release > SYNC_CAP,
"unfenced release peaked at {} B, inside the F1 bound; the fixture is not hostile \
and the G1 assertion is vacuous",
stats.max_release
);
}
/// G2 arm 1: F2 fires on a hostile unsynchronized stream.
/// F1 is retained here on purpose -- this arm proves F2 *deletion* under the
/// combined production shape.
/// G2 arm 1: deletion oracle. F1 remains enabled because this arm proves F2
/// deletion under the combined production configuration.
#[test]
fn g2_hostile_osc_triggers_reset() {
let (mut term, _actions) = Terminal::new(size(), Fences::ALL);
let mut chunks = vec![b"\x1b]0;".to_vec()];
for _ in 0..256 {
chunks.push(vec![b'A'; 8192]);
}
for chunk in &chunks {
fn g2_hostile_unsynchronized_osc_resets_parser() {
let (mut term, _) = Terminal::new(size(), Fences::ALL);
term.feed(b"\x1b]0;");
for chunk in repeated(b"A", OSC_BUDGET * 4).chunks(CHUNK) {
term.feed(chunk);
}
assert!(term.stats().osc_resets > 0, "F2 never rebuilt the parser");
}
/// G2 arm 2: charge accounting includes the flush route.
///
/// **F1 disabled** -- with it on, the abort releases the buffer in pieces that
/// are charged as ordinary input, so an F2 that ignores flushes still resets
/// and the arm cannot see the mutation.
/// G2 arm 2: every synchronized release is attributed. F1 is disabled so its
/// small abort releases cannot mask an implementation that omits ESU flushes.
#[test]
fn g2_flush_route_is_charged() {
let (mut term, _actions) = Terminal::new(size(), Fences::OSC_ONLY);
// Each frame buffers just under the budget, then releases it all at once.
// The released bytes are parser-visible only at the ESU.
let frame_bytes = OSC_BUDGET - (32 << 10);
let frames = 8;
for _ in 0..frames {
term.feed(b"\x1b[?2026h");
let mut sent = 0;
while sent < frame_bytes {
term.feed(&vec![b'A'; 8192]);
sent += 8192;
}
term.feed(b"\x1b[?2026l");
fn g2_each_synchronized_flush_is_attributed() {
let payload = repeated(b"A", G2_FRAME_BYTES);
let (mut term, _) = Terminal::new(size(), Fences::OSC_ONLY);
for _ in 0..G2_FRAMES {
feed_synchronized(&mut term, &payload, true);
}
let stats = term.stats();
assert_eq!(stats.sync_aborts, 0, "F1 must be disabled in this arm");
assert_eq!(
stats.sync_aborts, 0,
"F1 must be off for this arm to discriminate"
stats.osc_resets, G2_FRAMES as u64,
"expected one reset for each atomic synchronized release"
);
assert!(
stats.charged_bytes >= (frames * frame_bytes) as u64,
"charged {} B of {} B released through the flush route",
stats.charged_bytes,
frames * frame_bytes
);
assert!(
stats.osc_resets > 0,
"budget never spent: flush accounting omitted"
stats.charged_bytes >= (G2_FRAMES * G2_FRAME_BYTES) as u64,
"flush bytes were omitted from attribution: {} charged",
stats.charged_bytes
);
}
/// G2 arm 3: a legitimate frame survives intact.
///
/// **F1 disabled** -- this is the arm that catches raw counting, and F1's
/// abort masks it by releasing the buffer before the raw count can overrun.
/// G2 arm 3: parser-visible attribution preserves a legitimate 1.5 MiB frame.
/// F1 is disabled; raw-input counting would reset mid-frame and lose markers.
#[test]
fn g2_legitimate_frame_survives() {
fn g2_legitimate_large_frame_preserves_all_markers() {
let markers = 200;
let (mut term, _actions) = Terminal::new(size(), Fences::OSC_ONLY);
for chunk in legit_frame(markers, 7853).chunks(8192) {
term.feed(chunk);
}
let payload = legitimate_frame(markers, 1_500 * 1024);
let (mut term, _) = Terminal::new(size(), Fences::OSC_ONLY);
feed_synchronized(&mut term, &payload, true);
assert_eq!(
count_markers(&term, markers),
markers,
"content lost from a legitimate frame"
"legitimate frame lost markers"
);
}
/// Legitimacy control: neither fence alone nor the production combination may
/// corrupt a normal synchronized frame.
#[test]
fn g2_legitimate_frame_survives_each_fence_configuration() {
let markers = 200;
let payload = legitimate_frame(markers, 128 * 1024);
for fences in [Fences::SYNC_ONLY, Fences::OSC_ONLY, Fences::ALL] {
let (mut term, _) = Terminal::new(size(), fences);
feed_synchronized(&mut term, &payload, true);
assert_eq!(
count_markers(&term, markers),
markers,
"{fences:?} lost markers"
);
}
}

View File

@@ -107,6 +107,7 @@ fn measure(fences: Fences) -> buzz_terminal::AcquireStats {
/// measurement includes the other arm's CPU load and the control's ratio
/// becomes a race between two floods rather than a statement about F1.
#[test]
#[ignore = "native performance gate; run release-mode on a known-idle host"]
fn g3_renderer_acquire_stays_within_frame_budget() {
let fenced = measure(Fences::ALL);
let p95 = fenced.percentile_micros(0.95);