use sombrax_agentic_core::tools::context::ToolContext;
use sombrax_agentic_core::tools::registry::Tool;
use sombrax_agentic_core::tools::shell::{BashArgs, BashTool};
use tempfile::TempDir;
fn create_test_context() -> (TempDir, ToolContext) {
let temp_dir = TempDir::new().unwrap();
let ctx = ToolContext::new("test-session".to_string(), temp_dir.path().to_path_buf());
(temp_dir, ctx)
}
#[tokio::test]
async fn test_bash_tool_definition() {
let (_temp_dir, ctx) = create_test_context();
let tool = BashTool::new(ctx);
let def = tool.definition("".to_string()).await;
assert_eq!(def.name, "bash");
assert!(!def.description.is_empty());
}
#[tokio::test]
async fn test_bash_tool_simple_command() {
let (_temp_dir, ctx) = create_test_context();
let tool = BashTool::new(ctx);
let result = tool
.call(BashArgs {
command: "echo 'Hello, World!'".to_string(),
timeout: None,
description: Some("Echo test".to_string()),
})
.await;
assert!(result.is_ok());
let output = result.unwrap();
assert!(output.success);
assert!(output.stdout.contains("Hello, World!"));
}
#[tokio::test]
async fn test_bash_tool_with_exit_code() {
let (_temp_dir, ctx) = create_test_context();
let tool = BashTool::new(ctx);
let result = tool
.call(BashArgs {
command: "exit 0".to_string(),
timeout: None,
description: None,
})
.await;
assert!(result.is_ok());
let output = result.unwrap();
assert!(output.success);
assert_eq!(output.exit_code, 0);
}
#[tokio::test]
async fn test_bash_tool_failed_command() {
let (_temp_dir, ctx) = create_test_context();
let tool = BashTool::new(ctx);
let result = tool
.call(BashArgs {
command: "exit 1".to_string(),
timeout: None,
description: None,
})
.await;
assert!(result.is_ok());
let output = result.unwrap();
assert!(!output.success);
assert_eq!(output.exit_code, 1);
}
#[tokio::test]
async fn test_bash_tool_stderr() {
let (_temp_dir, ctx) = create_test_context();
let tool = BashTool::new(ctx);
let result = tool
.call(BashArgs {
command: "echo 'error' >&2".to_string(),
timeout: None,
description: None,
})
.await;
assert!(result.is_ok());
let output = result.unwrap();
assert!(output.stderr.contains("error"));
}
#[tokio::test]
async fn test_bash_tool_working_directory() {
let (_temp_dir, ctx) = create_test_context();
let tool = BashTool::new(ctx);
let result = tool
.call(BashArgs {
command: "pwd".to_string(),
timeout: None,
description: None,
})
.await;
assert!(result.is_ok());
let output = result.unwrap();
assert!(!output.stdout.trim().is_empty());
}
#[tokio::test]
async fn test_bash_tool_with_timeout() {
let (_temp_dir, ctx) = create_test_context();
let tool = BashTool::new(ctx);
let result = tool
.call(BashArgs {
command: "echo 'quick'".to_string(),
timeout: Some(5000), description: None,
})
.await;
assert!(result.is_ok());
let output = result.unwrap();
assert!(output.success);
}
#[tokio::test]
async fn test_bash_tool_dangerous_command_rejected() {
let (_temp_dir, ctx) = create_test_context();
let tool = BashTool::new(ctx);
let result = tool
.call(BashArgs {
command: "rm -rf /".to_string(),
timeout: None,
description: None,
})
.await;
assert!(result.is_err());
}
#[tokio::test]
async fn test_bash_tool_multiline_output() {
let (_temp_dir, ctx) = create_test_context();
let tool = BashTool::new(ctx);
let result = tool
.call(BashArgs {
command: "echo 'line1'; echo 'line2'; echo 'line3'".to_string(),
timeout: None,
description: None,
})
.await;
assert!(result.is_ok());
let output = result.unwrap();
assert!(output.stdout.contains("line1"));
assert!(output.stdout.contains("line2"));
assert!(output.stdout.contains("line3"));
}
#[tokio::test]
async fn test_bash_tool_html_entity_decoding() {
let (_temp_dir, ctx) = create_test_context();
let tool = BashTool::new(ctx);
let result = tool
.call(BashArgs {
command: "echo 'hello' && echo 'world'".to_string(),
timeout: None,
description: Some("Test HTML entity decoding".to_string()),
})
.await;
assert!(result.is_ok());
let output = result.unwrap();
assert!(output.success);
assert!(output.stdout.contains("hello"));
assert!(output.stdout.contains("world"));
}
#[tokio::test]
async fn test_bash_tool_html_entity_quotes() {
let (_temp_dir, ctx) = create_test_context();
let tool = BashTool::new(ctx);
let result = tool
.call(BashArgs {
command: "echo "quoted text"".to_string(),
timeout: None,
description: None,
})
.await;
assert!(result.is_ok());
let output = result.unwrap();
assert!(output.success);
assert!(output.stdout.contains("quoted text"));
}
#[tokio::test]
async fn test_bash_tool_dangerous_command_with_html_entities_rejected() {
let (_temp_dir, ctx) = create_test_context();
let tool = BashTool::new(ctx);
let result = tool
.call(BashArgs {
command: "rm -rf / && echo done".to_string(),
timeout: None,
description: None,
})
.await;
assert!(result.is_err());
}