aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe/tests/dependency_resolver
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-06-24 00:47:20 +0900
committernsfisis <nsfisis@gmail.com>2026-06-24 00:47:53 +0900
commit340164c64e90d44b1bdf620b514166db1f76cc98 (patch)
tree86195fe5ff8582b64e0324e9f40619e36c04948f /crates/shirabe/tests/dependency_resolver
parent8fe3390d064303b86133a1d2983144a4818a7121 (diff)
downloadphp-shirabe-340164c64e90d44b1bdf620b514166db1f76cc98.tar.gz
php-shirabe-340164c64e90d44b1bdf620b514166db1f76cc98.tar.zst
php-shirabe-340164c64e90d44b1bdf620b514166db1f76cc98.zip
test: port more unimplemented tests
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Diffstat (limited to 'crates/shirabe/tests/dependency_resolver')
-rw-r--r--crates/shirabe/tests/dependency_resolver/default_policy_test.rs208
-rw-r--r--crates/shirabe/tests/dependency_resolver/security_advisory_pool_filter_test.rs317
-rw-r--r--crates/shirabe/tests/dependency_resolver/solver_test.rs8
3 files changed, 513 insertions, 20 deletions
diff --git a/crates/shirabe/tests/dependency_resolver/default_policy_test.rs b/crates/shirabe/tests/dependency_resolver/default_policy_test.rs
index 776de6c..fafe0e2 100644
--- a/crates/shirabe/tests/dependency_resolver/default_policy_test.rs
+++ b/crates/shirabe/tests/dependency_resolver/default_policy_test.rs
@@ -3,6 +3,7 @@
use indexmap::IndexMap;
use shirabe::dependency_resolver::PolicyInterface;
use shirabe::dependency_resolver::default_policy::DefaultPolicy;
+use shirabe::package::Link;
use shirabe::package::handle::{CompleteAliasPackageHandle, CompletePackageHandle};
use shirabe::repository::array_repository::ArrayRepository;
use shirabe::repository::handle::{LockArrayRepositoryHandle, RepositoryInterfaceHandle};
@@ -556,28 +557,217 @@ fn test_select_local_repos_first() {
assert_eq!(expected, selected);
}
-#[ignore = "set_provides/set_replaces only exist on RootPackage handles; CompletePackage from get_package has no set_provides"]
+/// PHP `new Link($source, $target, $constraint, $type)`: prettyConstraint defaults to
+/// `(string) $constraint`.
+fn link(source: &str, target: &str, constraint: AnyConstraint, r#type: &str) -> Link {
+ let pretty = constraint.get_pretty_string();
+ Link::new(
+ source.to_string(),
+ target.to_string(),
+ constraint,
+ Some(r#type.to_string()),
+ pretty,
+ )
+}
+
+fn as_complete(
+ package: &shirabe::package::handle::PackageInterfaceHandle,
+) -> CompletePackageHandle {
+ CompletePackageHandle::from_rc_unchecked(package.as_rc().clone())
+}
+
+fn constraint(operator: &str, version: &str) -> AnyConstraint {
+ SimpleConstraint::new(operator.to_string(), version.to_string(), None).into()
+}
+
+#[ignore]
#[test]
fn test_select_all_providers() {
let _tear_down = TearDown;
- let _fixtures = set_up();
- todo!()
+ let mut fixtures = set_up();
+
+ let package_a = get_package("A", "1.0");
+ fixtures.repo.add_package(package_a.clone()).unwrap();
+ let package_b = get_package("B", "2.0");
+ fixtures.repo.add_package(package_b.clone()).unwrap();
+
+ let mut provides_a: IndexMap<String, Link> = IndexMap::new();
+ provides_a.insert(
+ "x".to_string(),
+ link("A", "X", constraint("==", "1.0"), Link::TYPE_PROVIDE),
+ );
+ as_complete(&package_a).__set_provides(provides_a);
+ let mut provides_b: IndexMap<String, Link> = IndexMap::new();
+ provides_b.insert(
+ "x".to_string(),
+ link("B", "X", constraint("==", "1.0"), Link::TYPE_PROVIDE),
+ );
+ as_complete(&package_b).__set_provides(provides_b);
+
+ fixtures
+ .repository_set
+ .add_repository(RepositoryInterfaceHandle::new(fixtures.repo))
+ .unwrap();
+
+ let pool = fixtures
+ .repository_set
+ .create_pool_for_packages(
+ vec!["A".to_string(), "B".to_string()],
+ Some(fixtures.repo_locked.clone()),
+ )
+ .unwrap();
+
+ let literals = vec![package_a.get_id(), package_b.get_id()];
+ let expected = literals.clone();
+
+ let selected = fixtures
+ .policy
+ .select_preferred_packages(&pool, literals, None);
+
+ assert_eq!(expected, selected);
}
-#[ignore = "set_provides/set_replaces only exist on RootPackage handles; CompletePackage from get_package has no set_replaces"]
+#[ignore]
#[test]
fn test_prefer_non_replacing_from_same_repo() {
let _tear_down = TearDown;
- let _fixtures = set_up();
- todo!()
+ let mut fixtures = set_up();
+
+ let package_a = get_package("A", "1.0");
+ fixtures.repo.add_package(package_a.clone()).unwrap();
+ let package_b = get_package("B", "2.0");
+ fixtures.repo.add_package(package_b.clone()).unwrap();
+
+ let mut replaces_b: IndexMap<String, Link> = IndexMap::new();
+ replaces_b.insert(
+ "a".to_string(),
+ link("B", "A", constraint("==", "1.0"), Link::TYPE_REPLACE),
+ );
+ as_complete(&package_b).__set_replaces(replaces_b);
+
+ fixtures
+ .repository_set
+ .add_repository(RepositoryInterfaceHandle::new(fixtures.repo))
+ .unwrap();
+
+ let pool = fixtures
+ .repository_set
+ .create_pool_for_packages(
+ vec!["A".to_string(), "B".to_string()],
+ Some(fixtures.repo_locked.clone()),
+ )
+ .unwrap();
+
+ let literals = vec![package_a.get_id(), package_b.get_id()];
+ let expected = literals.clone();
+
+ let selected = fixtures
+ .policy
+ .select_preferred_packages(&pool, literals, None);
+
+ assert_eq!(expected, selected);
}
-#[ignore = "set_replaces only exists on RootPackage handles; CompletePackage from get_package has no set_replaces"]
+#[ignore]
#[test]
fn test_prefer_replacing_package_from_same_vendor() {
let _tear_down = TearDown;
- let _fixtures = set_up();
- todo!()
+ let mut fixtures = set_up();
+
+ // test with default order
+ let package_b = get_package("vendor-b/replacer", "1.0");
+ fixtures.repo.add_package(package_b.clone()).unwrap();
+ let package_a = get_package("vendor-a/replacer", "1.0");
+ fixtures.repo.add_package(package_a.clone()).unwrap();
+
+ let mut replaces_a: IndexMap<String, Link> = IndexMap::new();
+ replaces_a.insert(
+ "vendor-a/package".to_string(),
+ link(
+ "vendor-a/replacer",
+ "vendor-a/package",
+ constraint("==", "1.0"),
+ Link::TYPE_REPLACE,
+ ),
+ );
+ as_complete(&package_a).__set_replaces(replaces_a);
+ let mut replaces_b: IndexMap<String, Link> = IndexMap::new();
+ replaces_b.insert(
+ "vendor-a/package".to_string(),
+ link(
+ "vendor-b/replacer",
+ "vendor-a/package",
+ constraint("==", "1.0"),
+ Link::TYPE_REPLACE,
+ ),
+ );
+ as_complete(&package_b).__set_replaces(replaces_b);
+
+ fixtures
+ .repository_set
+ .add_repository(RepositoryInterfaceHandle::new(fixtures.repo))
+ .unwrap();
+
+ let pool = fixtures
+ .repository_set
+ .create_pool_for_packages(
+ vec![
+ "vendor-a/replacer".to_string(),
+ "vendor-b/replacer".to_string(),
+ ],
+ Some(fixtures.repo_locked.clone()),
+ )
+ .unwrap();
+
+ let literals = vec![package_a.get_id(), package_b.get_id()];
+ let expected = literals.clone();
+
+ let selected = fixtures.policy.select_preferred_packages(
+ &pool,
+ literals,
+ Some("vendor-a/package".to_string()),
+ );
+ assert_eq!(expected, selected);
+
+ // test with reversed order in repo
+ let repo = ArrayRepository::new(vec![]).unwrap();
+ let package_a = CompletePackageHandle::dup(&as_complete(&package_a));
+ repo.add_package(package_a.clone().into()).unwrap();
+ let package_b = CompletePackageHandle::dup(&as_complete(&package_b));
+ repo.add_package(package_b.clone().into()).unwrap();
+
+ let mut repository_set = RepositorySet::new(
+ "dev",
+ IndexMap::new(),
+ vec![],
+ IndexMap::new(),
+ IndexMap::new(),
+ IndexMap::new(),
+ );
+ repository_set
+ .add_repository(RepositoryInterfaceHandle::new(repo))
+ .unwrap();
+
+ let pool = fixtures
+ .repository_set
+ .create_pool_for_packages(
+ vec![
+ "vendor-a/replacer".to_string(),
+ "vendor-b/replacer".to_string(),
+ ],
+ Some(fixtures.repo_locked.clone()),
+ )
+ .unwrap();
+
+ let literals = vec![package_a.get_id(), package_b.get_id()];
+ let expected = literals.clone();
+
+ let selected = fixtures.policy.select_preferred_packages(
+ &pool,
+ literals,
+ Some("vendor-a/package".to_string()),
+ );
+ assert_eq!(expected, selected);
}
#[ignore]
diff --git a/crates/shirabe/tests/dependency_resolver/security_advisory_pool_filter_test.rs b/crates/shirabe/tests/dependency_resolver/security_advisory_pool_filter_test.rs
index 98ac131..7938657 100644
--- a/crates/shirabe/tests/dependency_resolver/security_advisory_pool_filter_test.rs
+++ b/crates/shirabe/tests/dependency_resolver/security_advisory_pool_filter_test.rs
@@ -12,24 +12,272 @@ use shirabe::dependency_resolver::SecurityAdvisoryPoolFilter;
use shirabe::dependency_resolver::pool::Pool;
use shirabe::dependency_resolver::request::Request;
use shirabe::package::handle::{CompletePackageHandle, PackageHandle, PackageInterfaceHandle};
-use shirabe_php_shim::PhpMixed;
+use shirabe::repository::{PackageRepository, RepositoryInterfaceHandle};
+use shirabe_php_shim::{PhpMixed, uniqid};
+use shirabe_semver::constraint::{AnyConstraint, SimpleConstraint};
+#[ignore]
#[test]
-#[ignore = "requires PackageRepository to implement RepositoryInterface (filter takes Vec<RepositoryInterfaceHandle>) and php-shim uniqid() used by generateSecurityAdvisory; neither exists"]
fn test_filter_packages_by_advisories() {
- todo!()
+ let audit_config = AuditConfig::new(
+ true,
+ Auditor::FORMAT_SUMMARY.to_string(),
+ Auditor::ABANDONED_FAIL.to_string(),
+ true,
+ true,
+ false,
+ IndexMap::new(),
+ IndexMap::new(),
+ IndexMap::new(),
+ IndexMap::new(),
+ IndexMap::new(),
+ IndexMap::new(),
+ );
+ let filter = SecurityAdvisoryPoolFilter::new(Auditor, audit_config);
+
+ let advisory1 =
+ generate_security_advisory("acme/package", Some("CVE-1999-1000"), ">=1.0.0,<1.1.0");
+ let advisory2 =
+ generate_security_advisory("acme/package", Some("CVE-1999-1001"), ">=1.0.0,<1.1.0");
+ let mut security_advisories: IndexMap<String, PhpMixed> = IndexMap::new();
+ security_advisories.insert(
+ "acme/package".to_string(),
+ PhpMixed::List(vec![
+ PhpMixed::Array(advisory1.clone()),
+ PhpMixed::Array(advisory2.clone()),
+ ]),
+ );
+ let mut config: IndexMap<String, PhpMixed> = IndexMap::new();
+ config.insert("package".to_string(), PhpMixed::List(vec![]));
+ config.insert(
+ "security-advisories".to_string(),
+ PhpMixed::Array(security_advisories),
+ );
+ let repository = RepositoryInterfaceHandle::new(PackageRepository::new(config));
+
+ let package: PackageInterfaceHandle = PackageHandle::new(
+ "acme/package".to_string(),
+ "1.0.0.0".to_string(),
+ "1.0".to_string(),
+ )
+ .into();
+ let expected_package1: PackageInterfaceHandle = PackageHandle::new(
+ "acme/package".to_string(),
+ "2.0.0.0".to_string(),
+ "2.0".to_string(),
+ )
+ .into();
+ let expected_package2: PackageInterfaceHandle = PackageHandle::new(
+ "acme/other".to_string(),
+ "1.0.0.0".to_string(),
+ "1.0".to_string(),
+ )
+ .into();
+
+ let pool = Pool::new(
+ vec![
+ package.clone(),
+ expected_package1.clone(),
+ expected_package2.clone(),
+ ],
+ vec![],
+ IndexMap::new(),
+ IndexMap::new(),
+ IndexMap::new(),
+ IndexMap::new(),
+ );
+ let filtered_pool = filter
+ .filter(pool, vec![repository], &Request::new(None))
+ .unwrap();
+
+ let packages = filtered_pool.get_packages();
+ assert_eq!(packages.len(), 2);
+ assert!(packages[0].ptr_eq(&expected_package1));
+ assert!(packages[1].ptr_eq(&expected_package2));
+
+ let constraint: AnyConstraint =
+ SimpleConstraint::new("==".to_string(), "1.0.0.0".to_string(), None).into();
+ assert!(filtered_pool.is_security_removed_package_version("acme/package", Some(&constraint)));
+ assert_eq!(
+ filtered_pool
+ .get_all_abandoned_removed_package_versions()
+ .len(),
+ 0
+ );
+
+ let advisory_map = filtered_pool.get_all_security_removed_package_versions();
+ assert!(advisory_map.contains_key("acme/package"));
+ assert!(advisory_map["acme/package"].contains_key("1.0.0.0"));
+ assert_eq!(
+ vec![
+ advisory1["advisoryId"].as_string().unwrap().to_string(),
+ advisory2["advisoryId"].as_string().unwrap().to_string(),
+ ],
+ filtered_pool.get_security_advisory_identifiers_for_package_version(
+ "acme/package",
+ Some(&constraint)
+ ),
+ );
}
+#[ignore]
#[test]
-#[ignore = "requires PackageRepository to implement RepositoryInterface (filter takes Vec<RepositoryInterfaceHandle>) and php-shim uniqid() used by generateSecurityAdvisory; neither exists"]
fn test_dont_filter_packages_by_ignored_advisories() {
- todo!()
+ let mut ignore_list: IndexMap<String, Option<String>> = IndexMap::new();
+ ignore_list.insert("CVE-2024-1234".to_string(), None);
+ let audit_config = AuditConfig::new(
+ true,
+ Auditor::FORMAT_SUMMARY.to_string(),
+ Auditor::ABANDONED_FAIL.to_string(),
+ true,
+ true,
+ false,
+ ignore_list.clone(),
+ ignore_list,
+ IndexMap::new(),
+ IndexMap::new(),
+ IndexMap::new(),
+ IndexMap::new(),
+ );
+ let filter = SecurityAdvisoryPoolFilter::new(Auditor, audit_config);
+
+ let mut security_advisories: IndexMap<String, PhpMixed> = IndexMap::new();
+ security_advisories.insert(
+ "acme/package".to_string(),
+ PhpMixed::List(vec![PhpMixed::Array(generate_security_advisory(
+ "acme/package",
+ Some("CVE-2024-1234"),
+ ">=1.0.0,<1.1.0",
+ ))]),
+ );
+ let mut config: IndexMap<String, PhpMixed> = IndexMap::new();
+ config.insert("package".to_string(), PhpMixed::List(vec![]));
+ config.insert(
+ "security-advisories".to_string(),
+ PhpMixed::Array(security_advisories),
+ );
+ let repository = RepositoryInterfaceHandle::new(PackageRepository::new(config));
+
+ let expected_package1: PackageInterfaceHandle = PackageHandle::new(
+ "acme/package".to_string(),
+ "1.0.0.0".to_string(),
+ "1.0".to_string(),
+ )
+ .into();
+ let expected_package2: PackageInterfaceHandle = PackageHandle::new(
+ "acme/package".to_string(),
+ "1.1.0.0".to_string(),
+ "1.1".to_string(),
+ )
+ .into();
+
+ let pool = Pool::new(
+ vec![expected_package1.clone(), expected_package2.clone()],
+ vec![],
+ IndexMap::new(),
+ IndexMap::new(),
+ IndexMap::new(),
+ IndexMap::new(),
+ );
+ let filtered_pool = filter
+ .filter(pool, vec![repository], &Request::new(None))
+ .unwrap();
+
+ let packages = filtered_pool.get_packages();
+ assert_eq!(packages.len(), 2);
+ assert!(packages[0].ptr_eq(&expected_package1));
+ assert!(packages[1].ptr_eq(&expected_package2));
+ assert_eq!(
+ filtered_pool
+ .get_all_abandoned_removed_package_versions()
+ .len(),
+ 0
+ );
+ assert_eq!(
+ filtered_pool
+ .get_all_security_removed_package_versions()
+ .len(),
+ 0
+ );
}
+#[ignore]
#[test]
-#[ignore = "requires PackageRepository to implement RepositoryInterface (filter takes Vec<RepositoryInterfaceHandle>) and php-shim uniqid() used by generateSecurityAdvisory; neither exists"]
fn test_dont_filter_packages_with_block_insecure_disabled() {
- todo!()
+ let audit_config = AuditConfig::new(
+ true,
+ Auditor::FORMAT_SUMMARY.to_string(),
+ Auditor::ABANDONED_FAIL.to_string(),
+ false,
+ true,
+ false,
+ IndexMap::new(),
+ IndexMap::new(),
+ IndexMap::new(),
+ IndexMap::new(),
+ IndexMap::new(),
+ IndexMap::new(),
+ );
+ let filter = SecurityAdvisoryPoolFilter::new(Auditor, audit_config);
+
+ let mut security_advisories: IndexMap<String, PhpMixed> = IndexMap::new();
+ security_advisories.insert(
+ "acme/package".to_string(),
+ PhpMixed::List(vec![PhpMixed::Array(generate_security_advisory(
+ "acme/package",
+ Some("CVE-2024-1234"),
+ ">=1.0.0,<1.1.0",
+ ))]),
+ );
+ let mut config: IndexMap<String, PhpMixed> = IndexMap::new();
+ config.insert("package".to_string(), PhpMixed::List(vec![]));
+ config.insert(
+ "security-advisories".to_string(),
+ PhpMixed::Array(security_advisories),
+ );
+ let repository = RepositoryInterfaceHandle::new(PackageRepository::new(config));
+
+ let expected_package1: PackageInterfaceHandle = PackageHandle::new(
+ "acme/package".to_string(),
+ "1.0.0.0".to_string(),
+ "1.0".to_string(),
+ )
+ .into();
+ let expected_package2: PackageInterfaceHandle = PackageHandle::new(
+ "acme/package".to_string(),
+ "1.1.0.0".to_string(),
+ "1.1".to_string(),
+ )
+ .into();
+
+ let pool = Pool::new(
+ vec![expected_package1.clone(), expected_package2.clone()],
+ vec![],
+ IndexMap::new(),
+ IndexMap::new(),
+ IndexMap::new(),
+ IndexMap::new(),
+ );
+ let filtered_pool = filter
+ .filter(pool, vec![repository], &Request::new(None))
+ .unwrap();
+
+ let packages = filtered_pool.get_packages();
+ assert_eq!(packages.len(), 2);
+ assert!(packages[0].ptr_eq(&expected_package1));
+ assert!(packages[1].ptr_eq(&expected_package2));
+ assert_eq!(
+ filtered_pool
+ .get_all_abandoned_removed_package_versions()
+ .len(),
+ 0
+ );
+ assert_eq!(
+ filtered_pool
+ .get_all_security_removed_package_versions()
+ .len(),
+ 0
+ );
}
#[test]
@@ -106,3 +354,58 @@ fn test_dont_filter_packages_with_abandoned_package() {
0
);
}
+
+fn generate_security_advisory(
+ package_name: &str,
+ cve: Option<&str>,
+ affected_versions: &str,
+) -> IndexMap<String, PhpMixed> {
+ let mut source: IndexMap<String, PhpMixed> = IndexMap::new();
+ source.insert(
+ "name".to_string(),
+ PhpMixed::String("Security Advisory".to_string()),
+ );
+ source.insert("remoteId".to_string(), PhpMixed::String("test".to_string()));
+
+ let mut advisory: IndexMap<String, PhpMixed> = IndexMap::new();
+ advisory.insert(
+ "advisoryId".to_string(),
+ PhpMixed::String(uniqid("PKSA-", false)),
+ );
+ advisory.insert(
+ "packageName".to_string(),
+ PhpMixed::String(package_name.to_string()),
+ );
+ advisory.insert("remoteId".to_string(), PhpMixed::String("test".to_string()));
+ advisory.insert(
+ "title".to_string(),
+ PhpMixed::String("Security Advisory".to_string()),
+ );
+ advisory.insert("link".to_string(), PhpMixed::Null);
+ advisory.insert(
+ "cve".to_string(),
+ match cve {
+ Some(cve) => PhpMixed::String(cve.to_string()),
+ None => PhpMixed::Null,
+ },
+ );
+ advisory.insert(
+ "affectedVersions".to_string(),
+ PhpMixed::String(affected_versions.to_string()),
+ );
+ advisory.insert("source".to_string(), PhpMixed::String("Tests".to_string()));
+ advisory.insert(
+ "reportedAt".to_string(),
+ PhpMixed::String("2024-04-31 12:37:47".to_string()),
+ );
+ advisory.insert(
+ "composerRepository".to_string(),
+ PhpMixed::String("Package Repository".to_string()),
+ );
+ advisory.insert("severity".to_string(), PhpMixed::String("high".to_string()));
+ advisory.insert(
+ "sources".to_string(),
+ PhpMixed::List(vec![PhpMixed::Array(source)]),
+ );
+ advisory
+}
diff --git a/crates/shirabe/tests/dependency_resolver/solver_test.rs b/crates/shirabe/tests/dependency_resolver/solver_test.rs
index c9c4d26..a688190 100644
--- a/crates/shirabe/tests/dependency_resolver/solver_test.rs
+++ b/crates/shirabe/tests/dependency_resolver/solver_test.rs
@@ -277,7 +277,7 @@ fn test_solver_remove_if_not_requested() {
);
}
-#[ignore = "get_pretty_string path reaches an unimplemented todo!() (in_array non-strict in php-shim)"]
+#[ignore = "get_pretty_string path reaches an unimplemented stub (in_array non-strict in php-shim)"]
#[test]
fn test_install_non_existing_package_fails() {
let fixtures = set_up();
@@ -1921,7 +1921,7 @@ fn test_issue265() {
);
}
-#[ignore = "get_pretty_string path reaches an unimplemented todo!() (in_array non-strict in php-shim)"]
+#[ignore = "get_pretty_string path reaches an unimplemented stub (in_array non-strict in php-shim)"]
#[test]
fn test_conflict_result_empty() {
let fixtures = set_up();
@@ -1979,7 +1979,7 @@ fn test_conflict_result_empty() {
);
}
-#[ignore = "get_pretty_string path reaches an unimplemented todo!() (in_array non-strict in php-shim)"]
+#[ignore = "get_pretty_string path reaches an unimplemented stub (in_array non-strict in php-shim)"]
#[test]
fn test_unsatisfiable_requires() {
let fixtures = set_up();
@@ -2027,7 +2027,7 @@ fn test_unsatisfiable_requires() {
);
}
-#[ignore = "get_pretty_string path reaches an unimplemented todo!() (Intervals::is_subset_of)"]
+#[ignore = "get_pretty_string path reaches an unimplemented stub (Intervals::is_subset_of)"]
#[test]
fn test_require_mismatch_exception() {
let fixtures = set_up();