use anyhow::Result;
use crate::common::{ManifestBuilder, TestProject};
#[tokio::test]
async fn test_transitive_version_conflicts_concurrent() -> Result<()> {
agpm_cli::test_utils::init_test_logging(None);
let project = TestProject::new().await?;
let repo_a = project.create_source_repo("repo_a").await?;
let repo_b = project.create_source_repo("repo_b").await?;
repo_a
.add_resource(
"agents",
"shared-lib",
r#"---
name: Shared Library v1
version: "1.0.0"
---
# Shared Library v1.0.0
This is version 1.0.0 of the shared library.
"#,
)
.await?;
repo_a.commit_all("Add shared lib v1.0.0")?;
repo_a.tag_version("v1.0.0")?;
repo_b
.add_resource(
"agents",
"shared-lib",
r#"---
name: Shared Library v2
version: "2.0.0"
---
# Shared Library v2.0.0
This is version 2.0.0 of the shared library with breaking changes.
"#,
)
.await?;
repo_b.commit_all("Add shared lib v2.0.0")?;
repo_b.tag_version("v2.0.0")?;
for i in 0..5 {
repo_a
.add_resource(
"agents",
&format!("agent-v1-{:02}", i),
format!(
r#"---
dependencies:
agents:
- path: ./shared-lib.md
version: v1.0.0
---
# Agent V1 {:02}
This agent depends on shared-lib v1.0.0.
"#,
i
)
.as_str(),
)
.await?;
repo_b
.add_resource(
"agents",
&format!("agent-v2-{:02}", i),
format!(
r#"---
dependencies:
agents:
- path: ./shared-lib.md
version: v2.0.0
---
# Agent V2 {:02}
This agent depends on shared-lib v2.0.0.
"#,
i
)
.as_str(),
)
.await?;
}
repo_a.commit_all("Add v1 agents")?;
repo_a.tag_version("v1.1.0")?;
repo_b.commit_all("Add v2 agents")?;
repo_b.tag_version("v2.1.0")?;
let repo_a_url = repo_a.bare_file_url(project.sources_path()).await?;
let repo_b_url = repo_b.bare_file_url(project.sources_path()).await?;
let manifest = ManifestBuilder::new()
.add_source("repo_a", &repo_a_url)
.add_source("repo_b", &repo_b_url)
.add_agent("agent-v1-00", |d| {
d.source("repo_a").path("agents/agent-v1-00.md").version("v1.1.0")
})
.add_agent("agent-v2-00", |d| {
d.source("repo_b").path("agents/agent-v2-00.md").version("v2.1.0")
})
.add_agent("shared-lib-v1", |d| {
d.source("repo_a").path("agents/shared-lib.md").version("v1.0.0")
})
.add_agent("shared-lib-v2", |d| {
d.source("repo_b").path("agents/shared-lib.md").version("v2.0.0")
})
.build();
project.write_manifest(&manifest).await?;
let output = project.run_agpm(&["install"])?;
assert!(
!output.success,
"Install should fail due to version conflicts. Stderr: {}",
output.stderr
);
let stderr_lower = output.stderr.to_lowercase();
assert!(
stderr_lower.contains("conflict")
|| stderr_lower.contains("incompatible")
|| stderr_lower.contains("no compatible version")
|| stderr_lower.contains("target path conflicts"),
"Error message should mention conflict. Got: {}",
output.stderr
);
assert!(
stderr_lower.contains("conflict")
|| stderr_lower.contains("overwrite")
|| stderr_lower.contains("same installation path"),
"Error should mention conflict resolution. Got: {}",
output.stderr
);
println!("✅ Concurrent version conflict test passed - conflicts correctly detected");
Ok(())
}
#[tokio::test]
async fn test_concurrent_progress_tracking() -> Result<()> {
agpm_cli::test_utils::init_test_logging(None);
let project = TestProject::new().await?;
let community_repo = project.create_source_repo("community").await?;
for i in 0..30 {
community_repo
.add_resource(
"agents",
&format!("progress-test-{:02}", i),
r#"---
# Progress Test Agent
This agent is part of progress tracking tests.
---
"#,
)
.await?;
}
community_repo.commit_all("Initial commit")?;
community_repo.tag_version("v1.0.0")?;
let source_url = community_repo.bare_file_url(project.sources_path()).await?;
let mut builder = ManifestBuilder::new().add_source("community", &source_url);
for i in 0..30 {
builder = builder.add_standard_agent(
&format!("progress-test-{:02}", i),
"community",
&format!("agents/progress-test-{:02}.md", i),
);
}
let manifest = builder.build();
project.write_manifest(&manifest).await?;
let output = project.run_agpm(&["install", "--verbose"])?;
assert!(output.success, "Install should succeed. Stderr: {}", output.stderr);
let agents_dir = project.project_path().join(".claude/agents/agpm");
let mut installed_count = 0;
let mut entries = tokio::fs::read_dir(&agents_dir).await?;
while let Some(entry) = entries.next_entry().await? {
if entry.file_name().to_string_lossy().starts_with("progress-test-") {
installed_count += 1;
}
}
assert_eq!(
installed_count, 30,
"All 30 progress test agents should be installed (found {})",
installed_count
);
assert!(
output.stderr.contains("Processing")
|| output.stderr.contains("processed")
|| output.stderr.contains("resolved")
|| output.stderr.contains("dependencies"),
"Should show progress information in verbose output"
);
Ok(())
}