use std::time::Duration;
use termlens::{Key, Terminal};
mod common;
fn answered(n: usize) -> termlens::Result<usize> {
let queries = r"\e[6n".repeat(n);
let expected = (n * 6).to_string();
let mut t = common::spawn_emit(
Terminal::builder()
.size(80, 6)
.timeout(Duration::from_secs(30)),
&[
"--raw-mode",
"--raw",
&queries,
"ASKED GOT[",
"--read-count",
&expected,
"R",
"] DONE",
"--wait",
],
)?;
t.wait_until(|s| s.contains("DONE"))?;
let text = t.screen().text();
let count = text
.split("GOT[")
.nth(1)
.and_then(|s| s.split(']').next())
.and_then(|s| s.trim().parse().ok())
.unwrap_or(usize::MAX);
t.send(Key::Enter)?;
assert!(t.wait_exit()?.success());
Ok(count)
}
#[test]
#[cfg_attr(
windows,
ignore = "ConPTY answers or eats the child's queries itself, so they never reach the responder (#149)"
)]
fn a_batch_of_probes_is_answered_in_full() -> termlens::Result<()> {
for n in [50usize, 200, 400] {
assert_eq!(answered(n)?, n, "asked {n} probes back to back");
}
Ok(())
}
#[test]
#[cfg_attr(
windows,
ignore = "ConPTY answers or eats the child's queries itself, so they never reach the responder (#149)"
)]
fn fine_grained_arrival_is_answered_in_full() -> termlens::Result<()> {
for n in [100usize, 400] {
let expected = (n * 6).to_string();
let mut steps: Vec<&str> = vec!["--raw-mode"];
for _ in 0..n {
steps.extend(["--raw", r"\e[6n"]);
}
steps.extend([
"ASKED GOT[",
"--read-count",
&expected,
"R",
"] DONE",
"--wait",
]);
let mut t = common::spawn_emit(
Terminal::builder()
.size(80, 6)
.timeout(Duration::from_secs(40)),
&steps,
)?;
t.wait_until(|s| s.contains("DONE"))?;
let text = t.screen().text();
let got: usize = text
.split("GOT[")
.nth(1)
.and_then(|s| s.split(']').next())
.and_then(|s| s.trim().parse().ok())
.unwrap_or(usize::MAX);
assert_eq!(got, n, "one read per query must not lose answers");
t.send(Key::Enter)?;
assert!(t.wait_exit()?.success());
}
Ok(())
}