TestTerminal

Struct TestTerminal 

Source
pub struct TestTerminal { /* private fields */ }
Expand description

A test terminal backed by a pseudo-terminal (PTY).

This provides low-level access to PTY operations for spawning processes, reading output, and sending input.

Implementations§

Source§

impl TestTerminal

Source

pub fn new(width: u16, height: u16) -> Result<Self>

Creates a new test terminal with the specified dimensions.

§Arguments
  • width - Terminal width in columns
  • height - Terminal height in rows
§Errors

Returns an error if:

  • Terminal dimensions are invalid (zero or too large)
  • PTY creation fails
§Example
use ratatui_testlib::TestTerminal;

let terminal = TestTerminal::new(80, 24)?;
Source

pub fn with_buffer_size(self, size: usize) -> Self

Sets the buffer size for read operations.

§Arguments
  • size - Buffer size in bytes
§Example
use ratatui_testlib::TestTerminal;

let mut terminal = TestTerminal::new(80, 24)?
    .with_buffer_size(16384);
Source

pub fn spawn(&mut self, cmd: CommandBuilder) -> Result<()>

Spawns a process in the PTY with default timeout.

§Arguments
  • cmd - Command to spawn
§Errors

Returns an error if:

  • A process is already running
  • Process spawn fails
§Example
use ratatui_testlib::TestTerminal;
use portable_pty::CommandBuilder;

let mut terminal = TestTerminal::new(80, 24)?;
let mut cmd = CommandBuilder::new("ls");
cmd.arg("-la");
terminal.spawn(cmd)?;
Source

pub fn spawn_with_timeout( &mut self, cmd: CommandBuilder, timeout: Duration, ) -> Result<()>

Spawns a process in the PTY with a specified timeout.

This method supports the full CommandBuilder API including arguments, environment variables, and working directory.

§Arguments
  • cmd - Command to spawn (with args, env, cwd configured)
  • timeout - Maximum time to wait for spawn to complete
§Errors

Returns an error if:

  • A process is already running
  • Process spawn fails
  • Spawn operation times out
§Example
use ratatui_testlib::TestTerminal;
use portable_pty::CommandBuilder;
use std::time::Duration;

let mut terminal = TestTerminal::new(80, 24)?;
let mut cmd = CommandBuilder::new("bash");
cmd.arg("-c").arg("echo $TEST_VAR");
cmd.env("TEST_VAR", "hello");
terminal.spawn_with_timeout(cmd, Duration::from_secs(3))?;
Source

pub fn read(&mut self, buf: &mut [u8]) -> Result<usize>

Reads available output from the PTY.

This is a non-blocking read that returns immediately with whatever data is available. Handles EAGAIN/EWOULDBLOCK and EINTR gracefully.

§Arguments
  • buf - Buffer to read into
§Errors

Returns an error if the read operation fails (excluding EAGAIN/EWOULDBLOCK).

§Example
use ratatui_testlib::TestTerminal;

let mut terminal = TestTerminal::new(80, 24)?;
let mut buf = [0u8; 1024];
match terminal.read(&mut buf) {
    Ok(0) => println!("No data available"),
    Ok(n) => println!("Read {} bytes", n),
    Err(e) => eprintln!("Read error: {}", e),
}
Source

pub fn read_timeout( &mut self, buf: &mut [u8], timeout: Duration, ) -> Result<usize>

Reads output from the PTY with a timeout.

This method polls for data until either:

  • Data is available and read
  • The timeout expires
§Arguments
  • buf - Buffer to read into
  • timeout - Maximum time to wait for data
§Errors

Returns an error if:

  • The timeout expires without reading data
  • A read error occurs
§Example
use ratatui_testlib::TestTerminal;
use std::time::Duration;

let mut terminal = TestTerminal::new(80, 24)?;
let mut buf = [0u8; 1024];
let n = terminal.read_timeout(&mut buf, Duration::from_secs(1))?;
println!("Read {} bytes", n);
Source

pub fn read_all(&mut self) -> Result<Vec<u8>>

Reads all available output from the PTY into a buffer.

This method performs buffered reading with a configurable buffer size. It reads until no more data is immediately available.

§Errors

Returns an error if a read operation fails.

§Example
use ratatui_testlib::TestTerminal;

let mut terminal = TestTerminal::new(80, 24)?;
let output = terminal.read_all()?;
println!("Output: {}", String::from_utf8_lossy(&output));
Source

pub fn write(&mut self, data: &[u8]) -> Result<usize>

Writes data to the PTY (sends input to the process).

Handles EINTR (interrupted system calls) gracefully by retrying.

§Arguments
  • data - Data to write
§Errors

Returns an error if the write operation fails.

§Example
use ratatui_testlib::TestTerminal;

let mut terminal = TestTerminal::new(80, 24)?;
terminal.write(b"hello\n")?;
Source

pub fn write_all(&mut self, data: &[u8]) -> Result<()>

Writes all data to the PTY, ensuring the complete buffer is written.

§Arguments
  • data - Data to write
§Errors

Returns an error if the write operation fails.

Source

pub fn resize(&mut self, width: u16, height: u16) -> Result<()>

Resizes the PTY.

§Arguments
  • width - New width in columns
  • height - New height in rows
§Errors

Returns an error if:

  • Dimensions are invalid
  • Resize operation fails
Source

pub fn size(&self) -> (u16, u16)

Returns the current PTY dimensions.

Source

pub fn is_running(&mut self) -> bool

Checks if the child process is still running.

§Example
use ratatui_testlib::TestTerminal;
use portable_pty::CommandBuilder;

let mut terminal = TestTerminal::new(80, 24)?;
let cmd = CommandBuilder::new("sleep");
terminal.spawn(cmd)?;
assert!(terminal.is_running());
Source

pub fn kill(&mut self) -> Result<()>

Kills the child process.

This method first attempts to terminate the process gracefully (SIGTERM), then forcefully kills it (SIGKILL) if needed.

§Errors

Returns an error if no process is running or if the kill operation fails.

§Example
use ratatui_testlib::TestTerminal;
use portable_pty::CommandBuilder;

let mut terminal = TestTerminal::new(80, 24)?;
let cmd = CommandBuilder::new("sleep");
terminal.spawn(cmd)?;
terminal.kill()?;
Source

pub fn wait(&mut self) -> Result<ExitStatus>

Waits for the child process to exit and returns its exit status.

§Errors

Returns an error if no process is running.

§Example
use ratatui_testlib::TestTerminal;
use portable_pty::CommandBuilder;

let mut terminal = TestTerminal::new(80, 24)?;
let mut cmd = CommandBuilder::new("echo");
cmd.arg("hello");
terminal.spawn(cmd)?;
let status = terminal.wait()?;
Source

pub fn wait_timeout(&mut self, timeout: Duration) -> Result<ExitStatus>

Waits for the child process to exit with a timeout.

§Arguments
  • timeout - Maximum time to wait for process exit
§Errors

Returns an error if:

  • No process is running
  • The timeout expires before the process exits
§Example
use ratatui_testlib::TestTerminal;
use portable_pty::CommandBuilder;
use std::time::Duration;

let mut terminal = TestTerminal::new(80, 24)?;
let mut cmd = CommandBuilder::new("echo");
cmd.arg("hello");
terminal.spawn(cmd)?;
let status = terminal.wait_timeout(Duration::from_secs(5))?;
Source

pub fn get_exit_status(&self) -> Option<ExitStatus>

Returns the cached exit status of the child process, if available.

This returns the exit status if the process has already exited. Call is_running() or wait() to update the status.

§Example
use ratatui_testlib::TestTerminal;
use portable_pty::CommandBuilder;

let mut terminal = TestTerminal::new(80, 24)?;
let cmd = CommandBuilder::new("echo");
terminal.spawn(cmd)?;
terminal.wait()?;

if let Some(status) = terminal.get_exit_status() {
    println!("Process exited with status: {:?}", status);
}

Trait Implementations§

Source§

impl Drop for TestTerminal

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> Downcast for T
where T: Any,

Source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
Source§

fn as_any(&self) -> &(dyn Any + 'static)

Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
Source§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.