Files
2026-05-08 01:59:04 +02:00

297 lines
7.8 KiB
Rust

//! Integration tests for terminal operations.
use dirigent_tools::config::TerminalConfig;
use dirigent_tools::terminal::{
create_terminal, get_terminal_output, kill_terminal, release_terminal,
wait_for_terminal_exit, CreateTerminalRequest, KillTerminalCommandRequest,
ReleaseTerminalRequest, TerminalOutputRequest, WaitForTerminalExitRequest,
};
#[tokio::test]
async fn test_terminal_echo_command() {
let config = TerminalConfig {
enabled: true,
default_cwd: Some(std::env::current_dir().unwrap()),
env_allowlist: vec![],
command_blocklist: vec![],
output_byte_limit: 10_000,
max_runtime_secs: 30,
};
// Create terminal with echo command
#[cfg(windows)]
let request = CreateTerminalRequest {
command: "cmd".to_string(),
args: vec!["/C".to_string(), "echo".to_string(), "Hello World".to_string()],
cwd: None,
env: None,
output_byte_limit: None,
};
#[cfg(not(windows))]
let request = CreateTerminalRequest {
command: "echo".to_string(),
args: vec!["Hello World".to_string()],
cwd: None,
env: None,
output_byte_limit: None,
};
let create_response = create_terminal(request, &config).await.unwrap();
let terminal_id = create_response.terminal_id;
// Wait for command to complete
tokio::time::sleep(tokio::time::Duration::from_millis(500)).await;
// Get output
let output_response = get_terminal_output(
TerminalOutputRequest {
terminal_id: terminal_id.clone(),
},
&config,
)
.await
.unwrap();
assert!(output_response.output.contains("Hello World"));
// Release terminal
let _ = release_terminal(
ReleaseTerminalRequest {
terminal_id: terminal_id.clone(),
},
&config,
)
.await;
}
#[tokio::test]
async fn test_terminal_wait_for_exit() {
let config = TerminalConfig {
enabled: true,
default_cwd: Some(std::env::current_dir().unwrap()),
env_allowlist: vec![],
command_blocklist: vec![],
output_byte_limit: 10_000,
max_runtime_secs: 30,
};
// Create terminal with a quick command
#[cfg(windows)]
let request = CreateTerminalRequest {
command: "cmd".to_string(),
args: vec!["/C".to_string(), "exit".to_string(), "0".to_string()],
cwd: None,
env: None,
output_byte_limit: None,
};
#[cfg(not(windows))]
let request = CreateTerminalRequest {
command: "true".to_string(),
args: vec![],
cwd: None,
env: None,
output_byte_limit: None,
};
let create_response = create_terminal(request, &config).await.unwrap();
let terminal_id = create_response.terminal_id;
// Wait for exit
let wait_response = wait_for_terminal_exit(
WaitForTerminalExitRequest {
terminal_id: terminal_id.clone(),
},
&config,
)
.await
.unwrap();
assert_eq!(wait_response.exit_status, 0);
// Release terminal
let _ = release_terminal(
ReleaseTerminalRequest {
terminal_id: terminal_id.clone(),
},
&config,
)
.await;
}
#[tokio::test]
async fn test_terminal_kill() {
let config = TerminalConfig {
enabled: true,
default_cwd: Some(std::env::current_dir().unwrap()),
env_allowlist: vec![],
command_blocklist: vec![],
output_byte_limit: 10_000,
max_runtime_secs: 30,
};
// Create terminal with a long-running command
#[cfg(windows)]
let request = CreateTerminalRequest {
command: "cmd".to_string(),
args: vec!["/C".to_string(), "timeout".to_string(), "/t".to_string(), "10".to_string()],
cwd: None,
env: None,
output_byte_limit: None,
};
#[cfg(not(windows))]
let request = CreateTerminalRequest {
command: "sleep".to_string(),
args: vec!["10".to_string()],
cwd: None,
env: None,
output_byte_limit: None,
};
let create_response = create_terminal(request, &config).await.unwrap();
let terminal_id = create_response.terminal_id;
// Wait a bit to ensure process is running
tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
// Kill the terminal
let kill_response = kill_terminal(
KillTerminalCommandRequest {
terminal_id: terminal_id.clone(),
},
&config,
)
.await;
assert!(kill_response.is_ok());
// Release terminal
let _ = release_terminal(
ReleaseTerminalRequest {
terminal_id: terminal_id.clone(),
},
&config,
)
.await;
}
#[tokio::test]
async fn test_terminal_disabled() {
let config = TerminalConfig {
enabled: false,
default_cwd: Some(std::env::current_dir().unwrap()),
env_allowlist: vec![],
command_blocklist: vec![],
output_byte_limit: 10_000,
max_runtime_secs: 30,
};
let request = CreateTerminalRequest {
command: "echo".to_string(),
args: vec!["test".to_string()],
cwd: None,
env: None,
output_byte_limit: None,
};
let result = create_terminal(request, &config).await;
assert!(result.is_err());
}
#[tokio::test]
async fn test_terminal_command_blocklist() {
let config = TerminalConfig {
enabled: true,
default_cwd: Some(std::env::current_dir().unwrap()),
env_allowlist: vec![],
command_blocklist: vec!["rm".to_string(), "del".to_string()],
output_byte_limit: 10_000,
max_runtime_secs: 30,
};
let request = CreateTerminalRequest {
command: "rm".to_string(),
args: vec!["-rf".to_string(), "/".to_string()],
cwd: None,
env: None,
output_byte_limit: None,
};
let result = create_terminal(request, &config).await;
assert!(result.is_err());
}
#[tokio::test]
async fn test_terminal_output_truncation() {
let config = TerminalConfig {
enabled: true,
default_cwd: Some(std::env::current_dir().unwrap()),
env_allowlist: vec![],
command_blocklist: vec![],
output_byte_limit: 100, // Very small buffer
max_runtime_secs: 30,
};
// Create terminal that generates lots of output
#[cfg(windows)]
let request = CreateTerminalRequest {
command: "cmd".to_string(),
args: vec![
"/C".to_string(),
"for".to_string(),
"/L".to_string(),
"%i".to_string(),
"in".to_string(),
"(1,1,100)".to_string(),
"do".to_string(),
"@echo".to_string(),
"Line %i".to_string(),
],
cwd: None,
env: None,
output_byte_limit: Some(100),
};
#[cfg(not(windows))]
let request = CreateTerminalRequest {
command: "sh".to_string(),
args: vec![
"-c".to_string(),
"for i in $(seq 1 100); do echo Line $i; done".to_string(),
],
cwd: None,
env: None,
output_byte_limit: Some(100),
};
let create_response = create_terminal(request, &config).await.unwrap();
let terminal_id = create_response.terminal_id;
// Wait for command to complete
tokio::time::sleep(tokio::time::Duration::from_millis(1000)).await;
// Get output
let output_response = get_terminal_output(
TerminalOutputRequest {
terminal_id: terminal_id.clone(),
},
&config,
)
.await
.unwrap();
// Buffer should be truncated
assert!(output_response.truncated || output_response.output.len() <= 100);
// Release terminal
let _ = release_terminal(
ReleaseTerminalRequest {
terminal_id: terminal_id.clone(),
},
&config,
)
.await;
}