sync from monorepo @ 2452e92e
This commit is contained in:
@@ -0,0 +1,296 @@
|
||||
//! 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;
|
||||
}
|
||||
Reference in New Issue
Block a user