
- Remove Rust formatting check from CI workflow since formatting is now applied - Standardize import ordering and organization throughout codebase - Fix indentation, spacing, and line breaks for consistency - Clean up trailing whitespace and formatting inconsistencies - Apply rustfmt to all Rust source files including checkpoint, sandbox, commands, and test modules This establishes a consistent code style baseline for the project.
147 lines
5.0 KiB
Rust
147 lines
5.0 KiB
Rust
//! Unit tests for SandboxExecutor
|
|
use claudia_lib::sandbox::executor::{should_activate_sandbox, SandboxExecutor};
|
|
use gaol::profile::{AddressPattern, Operation, PathPattern, Profile};
|
|
use std::env;
|
|
use std::path::PathBuf;
|
|
|
|
/// Create a simple test profile
|
|
fn create_test_profile(project_path: PathBuf) -> Profile {
|
|
let operations = vec![
|
|
Operation::FileReadAll(PathPattern::Subpath(project_path)),
|
|
Operation::NetworkOutbound(AddressPattern::All),
|
|
];
|
|
|
|
Profile::new(operations).expect("Failed to create test profile")
|
|
}
|
|
|
|
#[test]
|
|
fn test_executor_creation() {
|
|
let project_path = PathBuf::from("/test/project");
|
|
let profile = create_test_profile(project_path.clone());
|
|
|
|
let _executor = SandboxExecutor::new(profile, project_path);
|
|
// Executor should be created successfully
|
|
}
|
|
|
|
#[test]
|
|
fn test_should_activate_sandbox_env_var() {
|
|
// Test when env var is not set
|
|
env::remove_var("GAOL_SANDBOX_ACTIVE");
|
|
assert!(
|
|
!should_activate_sandbox(),
|
|
"Should not activate when env var is not set"
|
|
);
|
|
|
|
// Test when env var is set to "1"
|
|
env::set_var("GAOL_SANDBOX_ACTIVE", "1");
|
|
assert!(
|
|
should_activate_sandbox(),
|
|
"Should activate when env var is '1'"
|
|
);
|
|
|
|
// Test when env var is set to other value
|
|
env::set_var("GAOL_SANDBOX_ACTIVE", "0");
|
|
assert!(
|
|
!should_activate_sandbox(),
|
|
"Should not activate when env var is not '1'"
|
|
);
|
|
|
|
// Clean up
|
|
env::remove_var("GAOL_SANDBOX_ACTIVE");
|
|
}
|
|
|
|
#[test]
|
|
fn test_prepare_sandboxed_command() {
|
|
let project_path = PathBuf::from("/test/project");
|
|
let profile = create_test_profile(project_path.clone());
|
|
let executor = SandboxExecutor::new(profile, project_path.clone());
|
|
|
|
let _cmd = executor.prepare_sandboxed_command("echo", &["hello"], &project_path);
|
|
|
|
// The command should have sandbox environment variables set
|
|
// Note: We can't easily test Command internals, but we can verify it doesn't panic
|
|
}
|
|
|
|
#[test]
|
|
fn test_executor_with_empty_profile() {
|
|
let project_path = PathBuf::from("/test/project");
|
|
let profile = Profile::new(vec![]).expect("Failed to create empty profile");
|
|
|
|
let executor = SandboxExecutor::new(profile, project_path.clone());
|
|
let _cmd = executor.prepare_sandboxed_command("echo", &["test"], &project_path);
|
|
|
|
// Should handle empty profile gracefully
|
|
}
|
|
|
|
#[test]
|
|
fn test_executor_with_complex_profile() {
|
|
let project_path = PathBuf::from("/test/project");
|
|
let operations = vec![
|
|
Operation::FileReadAll(PathPattern::Subpath(project_path.clone())),
|
|
Operation::FileReadAll(PathPattern::Subpath(PathBuf::from("/usr/lib"))),
|
|
Operation::FileReadAll(PathPattern::Literal(PathBuf::from("/etc/hosts"))),
|
|
Operation::FileReadMetadata(PathPattern::Subpath(PathBuf::from("/"))),
|
|
Operation::NetworkOutbound(AddressPattern::All),
|
|
Operation::NetworkOutbound(AddressPattern::Tcp(443)),
|
|
Operation::SystemInfoRead,
|
|
];
|
|
|
|
// Only create profile with supported operations
|
|
let filtered_ops: Vec<_> = operations
|
|
.into_iter()
|
|
.filter(|op| {
|
|
use gaol::profile::{OperationSupport, OperationSupportLevel};
|
|
matches!(op.support(), OperationSupportLevel::CanBeAllowed)
|
|
})
|
|
.collect();
|
|
|
|
if !filtered_ops.is_empty() {
|
|
let profile = Profile::new(filtered_ops).expect("Failed to create complex profile");
|
|
let executor = SandboxExecutor::new(profile, project_path.clone());
|
|
let _cmd = executor.prepare_sandboxed_command("echo", &["test"], &project_path);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn test_command_environment_setup() {
|
|
let project_path = PathBuf::from("/test/project");
|
|
let profile = create_test_profile(project_path.clone());
|
|
let executor = SandboxExecutor::new(profile, project_path.clone());
|
|
|
|
// Test with various arguments
|
|
let _cmd1 = executor.prepare_sandboxed_command("ls", &[], &project_path);
|
|
let _cmd2 = executor.prepare_sandboxed_command("cat", &["file.txt"], &project_path);
|
|
let _cmd3 = executor.prepare_sandboxed_command("grep", &["-r", "pattern", "."], &project_path);
|
|
|
|
// Commands should be prepared without panic
|
|
}
|
|
|
|
#[test]
|
|
#[cfg(unix)]
|
|
fn test_spawn_sandboxed_process() {
|
|
use crate::sandbox::common::is_sandboxing_supported;
|
|
|
|
if !is_sandboxing_supported() {
|
|
return;
|
|
}
|
|
|
|
let project_path = env::current_dir().unwrap_or_else(|_| PathBuf::from("/tmp"));
|
|
let profile = create_test_profile(project_path.clone());
|
|
let executor = SandboxExecutor::new(profile, project_path.clone());
|
|
|
|
// Try to spawn a simple command
|
|
let result = executor.execute_sandboxed_spawn("echo", &["sandbox test"], &project_path);
|
|
|
|
// On supported platforms, this should either succeed or fail gracefully
|
|
match result {
|
|
Ok(mut child) => {
|
|
// If spawned successfully, wait for it to complete
|
|
let _ = child.wait();
|
|
}
|
|
Err(e) => {
|
|
// Sandboxing might fail due to permissions or platform limitations
|
|
println!("Sandbox spawn failed (expected in some environments): {e}");
|
|
}
|
|
}
|
|
}
|