aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe/tests/repository/path_repository_test.rs
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-06-22 23:42:07 +0900
committernsfisis <nsfisis@gmail.com>2026-06-22 23:42:07 +0900
commit5ab5f3b316798c1411ce8e6a7f5b091fda93589c (patch)
treec7669f94f5d9bd9adc07bc1aab3f14cfdec1ae5f /crates/shirabe/tests/repository/path_repository_test.rs
parentb291e714bc739262140323e08fe2fb9e91e00ee7 (diff)
downloadphp-shirabe-5ab5f3b316798c1411ce8e6a7f5b091fda93589c.tar.gz
php-shirabe-5ab5f3b316798c1411ce8e6a7f5b091fda93589c.tar.zst
php-shirabe-5ab5f3b316798c1411ce8e6a7f5b091fda93589c.zip
test: port previously-ignored Composer tests via __ test hatches
Re-evaluate the reason'd #[ignore] tests under the Phase D criterion: a test is unportable ONLY if the APIs/types needed to WRITE it do not exist. A test that compiles but panics at runtime (todo!() body, a regex the regex crate cannot compile) or fails at runtime (incomplete or incorrect impl behavior) is portable -- it is written in full and marked with a reason-less #[ignore]. About 120 test functions move from reason'd #[ignore] to reason-less #[ignore] (the ported-but-not-yet-passing signal). Impl crates gain only additive __ test hatches (init_command, pool, file_downloader, package handle link setters, artifact/path repository, repository manager, svn); no existing logic changes. Tests whose required APIs genuinely do not exist (mock/reflection harness, ApplicationTester, solve() discarding SolverProblemsException, a script::Event that cannot be passed as an originating event) keep their reason'd #[ignore]. cargo check -p shirabe --tests passes. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Diffstat (limited to 'crates/shirabe/tests/repository/path_repository_test.rs')
-rw-r--r--crates/shirabe/tests/repository/path_repository_test.rs239
1 files changed, 219 insertions, 20 deletions
diff --git a/crates/shirabe/tests/repository/path_repository_test.rs b/crates/shirabe/tests/repository/path_repository_test.rs
index c2cf892..cea6a85 100644
--- a/crates/shirabe/tests/repository/path_repository_test.rs
+++ b/crates/shirabe/tests/repository/path_repository_test.rs
@@ -1,54 +1,253 @@
//! ref: composer/tests/Composer/Test/Repository/PathRepositoryTest.php
-// PathRepository does not implement RepositoryInterface and exposes no public
-// getPackages/count/hasPackage; the delegation to its inner ArrayRepository is not yet
-// ported, so there is no way to drive these tests. The unversioned cases additionally
-// require the VersionGuesser (git).
+use std::cell::RefCell;
+use std::rc::Rc;
-#[ignore = "PathRepository exposes no public RepositoryInterface::get_packages/count/has_package; the inner ArrayRepository delegation is not ported"]
+use indexmap::IndexMap;
+use shirabe::config::Config;
+use shirabe::io::{IOInterface, NullIO};
+use shirabe::repository::PathRepository;
+use shirabe::util::{Platform, ProcessExecutor};
+use shirabe_php_shim::{
+ DIRECTORY_SEPARATOR, PhpMixed, file_get_contents, hash, realpath, serialize,
+};
+
+use crate::test_case::get_package;
+
+fn fixtures_dir() -> String {
+ format!(
+ "{}/../../composer/tests/Composer/Test/Repository/Fixtures",
+ env!("CARGO_MANIFEST_DIR")
+ )
+}
+
+/// ref: PathRepositoryTest::createPathRepo
+fn create_path_repo(options: IndexMap<String, PhpMixed>) -> PathRepository {
+ let io: Rc<RefCell<dyn IOInterface>> = Rc::new(RefCell::new(NullIO::new()));
+
+ let config = Rc::new(RefCell::new(Config::new(true, None)));
+ let proc = Rc::new(RefCell::new(ProcessExecutor::new(None)));
+
+ PathRepository::new(options, io, config, None, None, Some(proc)).unwrap()
+}
+
+fn coordinates(pairs: Vec<(&str, PhpMixed)>) -> IndexMap<String, PhpMixed> {
+ let mut map: IndexMap<String, PhpMixed> = IndexMap::new();
+ for (key, value) in pairs {
+ map.insert(key.to_string(), value);
+ }
+ map
+}
+
+#[ignore]
#[test]
fn test_load_package_from_file_system_with_incorrect_path() {
- todo!()
+ let repository_url =
+ [fixtures_dir(), "path".to_string(), "missing".to_string()].join(DIRECTORY_SEPARATOR);
+ let mut repository =
+ create_path_repo(coordinates(vec![("url", PhpMixed::String(repository_url))]));
+ assert!(repository.__get_packages().is_err());
}
-#[ignore = "PathRepository exposes no public RepositoryInterface::get_packages/count/has_package; the inner ArrayRepository delegation is not ported"]
+#[ignore]
#[test]
fn test_load_package_from_file_system_with_version() {
- todo!()
+ let repository_url = [
+ fixtures_dir(),
+ "path".to_string(),
+ "with-version".to_string(),
+ ]
+ .join(DIRECTORY_SEPARATOR);
+ let mut repository =
+ create_path_repo(coordinates(vec![("url", PhpMixed::String(repository_url))]));
+ repository.__get_packages().unwrap();
+
+ assert_eq!(1, repository.__count().unwrap());
+ assert!(
+ repository
+ .__has_package(get_package("test/path-versioned", "0.0.2"))
+ .unwrap()
+ );
}
-#[ignore = "PathRepository exposes no public RepositoryInterface::get_packages/count/has_package; the inner ArrayRepository delegation is not ported"]
+#[ignore]
#[test]
fn test_load_package_from_file_system_without_version() {
- todo!()
+ let repository_url = [
+ fixtures_dir(),
+ "path".to_string(),
+ "without-version".to_string(),
+ ]
+ .join(DIRECTORY_SEPARATOR);
+ let mut repository =
+ create_path_repo(coordinates(vec![("url", PhpMixed::String(repository_url))]));
+ let packages = repository.__get_packages().unwrap();
+
+ assert!(repository.__count().unwrap() >= 1);
+
+ let package = &packages[0];
+ assert_eq!("test/path-unversioned", package.get_name());
+
+ let package_version = package.get_version();
+ assert!(!package_version.is_empty());
}
-#[ignore = "PathRepository exposes no public RepositoryInterface::get_packages/count/has_package; the inner ArrayRepository delegation is not ported"]
+#[ignore]
#[test]
fn test_load_package_from_file_system_with_wildcard() {
- todo!()
+ let repository_url =
+ [fixtures_dir(), "path".to_string(), "*".to_string()].join(DIRECTORY_SEPARATOR);
+ let mut repository =
+ create_path_repo(coordinates(vec![("url", PhpMixed::String(repository_url))]));
+ let packages = repository.__get_packages().unwrap();
+ let mut names: Vec<String> = Vec::new();
+
+ assert!(repository.__count().unwrap() >= 2);
+
+ let package = &packages[0];
+ names.push(package.get_name());
+
+ let package = &packages[1];
+ names.push(package.get_name());
+
+ names.sort();
+ assert_eq!(
+ vec![
+ "test/path-unversioned".to_string(),
+ "test/path-versioned".to_string()
+ ],
+ names
+ );
}
-#[ignore = "PathRepository exposes no public RepositoryInterface::get_packages/count/has_package; the inner ArrayRepository delegation is not ported"]
+#[ignore]
#[test]
fn test_load_package_with_explicit_versions() {
- todo!()
+ let mut versions: IndexMap<String, PhpMixed> = IndexMap::new();
+ versions.insert(
+ "test/path-unversioned".to_string(),
+ PhpMixed::String("4.3.2.1".to_string()),
+ );
+ versions.insert(
+ "test/path-versioned".to_string(),
+ PhpMixed::String("3.2.1.0".to_string()),
+ );
+ let options = coordinates(vec![("versions", PhpMixed::Array(versions))]);
+
+ let repository_url =
+ [fixtures_dir(), "path".to_string(), "*".to_string()].join(DIRECTORY_SEPARATOR);
+ let mut repository = create_path_repo(coordinates(vec![
+ ("url", PhpMixed::String(repository_url)),
+ ("options", PhpMixed::Array(options)),
+ ]));
+ let packages = repository.__get_packages().unwrap();
+
+ let mut versions: IndexMap<String, String> = IndexMap::new();
+
+ assert_eq!(2, repository.__count().unwrap());
+
+ let package = &packages[0];
+ versions.insert(package.get_name(), package.get_version());
+
+ let package = &packages[1];
+ versions.insert(package.get_name(), package.get_version());
+
+ versions.sort_keys();
+ let expected: IndexMap<String, String> = [
+ ("test/path-unversioned".to_string(), "4.3.2.1".to_string()),
+ ("test/path-versioned".to_string(), "3.2.1.0".to_string()),
+ ]
+ .into_iter()
+ .collect();
+ assert_eq!(expected, versions);
}
-#[ignore = "PathRepository exposes no public RepositoryInterface::get_packages/count/has_package; the inner ArrayRepository delegation is not ported"]
+/// Verify relative repository URLs remain relative, see #4439
+#[ignore]
#[test]
fn test_url_remains_relative() {
- todo!()
+ // realpath() does not fully expand the paths
+ // PHP Bug https://bugs.php.net/bug.php?id=72642
+ let repository_url = [
+ realpath(&realpath(&fixtures_dir().replace("/Fixtures", "")).unwrap_or_default())
+ .unwrap_or_default(),
+ "Fixtures".to_string(),
+ "path".to_string(),
+ "with-version".to_string(),
+ ]
+ .join(DIRECTORY_SEPARATOR);
+ // getcwd() not necessarily match __DIR__
+ // PHP Bug https://bugs.php.net/bug.php?id=73797
+ let cwd = realpath(&realpath(&Platform::get_cwd(false).unwrap()).unwrap_or_default())
+ .unwrap_or_default();
+ let relative_url = repository_url[cwd.len().min(repository_url.len())..]
+ .trim_start_matches(DIRECTORY_SEPARATOR)
+ .to_string();
+
+ let mut repository = create_path_repo(coordinates(vec![(
+ "url",
+ PhpMixed::String(relative_url.clone()),
+ )]));
+ let packages = repository.__get_packages().unwrap();
+
+ assert_eq!(1, repository.__count().unwrap());
+
+ let package = &packages[0];
+ assert_eq!("test/path-versioned", package.get_name());
+
+ // Convert platform specific separators back to generic URL slashes
+ let relative_url = relative_url.replace(DIRECTORY_SEPARATOR, "/");
+ assert_eq!(Some(relative_url), package.get_dist_url());
}
-#[ignore = "PathRepository exposes no public RepositoryInterface::get_packages/count/has_package; the inner ArrayRepository delegation is not ported"]
+#[ignore]
#[test]
fn test_reference_none() {
- todo!()
+ let options = coordinates(vec![("reference", PhpMixed::String("none".to_string()))]);
+ let repository_url =
+ [fixtures_dir(), "path".to_string(), "*".to_string()].join(DIRECTORY_SEPARATOR);
+ let mut repository = create_path_repo(coordinates(vec![
+ ("url", PhpMixed::String(repository_url)),
+ ("options", PhpMixed::Array(options)),
+ ]));
+ let packages = repository.__get_packages().unwrap();
+
+ assert!(repository.__count().unwrap() >= 2);
+
+ for package in &packages {
+ assert_eq!(package.get_dist_reference(), None);
+ }
}
-#[ignore = "PathRepository exposes no public RepositoryInterface::get_packages/count/has_package; the inner ArrayRepository delegation is not ported"]
+#[ignore]
#[test]
fn test_reference_config() {
- todo!()
+ let options = coordinates(vec![
+ ("reference", PhpMixed::String("config".to_string())),
+ ("relative", PhpMixed::Bool(true)),
+ ]);
+ let repository_url =
+ [fixtures_dir(), "path".to_string(), "*".to_string()].join(DIRECTORY_SEPARATOR);
+ let mut repository = create_path_repo(coordinates(vec![
+ ("url", PhpMixed::String(repository_url)),
+ ("options", PhpMixed::Array(options.clone())),
+ ]));
+ let packages = repository.__get_packages().unwrap();
+
+ assert!(repository.__count().unwrap() >= 2);
+
+ for package in &packages {
+ let dist_url = package.get_dist_url().unwrap_or_default();
+ assert_eq!(
+ package.get_dist_reference(),
+ Some(hash(
+ "sha1",
+ &format!(
+ "{}{}",
+ file_get_contents(format!("{}/composer.json", dist_url)).unwrap_or_default(),
+ serialize(&PhpMixed::Array(options.clone()))
+ )
+ ))
+ );
+ }
}