use acpr::{Agent, BinaryDist, ForceOption, download_binary, fetch_registry, get_platform};
use std::collections::HashMap;
use std::path::PathBuf;
use tempfile::TempDir;
#[tokio::test]
async fn test_fetch_custom_registry() {
let temp_dir = TempDir::new().unwrap();
let cache_dir = temp_dir.path().to_path_buf();
let registry_path = PathBuf::from("tests/fixtures/test-registry.json");
let registry = fetch_registry(&cache_dir, None, Some(®istry_path))
.await
.unwrap();
assert_eq!(registry.agents.len(), 3);
assert_eq!(registry.agents[0].id, "test-npx-agent");
assert_eq!(registry.agents[1].id, "test-binary-agent");
assert_eq!(registry.agents[2].id, "test-versioned-npx-agent");
}
#[tokio::test]
async fn test_registry_caching() {
let temp_dir = TempDir::new().unwrap();
let cache_dir = temp_dir.path().to_path_buf();
let registry1 = fetch_registry(&cache_dir, None, None).await.unwrap();
assert!(!registry1.agents.is_empty());
assert!(cache_dir.join("registry.json").exists());
assert!(cache_dir.join("registry_cache.json").exists());
let registry2 = fetch_registry(&cache_dir, None, None).await.unwrap();
assert_eq!(registry1.agents.len(), registry2.agents.len());
}
#[tokio::test]
async fn test_force_registry_refresh() {
let temp_dir = TempDir::new().unwrap();
let cache_dir = temp_dir.path().to_path_buf();
let _registry1 = fetch_registry(&cache_dir, None, None).await.unwrap();
let registry2 = fetch_registry(&cache_dir, Some(&ForceOption::Registry), None)
.await
.unwrap();
assert!(!registry2.agents.is_empty());
}
#[test]
fn test_platform_detection() {
let platform = get_platform();
assert!(
platform.contains("darwin") || platform.contains("linux") || platform.contains("windows")
);
assert!(platform.contains("aarch64") || platform.contains("x86_64"));
}
#[tokio::test]
async fn test_binary_caching() {
let temp_dir = TempDir::new().unwrap();
let cache_dir = temp_dir.path().to_path_buf();
let agent = Agent {
id: "test-agent".to_string(),
distribution: acpr::Distribution {
binary: {
let mut map = HashMap::new();
map.insert(
"darwin-aarch64".to_string(),
BinaryDist {
archive: "https://httpbin.org/base64/aGVsbG8gd29ybGQ=".to_string(),
cmd: "./test-binary".to_string(),
args: vec![],
},
);
map
},
npx: None,
uvx: None,
},
};
let binary_dist = &agent.distribution.binary["darwin-aarch64"];
let binary_path1 = download_binary(&agent, binary_dist, &cache_dir, None).await;
if binary_path1.is_ok() {
let path1 = binary_path1.unwrap();
assert!(path1.exists());
let content = tokio::fs::read_to_string(&path1).await.unwrap();
assert_eq!(content, "hello world");
let binary_path2 = download_binary(&agent, binary_dist, &cache_dir, None)
.await
.unwrap();
assert_eq!(path1, binary_path2);
let binary_path3 =
download_binary(&agent, binary_dist, &cache_dir, Some(&ForceOption::Binary))
.await
.unwrap();
assert_eq!(path1, binary_path3);
}
}
#[test]
fn test_versioned_package_handling() {
let versioned_package = "@google/gemini-cli@0.38.2";
let unversioned_package = "cowsay";
let versioned_arg =
if versioned_package.contains('@') && versioned_package.matches('@').count() > 1 {
versioned_package.to_string()
} else {
format!("{}@latest", versioned_package)
};
let unversioned_arg =
if unversioned_package.contains('@') && unversioned_package.matches('@').count() > 1 {
unversioned_package.to_string()
} else {
format!("{}@latest", unversioned_package)
};
assert_eq!(versioned_arg, "@google/gemini-cli@0.38.2");
assert_eq!(unversioned_arg, "cowsay@latest");
}
async fn test_agent_sacp_integration(agent_name: &str) -> Result<(), Box<dyn std::error::Error>> {
if std::env::var("ACPR_SKIP_AGENT").is_ok() {
return Ok(());
}
let _ = tracing_subscriber::fmt()
.with_writer(std::io::stderr)
.with_env_filter(
tracing_subscriber::EnvFilter::try_from_default_env()
.unwrap_or_else(|_| tracing_subscriber::EnvFilter::new("off")),
)
.try_init();
use acpr::Acpr;
use agent_client_protocol::{
Client,
schema::{InitializeRequest, ProtocolVersion},
};
use std::time::Duration;
use tracing::info;
info!("Testing sacp integration with agent: {}", agent_name);
let agent = Acpr::new(agent_name);
info!("Created Acpr instance for {} agent", agent_name);
let result = tokio::time::timeout(Duration::from_secs(30), async {
Client
.builder()
.name("acpr-test-client")
.connect_with(agent, async |cx| {
info!("Connected to agent, initializing...");
info!("Sending initialize request...");
let init_response = cx
.send_request(InitializeRequest::new(ProtocolVersion::LATEST))
.block_task()
.await?;
info!("Initialization complete: {:?}", init_response);
Ok(())
})
.await
})
.await;
match result {
Ok(Ok(())) => {
info!(
"Agent {} integration test completed successfully",
agent_name
);
Ok(())
}
Ok(Err(e)) => Err(format!("Agent {} integration test failed: {}", agent_name, e).into()),
Err(_) => Err(format!(
"Agent {} integration test timed out after 30 seconds",
agent_name
)
.into()),
}
}
#[tokio::test]
async fn test_amp_acp_integration() {
test_agent_sacp_integration("amp-acp")
.await
.expect("amp-acp integration test failed");
}
#[tokio::test]
async fn test_claude_integration() {
test_agent_sacp_integration("claude-acp")
.await
.expect("claude-acp integration test failed");
}
#[tokio::test]
async fn test_uvx_agent_basic() {
if std::env::var("ACPR_SKIP_AGENT").is_ok() {
return;
}
use acpr::Acpr;
use std::time::Duration;
use tokio::io;
let agent = Acpr::new("fast-agent");
let (stdin_read, stdout_write) = tokio::io::duplex(1024);
let result = tokio::time::timeout(Duration::from_secs(5), async {
drop(stdin_read); agent.run_with_streams(io::empty(), stdout_write).await
})
.await;
match result {
Ok(Ok(())) => {
}
Ok(Err(_)) => {
}
Err(_) => {
panic!("uvx agent test timed out - agent may not be starting properly");
}
}
}