use adk_code::{
CodeExecutor, ContainerCommandExecutor, ContainerConfig, ExecutionError, ExecutionIsolation,
ExecutionLanguage, ExecutionPayload, ExecutionRequest, GuestModuleFormat, SandboxPolicy,
validate_policy,
};
use proptest::prelude::*;
fn arb_supported_language() -> impl Strategy<Value = ExecutionLanguage> {
prop_oneof![
Just(ExecutionLanguage::Python),
Just(ExecutionLanguage::JavaScript),
Just(ExecutionLanguage::Command),
]
}
fn arb_unsupported_language() -> impl Strategy<Value = ExecutionLanguage> {
prop_oneof![Just(ExecutionLanguage::Rust), Just(ExecutionLanguage::Wasm),]
}
proptest! {
#![proptest_config(ProptestConfig::with_cases(100))]
#[test]
fn prop_container_supports_expected_languages(lang in arb_supported_language()) {
let executor = ContainerCommandExecutor::default();
prop_assert!(
executor.supports_language(&lang),
"container should support {lang}"
);
}
#[test]
fn prop_container_rejects_unsupported_languages(lang in arb_unsupported_language()) {
let executor = ContainerCommandExecutor::default();
prop_assert!(
!executor.supports_language(&lang),
"container should not support {lang}"
);
}
#[test]
fn prop_container_enforces_all_strict_policies(_seed in 0u32..100) {
let executor = ContainerCommandExecutor::default();
let caps = executor.capabilities();
let policy = SandboxPolicy::strict_rust();
let result = validate_policy(&caps, &policy);
prop_assert!(result.is_ok(), "container should enforce strict policies: {:?}", result);
}
#[test]
fn prop_container_rejects_guest_module_payloads(code_len in 1usize..50) {
let executor = ContainerCommandExecutor::default();
let bytes = vec![0u8; code_len];
let request = ExecutionRequest {
language: ExecutionLanguage::Python,
payload: ExecutionPayload::GuestModule {
format: GuestModuleFormat::Wasm,
bytes,
},
argv: vec![],
stdin: None,
input: None,
sandbox: SandboxPolicy::strict_rust(),
identity: None,
};
let rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(executor.execute(request));
prop_assert!(result.is_err());
match result.unwrap_err() {
ExecutionError::InvalidRequest(msg) => {
prop_assert!(
msg.contains("guest module") || msg.contains("GuestModule"),
"error should mention guest modules: {msg}"
);
}
other => prop_assert!(false, "expected InvalidRequest, got: {other}"),
}
}
#[test]
fn prop_container_rejects_empty_source(whitespace in "[ \t\n]{0,20}") {
let executor = ContainerCommandExecutor::default();
let request = ExecutionRequest {
language: ExecutionLanguage::Python,
payload: ExecutionPayload::Source { code: whitespace },
argv: vec![],
stdin: None,
input: None,
sandbox: SandboxPolicy::strict_rust(),
identity: None,
};
let rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(executor.execute(request));
prop_assert!(result.is_err());
match result.unwrap_err() {
ExecutionError::InvalidRequest(msg) => {
prop_assert!(msg.contains("empty"), "error should mention empty: {msg}");
}
other => prop_assert!(false, "expected InvalidRequest, got: {other}"),
}
}
}
#[test]
fn container_isolation_is_container_ephemeral() {
let executor = ContainerCommandExecutor::default();
let caps = executor.capabilities();
assert_eq!(caps.isolation, ExecutionIsolation::ContainerEphemeral);
}
#[test]
fn container_claims_all_policy_enforcement() {
let executor = ContainerCommandExecutor::default();
let caps = executor.capabilities();
assert!(caps.enforce_network_policy);
assert!(caps.enforce_filesystem_policy);
assert!(caps.enforce_environment_policy);
assert!(caps.enforce_timeout);
}
#[test]
fn container_supports_process_execution() {
let executor = ContainerCommandExecutor::default();
let caps = executor.capabilities();
assert!(caps.supports_process_execution);
}
#[test]
fn container_isolation_differs_from_host_local() {
let container_caps = ContainerCommandExecutor::default().capabilities();
let host_caps = adk_code::RustSandboxExecutor::default().capabilities();
assert_ne!(container_caps.isolation, host_caps.isolation);
assert_eq!(container_caps.isolation, ExecutionIsolation::ContainerEphemeral);
assert_eq!(host_caps.isolation, ExecutionIsolation::HostLocal);
assert!(container_caps.enforce_network_policy);
assert!(!host_caps.enforce_network_policy);
}
#[test]
fn container_isolation_differs_from_in_process() {
let container_caps = ContainerCommandExecutor::default().capabilities();
let wasm_caps = adk_code::WasmGuestExecutor::new().capabilities();
assert_ne!(container_caps.isolation, wasm_caps.isolation);
assert_eq!(container_caps.isolation, ExecutionIsolation::ContainerEphemeral);
assert_eq!(wasm_caps.isolation, ExecutionIsolation::InProcess);
}
#[test]
fn all_three_backends_have_distinct_isolation_classes() {
let rust_iso = adk_code::RustSandboxExecutor::default().capabilities().isolation;
let container_iso = ContainerCommandExecutor::default().capabilities().isolation;
let wasm_iso = adk_code::WasmGuestExecutor::new().capabilities().isolation;
assert_ne!(rust_iso, container_iso);
assert_ne!(container_iso, wasm_iso);
assert_ne!(rust_iso, wasm_iso);
}
#[test]
fn container_backend_name_is_descriptive() {
let executor = ContainerCommandExecutor::default();
assert_eq!(executor.name(), "container-command");
}
#[test]
fn custom_config_is_respected() {
let config = ContainerConfig {
runtime: "podman".to_string(),
default_image: "node:20-slim".to_string(),
extra_flags: vec!["--security-opt=no-new-privileges".to_string()],
auto_remove: false,
};
let executor = ContainerCommandExecutor::new(config);
assert_eq!(executor.name(), "container-command");
}