#![cfg(unix)]
use std::time::Duration;
use rust_expect::{QuickSession, SessionBuilder};
#[test]
fn session_builder_creates_config() {
let config = SessionBuilder::new()
.command("/bin/echo")
.arg("hello world")
.timeout(Duration::from_secs(5))
.build();
assert_eq!(config.command, "/bin/echo");
assert_eq!(config.args, vec!["hello world"]);
assert_eq!(config.timeout.default, Duration::from_secs(5));
}
#[test]
fn session_builder_with_env() {
let config = SessionBuilder::new()
.command("/bin/sh")
.arg("-c")
.arg("echo $TEST_VAR")
.env("TEST_VAR", "test_value")
.build();
assert!(config.env.contains_key("TEST_VAR"));
assert_eq!(config.env.get("TEST_VAR"), Some(&"test_value".to_string()));
}
#[tokio::test]
async fn env_vars_reach_child_process() {
use rust_expect::Session;
let config = SessionBuilder::new()
.command("/bin/sh")
.arg("-c")
.arg("printf 'value=%s\\n' \"$RUST_EXPECT_TEST_VAR\"; exit 0")
.env("RUST_EXPECT_TEST_VAR", "smelt-pinecone-42")
.timeout(Duration::from_secs(5))
.build();
let mut session = Session::spawn_with_config(
"/bin/sh",
&[
"-c",
"printf 'value=%s\\n' \"$RUST_EXPECT_TEST_VAR\"; exit 0",
],
config,
)
.await
.expect("spawn should succeed");
let m = session
.expect_timeout("value=smelt-pinecone-42", Duration::from_secs(3))
.await
.expect("expected child to receive RUST_EXPECT_TEST_VAR=smelt-pinecone-42");
assert!(m.matched.contains("smelt-pinecone-42"));
session.wait_timeout(Duration::from_secs(2)).await.ok();
}
#[tokio::test]
async fn parent_env_inherited_when_no_overrides() {
use rust_expect::Session;
#[allow(unsafe_code)]
unsafe {
std::env::set_var("RUST_EXPECT_PARENT_PROBE", "from-parent");
}
let config = SessionBuilder::new()
.command("/bin/sh")
.arg("-c")
.arg("printf 'probe=%s\\n' \"$RUST_EXPECT_PARENT_PROBE\"; exit 0")
.timeout(Duration::from_secs(5))
.build();
let mut session = Session::spawn_with_config(
"/bin/sh",
&[
"-c",
"printf 'probe=%s\\n' \"$RUST_EXPECT_PARENT_PROBE\"; exit 0",
],
config,
)
.await
.expect("spawn should succeed");
let m = session
.expect_timeout("probe=from-parent", Duration::from_secs(3))
.await
.expect("expected child to inherit RUST_EXPECT_PARENT_PROBE=from-parent");
assert!(m.matched.contains("from-parent"));
session.wait_timeout(Duration::from_secs(2)).await.ok();
}
#[test]
fn session_builder_with_dimensions() {
let config = SessionBuilder::new()
.command("/bin/sh")
.dimensions(120, 40)
.build();
assert_eq!(config.dimensions, (120, 40));
}
#[test]
fn quick_session_bash_config() {
let config = QuickSession::bash();
assert_eq!(config.command, "/bin/bash");
assert!(config.args.contains(&"--norc".to_string()));
assert!(config.args.contains(&"--noprofile".to_string()));
}
#[test]
fn quick_session_shell_config() {
let config = QuickSession::shell();
assert!(!config.command.is_empty());
}
#[test]
fn quick_session_ssh_config() {
let config = QuickSession::ssh("example.com");
assert_eq!(config.command, "ssh");
assert!(config.args.contains(&"example.com".to_string()));
assert_eq!(config.timeout.default, Duration::from_secs(30));
}
#[test]
fn quick_session_ssh_user_config() {
let config = QuickSession::ssh_user("admin", "server.example.com");
assert_eq!(config.command, "ssh");
assert!(
config
.args
.contains(&"admin@server.example.com".to_string())
);
}
#[test]
fn quick_session_python_config() {
let config = QuickSession::python();
assert_eq!(config.command, "python3");
assert!(config.args.contains(&"-i".to_string()));
}
#[test]
fn quick_session_telnet_config() {
let config = QuickSession::telnet("host.example.com", 23);
assert_eq!(config.command, "telnet");
assert!(config.args.contains(&"host.example.com".to_string()));
assert!(config.args.contains(&"23".to_string()));
}
#[test]
fn session_builder_working_dir() {
let config = SessionBuilder::new()
.command("/bin/pwd")
.working_directory("/tmp")
.build();
assert_eq!(config.working_dir, Some("/tmp".into()));
}
#[test]
fn session_builder_line_endings() {
use rust_expect::LineEnding;
let config_unix = SessionBuilder::new()
.command("test")
.unix_line_endings()
.build();
assert!(matches!(config_unix.line_ending, LineEnding::Lf));
let config_windows = SessionBuilder::new()
.command("test")
.windows_line_endings()
.build();
assert!(matches!(config_windows.line_ending, LineEnding::CrLf));
}
#[test]
fn session_builder_buffer_size() {
let config = SessionBuilder::new()
.command("test")
.buffer_max_size(1024 * 1024)
.build();
assert_eq!(config.buffer.max_size, 1024 * 1024);
}
#[test]
fn session_builder_logging() {
let config = SessionBuilder::new()
.command("test")
.log_to_file("/tmp/test.log")
.build();
assert_eq!(config.logging.log_file, Some("/tmp/test.log".into()));
}
use rust_expect::Session;
#[tokio::test]
async fn spawn_echo_command() {
let mut session = Session::spawn("/bin/echo", &["hello", "world"])
.await
.expect("Failed to spawn echo");
let m = session.expect("world").await.expect("Expected 'world'");
assert!(m.matched.contains("world"));
}
#[tokio::test]
async fn spawn_shell_send_command() {
let mut session = Session::spawn("/bin/sh", &[])
.await
.expect("Failed to spawn shell");
session
.send_line("echo test123")
.await
.expect("Failed to send");
let m = session.expect("test123").await.expect("Expected 'test123'");
assert!(m.matched.contains("test123"));
}
#[tokio::test]
async fn spawn_cat_interactive() {
let mut session = Session::spawn("/bin/cat", &[])
.await
.expect("Failed to spawn cat");
session
.send_line("hello cat")
.await
.expect("Failed to send");
let m = session
.expect("hello cat")
.await
.expect("Expected 'hello cat'");
assert!(m.matched.contains("hello cat"));
session
.send_control(rust_expect::ControlChar::CtrlD)
.await
.expect("Failed to send EOF");
}
#[tokio::test]
async fn spawn_has_pid() {
let session = Session::spawn("/bin/true", &[])
.await
.expect("Failed to spawn true");
let pid = session.pid();
assert!(pid > 0, "Expected valid PID, got {pid}");
}
#[tokio::test]
async fn spawn_with_custom_config() {
use rust_expect::SessionConfig;
let config = SessionConfig {
dimensions: (100, 30),
..SessionConfig::default()
};
let session = Session::spawn_with_config("/bin/sh", &[], config)
.await
.expect("Failed to spawn with config");
let pid = session.pid();
assert!(pid > 0);
}
#[tokio::test]
async fn spawn_nonexistent_command() {
let result = Session::spawn("/nonexistent/command", &[]).await;
assert!(result.is_ok() || result.is_err());
}
#[tokio::test]
async fn spawn_send_control_c() {
let mut session = Session::spawn("/bin/cat", &[])
.await
.expect("Failed to spawn cat");
session
.send_control(rust_expect::ControlChar::CtrlC)
.await
.expect("Failed to send Ctrl-C");
let result = session.wait_timeout(Duration::from_secs(5)).await;
assert!(
result.is_ok() || result.is_err(),
"wait_timeout should return a result"
);
}
#[tokio::test]
async fn spawn_expect_multiple() {
let mut session = Session::spawn("/bin/sh", &[])
.await
.expect("Failed to spawn shell");
session
.send_line("echo first; echo second")
.await
.expect("Failed to send");
session.expect("first").await.expect("Expected 'first'");
session.expect("second").await.expect("Expected 'second'");
}
#[tokio::test]
async fn spawn_match_contains_text() {
let mut session = Session::spawn("/bin/echo", &["hello", "world"])
.await
.expect("Failed to spawn echo");
let m = session.expect("hello").await.expect("Expected 'hello'");
assert!(m.matched.contains("hello"), "Match should contain 'hello'");
}