use std::sync::mpsc;
use std::thread;
use std::time::Duration;
use termlens::{Key, Terminal};
const AT_ONCE: usize = 24;
#[test]
fn two_dozen_terminals_open_at_once() {
let (report, results) = mpsc::channel();
let mut threads = Vec::with_capacity(AT_ONCE);
for index in 0..AT_ONCE {
let report = report.clone();
threads.push(thread::spawn(move || {
let outcome = (|| -> termlens::Result<()> {
let mut terminal = Terminal::builder()
.size(40, 10)
.env_clear()
.timeout(Duration::from_secs(30))
.arg("-c")
.arg(format!("printf 'terminal {index}\\n'; read _"))
.spawn("/bin/sh")?;
terminal.wait_until(|screen| screen.contains(&format!("terminal {index}")))?;
terminal.send(Key::Enter)?;
terminal.wait_exit()?;
Ok(())
})();
report
.send((index, outcome))
.expect("the collector is alive");
}));
}
drop(report);
let mut failures = Vec::new();
for (index, outcome) in results {
if let Err(error) = outcome {
failures.push(format!("terminal {index}: {error}"));
}
}
for thread in threads {
thread.join().expect("no thread panicked");
}
assert!(
failures.is_empty(),
"{} of {AT_ONCE} terminals failed to run:\n{}",
failures.len(),
failures.join("\n")
);
}
#[test]
fn terminals_recycle_without_running_out_of_devices() {
for round in 0..8 {
let mut open = Vec::new();
for index in 0..6 {
let mut terminal = Terminal::builder()
.size(20, 5)
.env_clear()
.timeout(Duration::from_secs(30))
.arg("-c")
.arg(format!("printf 'round {round} {index}\\n'; read _"))
.spawn("/bin/sh")
.unwrap_or_else(|error| panic!("round {round}, terminal {index}: {error}"));
terminal
.wait_until(|screen| screen.contains(&format!("round {round} {index}")))
.unwrap_or_else(|error| panic!("round {round}, terminal {index}: {error}"));
open.push(terminal);
}
drop(open);
}
}