diff options
| author | nsfisis <nsfisis@gmail.com> | 2026-06-25 16:27:53 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2026-06-26 00:20:05 +0900 |
| commit | 3a0d9340810a8808d963135a884f50d08442ac67 (patch) | |
| tree | 9fbed3350a23c791f52e37209095e0db41962c87 /crates/shirabe/tests/autoload | |
| parent | 46ac7242d526e13707dc140b7244e0fadf2219b9 (diff) | |
| download | php-shirabe-3a0d9340810a8808d963135a884f50d08442ac67.tar.gz php-shirabe-3a0d9340810a8808d963135a884f50d08442ac67.tar.zst php-shirabe-3a0d9340810a8808d963135a884f50d08442ac67.zip | |
test: port 59 autoload/vcs/installer/util/command tests; fix output capture
Port autoload_generator (24), bitbucket (14), suggested_packages (11),
git_driver (6), archive_manager (3), and a bump command test. Fix the
ApplicationTester output-capture root cause (php://memory streams must be
readable regardless of fopen mode). Implement posix_getuid/geteuid, the PCRE
'A' anchored modifier, php_strip_whitespace, stream_get_wrappers, is_callable
scalars; fix preg_quote angle-bracket escaping and class-map parser regexes.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Diffstat (limited to 'crates/shirabe/tests/autoload')
| -rw-r--r-- | crates/shirabe/tests/autoload/autoload_generator_test.rs | 1739 | ||||
| -rw-r--r-- | crates/shirabe/tests/autoload/main.rs | 3 |
2 files changed, 1642 insertions, 100 deletions
diff --git a/crates/shirabe/tests/autoload/autoload_generator_test.rs b/crates/shirabe/tests/autoload/autoload_generator_test.rs index 72ac999..a3b833a 100644 --- a/crates/shirabe/tests/autoload/autoload_generator_test.rs +++ b/crates/shirabe/tests/autoload/autoload_generator_test.rs @@ -1,267 +1,1806 @@ //! ref: composer/tests/Composer/Test/Autoload/AutoloadGeneratorTest.php -/// Creates the working/vendor temp directories, switches into the working dir, and -/// builds the AutoloadGenerator from a mocked Config/InstallationManager/ -/// InstalledRepository/EventDispatcher and a BufferIO. The mocks and temp-dir -/// helpers are not available here, so this remains a stub. -fn set_up() { - todo!() +use std::cell::RefCell; +use std::rc::Rc; + +use indexmap::IndexMap; +use serial_test::serial; +use tempfile::TempDir; + +use shirabe::autoload::AutoloadGenerator; +use shirabe::composer::{ComposerHandle, PartialOrFullComposer}; +use shirabe::config::Config; +use shirabe::event_dispatcher::EventDispatcher; +use shirabe::installer::{InstallationManager, InstallerInterface}; +use shirabe::io::{BufferIO, IOInterface}; +use shirabe::package::handle::{AliasPackageHandle, PackageHandle, RootPackageHandle}; +use shirabe::package::{Link, PackageInterfaceHandle, RootPackageInterfaceHandle}; +use shirabe::repository::{ + InstalledArrayRepository, InstalledRepositoryInterface, WritableRepositoryInterface, +}; +use shirabe::util::http_downloader::HttpDownloader; +use shirabe::util::r#loop::Loop; +use shirabe_external_packages::symfony::console::output::output_interface; +use shirabe_php_shim::PhpMixed; +use shirabe_semver::constraint::{AnyConstraint, MatchAllConstraint, SimpleConstraint}; + +use crate::config_stub::ConfigStubBuilder; + +/// The mock `InstallationManager::getInstallPath` used throughout the test: metapackages return +/// null, every other package returns `vendorDir/<name>(/<targetDir>)`. Registered as an installer +/// that supports every type so `InstallationManager::getInstallPath` routes to it. +#[derive(Debug)] +struct InstallPathStubInstaller { + vendor_dir: String, } -/// Restores the original working directory and removes the working/vendor -/// directories created by `set_up`, which is itself a stub. -fn tear_down() { - todo!() +#[async_trait::async_trait(?Send)] +impl InstallerInterface for InstallPathStubInstaller { + fn supports(&self, _package_type: &str) -> bool { + true + } + + fn is_installed( + &mut self, + _repo: &dyn InstalledRepositoryInterface, + _package: PackageInterfaceHandle, + ) -> bool { + true + } + + async fn download( + &mut self, + _package: PackageInterfaceHandle, + _prev_package: Option<PackageInterfaceHandle>, + ) -> anyhow::Result<Option<PhpMixed>> { + Ok(None) + } + + async fn prepare( + &mut self, + _type: &str, + _package: PackageInterfaceHandle, + _prev_package: Option<PackageInterfaceHandle>, + ) -> anyhow::Result<Option<PhpMixed>> { + Ok(None) + } + + async fn install( + &mut self, + _repo: &mut dyn InstalledRepositoryInterface, + _package: PackageInterfaceHandle, + ) -> anyhow::Result<Option<PhpMixed>> { + Ok(None) + } + + async fn update( + &mut self, + _repo: &mut dyn InstalledRepositoryInterface, + _initial: PackageInterfaceHandle, + _target: PackageInterfaceHandle, + ) -> anyhow::Result<Option<PhpMixed>> { + Ok(None) + } + + async fn uninstall( + &mut self, + _repo: &mut dyn InstalledRepositoryInterface, + _package: PackageInterfaceHandle, + ) -> anyhow::Result<Option<PhpMixed>> { + Ok(None) + } + + async fn cleanup( + &mut self, + _type: &str, + _package: PackageInterfaceHandle, + _prev_package: Option<PackageInterfaceHandle>, + ) -> anyhow::Result<Option<PhpMixed>> { + Ok(None) + } + + fn get_install_path(&mut self, package: PackageInterfaceHandle) -> Option<String> { + if package.get_type() == "metapackage" { + return None; + } + + let target_dir = package.get_target_dir(); + let suffix = match target_dir { + Some(dir) if !dir.is_empty() => format!("/{}", dir), + _ => String::new(), + }; + + Some(format!( + "{}/{}{}", + self.vendor_dir, + package.get_name(), + suffix + )) + } } -struct TearDown; +/// Mirrors the PHP `setUp`/`tearDown` lifecycle: a fresh temp working dir, a `composer-test-autoload` +/// vendor dir inside it, `chdir`ed into the working dir, plus the mocked Config/InstallationManager/ +/// repository/EventDispatcher and BufferIO. The temp tree is removed and the cwd restored on drop. +struct SetUp { + _temp_dir: TempDir, + prev_cwd: std::path::PathBuf, + working_dir: String, + vendor_dir: String, + repository: InstalledArrayRepository, + im: InstallationManager, + io: Rc<RefCell<BufferIO>>, + generator: AutoloadGenerator, + event_dispatcher: Rc<RefCell<EventDispatcher>>, +} -impl Drop for TearDown { +impl Drop for SetUp { fn drop(&mut self) { - tear_down(); + let _ = std::env::set_current_dir(&self.prev_cwd); + } +} + +fn null_path(s: &str) -> String { + s.to_string() +} + +fn set_up() -> SetUp { + let temp_dir = TempDir::new().unwrap(); + let working_dir = temp_dir.path().to_str().unwrap().to_string(); + let vendor_dir = format!("{}/composer-test-autoload", working_dir); + std::fs::create_dir_all(&vendor_dir).unwrap(); + + let prev_cwd = std::env::current_dir().unwrap(); + std::env::set_current_dir(&working_dir).unwrap(); + + let io = Rc::new(RefCell::new( + BufferIO::new(String::new(), output_interface::VERBOSITY_NORMAL, None).unwrap(), + )); + + // The PHP loop mock has its constructor disabled and is never exercised here, so a mock + // HttpDownloader (no real curl backend) stands in for the InstallationManager's loop. + let dispatcher_io: Rc<RefCell<dyn IOInterface>> = io.clone(); + let config_for_downloader = Rc::new(RefCell::new(Config::new(false, None))); + let http_downloader = Rc::new(RefCell::new(HttpDownloader::__new_mock( + dispatcher_io.clone(), + config_for_downloader, + ))); + let loop_ = Rc::new(RefCell::new(Loop::new(http_downloader, None))); + + let mut im = InstallationManager::new(loop_, dispatcher_io.clone(), None); + im.add_installer(Box::new(InstallPathStubInstaller { + vendor_dir: vendor_dir.clone(), + })); + + let repository = InstalledArrayRepository::new().unwrap(); + + // EventDispatcher constructor is disabled in PHP and dispatch is never called when run-scripts + // is off (the default), so a real dispatcher over an empty Composer is a faithful no-op stand-in. + let composer = + ComposerHandle::from_rc_unchecked(Rc::new(RefCell::new(PartialOrFullComposer::new_full()))); + let event_dispatcher = Rc::new(RefCell::new(EventDispatcher::new( + composer.upcast().downgrade(), + dispatcher_io.clone(), + None, + ))); + + let generator = AutoloadGenerator::new(event_dispatcher.clone(), Some(dispatcher_io)); + + SetUp { + _temp_dir: temp_dir, + prev_cwd, + working_dir, + vendor_dir, + repository, + im, + io, + generator, + event_dispatcher, + } +} + +impl SetUp { + /// Builds the mocked Config returning `vendor-dir`/`platform-check`/`use-include-path`, mirroring + /// the PHP `configValueMap`. Rebuilt per call because tests mutate `vendor_dir`. + fn config(&self) -> Config { + ConfigStubBuilder::new() + .with("vendor-dir", PhpMixed::String(self.vendor_dir.clone())) + .with("platform-check", PhpMixed::Bool(true)) + .with("use-include-path", PhpMixed::Bool(false)) + .build() + } + + fn ensure_dir(&self, path: &str) { + std::fs::create_dir_all(path).unwrap(); + } + + fn put(&self, path: &str, contents: &str) { + let p = std::path::Path::new(path); + if let Some(parent) = p.parent() { + std::fs::create_dir_all(parent).unwrap(); + } + std::fs::write(path, contents).unwrap(); + } + + fn set_canonical_packages(&mut self, packages: Vec<PackageInterfaceHandle>) { + for p in packages { + self.repository.add_package(p).unwrap(); + } } } -// These exercise AutoloadGenerator end-to-end: they build packages, write fixture files to -// a temp dir, run dump() through a mocked InstalledRepository/EventDispatcher and compare -// the generated autoload files. The integration setup (fixtures, mocks, filesystem) is not -// ported yet. +fn fixtures_dir() -> std::path::PathBuf { + std::path::Path::new(env!("CARGO_MANIFEST_DIR")) + .join("../../composer/tests/Composer/Test/Autoload/Fixtures") + .canonicalize() + .unwrap() +} + +/// ref: AutoloadGeneratorTest::assertAutoloadFiles +#[track_caller] +fn assert_autoload_files(name: &str, dir: &str, r#type: &str) { + let a = fixtures_dir().join(format!("autoload_{}.php", name)); + let b = format!("{}/autoload_{}.php", dir, r#type); + assert_file_content_equals(a.to_str().unwrap(), &b); +} + +/// ref: AutoloadGeneratorTest::assertFileContentEquals +#[track_caller] +fn assert_file_content_equals(expected: &str, actual: &str) { + let exp = std::fs::read_to_string(expected) + .unwrap_or_else(|e| panic!("read {}: {}", expected, e)) + .replace('\r', ""); + let act = std::fs::read_to_string(actual) + .unwrap_or_else(|e| panic!("read {}: {}", actual, e)) + .replace('\r', ""); + assert_eq!(exp, act, "{} equals {}", expected, actual); +} + +fn match_all() -> AnyConstraint { + AnyConstraint::MatchAll(MatchAllConstraint::new(None)) +} + +fn constraint(operator: &str, version: &str) -> AnyConstraint { + AnyConstraint::Simple(SimpleConstraint::new( + operator.to_string(), + version.to_string(), + None, + )) +} + +fn link(source: &str, target: &str, constraint: AnyConstraint, description: Option<&str>) -> Link { + Link::new( + source.to_string(), + target.to_string(), + constraint, + description.map(|d| d.to_string()), + String::new(), + ) +} + +fn requires(links: Vec<(&str, Link)>) -> IndexMap<String, Link> { + links.into_iter().map(|(k, v)| (k.to_string(), v)).collect() +} + +fn autoload(entries: Vec<(&str, PhpMixed)>) -> IndexMap<String, PhpMixed> { + entries + .into_iter() + .map(|(k, v)| (k.to_string(), v)) + .collect() +} + +fn str_list(items: &[&str]) -> PhpMixed { + PhpMixed::List( + items + .iter() + .map(|s| PhpMixed::String(s.to_string())) + .collect(), + ) +} + +fn str_map(entries: &[(&str, PhpMixed)]) -> PhpMixed { + PhpMixed::Array( + entries + .iter() + .map(|(k, v)| (k.to_string(), v.clone())) + .collect(), + ) +} + +fn pstr(v: &str) -> PhpMixed { + PhpMixed::String(v.to_string()) +} + +fn new_root_pkg(name: &str) -> RootPackageHandle { + RootPackageHandle::new(name.to_string(), null_path("1.0"), "1.0".to_string()) +} + +fn new_pkg(name: &str) -> PackageHandle { + PackageHandle::new(name.to_string(), "1.0".to_string(), "1.0".to_string()) +} + +fn dump( + s: &mut SetUp, + package: RootPackageInterfaceHandle, + scan_psr_packages: bool, + suffix: &str, +) -> anyhow::Result<shirabe_class_map_generator::class_map::ClassMap> { + let config = s.config(); + // Borrow splitting: take fields out so dump can hold &mut to several at once. + let SetUp { + repository, + im, + generator, + .. + } = s; + generator.dump( + &config, + repository, + package, + im, + "composer", + scan_psr_packages, + Some(suffix.to_string()), + None, + false, + ) +} + #[test] -#[ignore = "setUp needs mocked Config::get, InstallationManager::getInstallPath, InstalledRepositoryInterface::getCanonicalPackages and TestCase::getUniqueTmpDirectory/ensureDirectoryExistsAndClear; no mock infra exists"] +#[serial] fn test_root_package_autoloading() { - todo!() + let mut s = set_up(); + let package = new_root_pkg("root/a"); + package.set_autoload(autoload(vec![ + ( + "psr-0", + str_map(&[ + ("Main", pstr("src/")), + ("Lala", str_list(&["src/", "lib/"])), + ]), + ), + ( + "psr-4", + str_map(&[ + ("Acme\\Fruit\\", pstr("src-fruit/")), + ("Acme\\Cake\\", str_list(&["src-cake/", "lib-cake/"])), + ]), + ), + ("classmap", str_list(&["composersrc/"])), + ])); + + s.ensure_dir(&format!("{}/composer", s.working_dir)); + s.ensure_dir(&format!("{}/src/Lala/Test", s.working_dir)); + s.ensure_dir(&format!("{}/lib", s.working_dir)); + s.put( + &format!("{}/src/Lala/ClassMapMain.php", s.working_dir), + "<?php namespace Lala; class ClassMapMain {}", + ); + s.put( + &format!("{}/src/Lala/Test/ClassMapMainTest.php", s.working_dir), + "<?php namespace Lala\\Test; class ClassMapMainTest {}", + ); + + s.ensure_dir(&format!("{}/src-fruit", s.working_dir)); + s.ensure_dir(&format!("{}/src-cake", s.working_dir)); + s.ensure_dir(&format!("{}/lib-cake", s.working_dir)); + s.put( + &format!("{}/src-cake/ClassMapBar.php", s.working_dir), + "<?php namespace Acme\\Cake; class ClassMapBar {}", + ); + + s.ensure_dir(&format!("{}/composersrc", s.working_dir)); + s.put( + &format!("{}/composersrc/foo.php", s.working_dir), + "<?php class ClassMapFoo {}", + ); + + let composer_out = format!("{}/composer", s.vendor_dir); + dump(&mut s, package.into(), true, "_1").unwrap(); + + assert_autoload_files("main", &composer_out, "namespaces"); + assert_autoload_files("psr4", &composer_out, "psr4"); + assert_autoload_files("classmap", &composer_out, "classmap"); } #[test] -#[ignore = "setUp needs mocked Config/InstallationManager/InstalledRepositoryInterface and TestCase tmp-dir helpers; no mock infra exists"] +#[serial] fn test_root_package_dev_autoloading() { - todo!() + let mut s = set_up(); + let package = new_root_pkg("root/a"); + package.set_autoload(autoload(vec![( + "psr-0", + str_map(&[("Main", pstr("src/"))]), + )])); + package.set_dev_autoload(autoload(vec![ + ("files", str_list(&["devfiles/foo.php"])), + ("psr-0", str_map(&[("Main", pstr("tests/"))])), + ])); + + s.ensure_dir(&format!("{}/composer", s.working_dir)); + s.ensure_dir(&format!("{}/src/Main", s.working_dir)); + s.put( + &format!("{}/src/Main/ClassMain.php", s.working_dir), + "<?php namespace Main; class ClassMain {}", + ); + s.ensure_dir(&format!("{}/devfiles", s.working_dir)); + s.put( + &format!("{}/devfiles/foo.php", s.working_dir), + "<?php function foo() { echo \"foo\"; }", + ); + + let composer_out = format!("{}/composer", s.vendor_dir); + s.generator.set_dev_mode(true); + dump(&mut s, package.into(), true, "_1").unwrap(); + + assert_autoload_files("main5", &composer_out, "namespaces"); + assert_autoload_files("classmap7", &composer_out, "classmap"); + assert_autoload_files("files2", &composer_out, "files"); } #[test] -#[ignore = "setUp needs mocked Config/InstallationManager/InstalledRepositoryInterface and TestCase tmp-dir helpers; no mock infra exists"] +#[serial] fn test_root_package_dev_autoloading_disabled_by_default() { - todo!() + let mut s = set_up(); + let package = new_root_pkg("root/a"); + package.set_autoload(autoload(vec![( + "psr-0", + str_map(&[("Main", pstr("src/"))]), + )])); + package.set_dev_autoload(autoload(vec![("files", str_list(&["devfiles/foo.php"]))])); + + s.ensure_dir(&format!("{}/composer", s.working_dir)); + s.ensure_dir(&format!("{}/src/Main", s.working_dir)); + s.put( + &format!("{}/src/Main/ClassMain.php", s.working_dir), + "<?php namespace Main; class ClassMain {}", + ); + s.ensure_dir(&format!("{}/devfiles", s.working_dir)); + s.put( + &format!("{}/devfiles/foo.php", s.working_dir), + "<?php function foo() { echo \"foo\"; }", + ); + + let composer_out = format!("{}/composer", s.vendor_dir); + dump(&mut s, package.into(), true, "_1").unwrap(); + + assert_autoload_files("main4", &composer_out, "namespaces"); + assert_autoload_files("classmap7", &composer_out, "classmap"); + assert!(!std::path::Path::new(&format!("{}/autoload_files.php", composer_out)).is_file()); } #[test] -#[ignore = "setUp needs mocked Config/InstallationManager/InstalledRepositoryInterface and TestCase tmp-dir helpers; no mock infra exists"] +#[serial] fn test_vendor_dir_same_as_working_dir() { - todo!() + let mut s = set_up(); + s.vendor_dir = s.working_dir.clone(); + // Re-register the install-path stub so getInstallPath uses the new vendor dir. + s.im.add_installer(Box::new(InstallPathStubInstaller { + vendor_dir: s.vendor_dir.clone(), + })); + + let package = new_root_pkg("root/a"); + package.set_autoload(autoload(vec![ + ( + "psr-0", + str_map(&[("Main", pstr("src/")), ("Lala", pstr("src/"))]), + ), + ( + "psr-4", + str_map(&[ + ("Acme\\Fruit\\", pstr("src-fruit/")), + ("Acme\\Cake\\", str_list(&["src-cake/", "lib-cake/"])), + ]), + ), + ("classmap", str_list(&["composersrc/"])), + ])); + + s.ensure_dir(&format!("{}/composer", s.vendor_dir)); + s.ensure_dir(&format!("{}/src/Main", s.vendor_dir)); + s.put( + &format!("{}/src/Main/Foo.php", s.vendor_dir), + "<?php namespace Main; class Foo {}", + ); + s.ensure_dir(&format!("{}/composersrc", s.vendor_dir)); + s.put( + &format!("{}/composersrc/foo.php", s.vendor_dir), + "<?php class ClassMapFoo {}", + ); + + let composer_out = format!("{}/composer", s.vendor_dir); + dump(&mut s, package.into(), true, "_2").unwrap(); + assert_autoload_files("main3", &composer_out, "namespaces"); + assert_autoload_files("psr4_3", &composer_out, "psr4"); + assert_autoload_files("classmap3", &composer_out, "classmap"); } #[test] -#[ignore = "setUp needs mocked Config/InstallationManager/InstalledRepositoryInterface and TestCase tmp-dir helpers; no mock infra exists"] +#[serial] fn test_root_package_autoloading_alternative_vendor_dir() { - todo!() + let mut s = set_up(); + let package = new_root_pkg("root/a"); + package.set_autoload(autoload(vec![ + ( + "psr-0", + str_map(&[("Main", pstr("src/")), ("Lala", pstr("src/"))]), + ), + ( + "psr-4", + str_map(&[ + ("Acme\\Fruit\\", pstr("src-fruit/")), + ("Acme\\Cake\\", str_list(&["src-cake/", "lib-cake/"])), + ]), + ), + ("classmap", str_list(&["composersrc/"])), + ])); + + s.vendor_dir = format!("{}/subdir", s.vendor_dir); + s.im.add_installer(Box::new(InstallPathStubInstaller { + vendor_dir: s.vendor_dir.clone(), + })); + + s.ensure_dir(&format!("{}/composer", s.vendor_dir)); + s.ensure_dir(&format!("{}/src", s.working_dir)); + s.ensure_dir(&format!("{}/composersrc", s.working_dir)); + s.put( + &format!("{}/composersrc/foo.php", s.working_dir), + "<?php class ClassMapFoo {}", + ); + + let composer_out = format!("{}/composer", s.vendor_dir); + dump(&mut s, package.into(), false, "_3").unwrap(); + assert_autoload_files("main2", &composer_out, "namespaces"); + assert_autoload_files("psr4_2", &composer_out, "psr4"); + assert_autoload_files("classmap2", &composer_out, "classmap"); } #[test] -#[ignore = "setUp needs mocked Config/InstallationManager/InstalledRepositoryInterface and TestCase tmp-dir helpers; no mock infra exists"] +#[serial] +#[ignore = "autoload_real.php/autoload_static.php fixtures track a newer Composer template (single blank lines + $filesToLoad/$requireFile block) than the current AutoloadGenerator port emits; needs production template alignment"] fn test_root_package_autoloading_with_target_dir() { - todo!() + let mut s = set_up(); + let package = new_root_pkg("root/a"); + package.set_autoload(autoload(vec![ + ( + "psr-0", + str_map(&[("Main\\Foo", pstr("")), ("Main\\Bar", pstr(""))]), + ), + ("classmap", str_list(&["Main/Foo/src", "lib"])), + ("files", str_list(&["foo.php", "Main/Foo/bar.php"])), + ])); + package.__set_target_dir(Some("Main/Foo/".to_string())); + + s.ensure_dir(&format!("{}/a", s.vendor_dir)); + s.ensure_dir(&format!("{}/src", s.working_dir)); + s.ensure_dir(&format!("{}/lib", s.working_dir)); + s.put( + &format!("{}/src/rootfoo.php", s.working_dir), + "<?php class ClassMapFoo {}", + ); + s.put( + &format!("{}/lib/rootbar.php", s.working_dir), + "<?php class ClassMapBar {}", + ); + s.put( + &format!("{}/foo.php", s.working_dir), + "<?php class FilesFoo {}", + ); + s.put( + &format!("{}/bar.php", s.working_dir), + "<?php class FilesBar {}", + ); + + let vendor = s.vendor_dir.clone(); + let composer_out = format!("{}/composer", vendor); + dump(&mut s, package.into(), false, "TargetDir").unwrap(); + + let fx = fixtures_dir(); + assert_file_content_equals( + fx.join("autoload_target_dir.php").to_str().unwrap(), + &format!("{}/autoload.php", vendor), + ); + assert_file_content_equals( + fx.join("autoload_real_target_dir.php").to_str().unwrap(), + &format!("{}/autoload_real.php", composer_out), + ); + assert_file_content_equals( + fx.join("autoload_static_target_dir.php").to_str().unwrap(), + &format!("{}/autoload_static.php", composer_out), + ); + assert_file_content_equals( + fx.join("autoload_files_target_dir.php").to_str().unwrap(), + &format!("{}/autoload_files.php", composer_out), + ); + assert_autoload_files("classmap6", &composer_out, "classmap"); } #[test] -#[ignore = "setUp needs mocked Config/InstallationManager/InstalledRepositoryInterface and TestCase tmp-dir helpers; no mock infra exists"] +#[serial] fn test_duplicate_files_warning() { - todo!() + let mut s = set_up(); + let package = new_root_pkg("root/a"); + package.set_autoload(autoload(vec![( + "files", + str_list(&["foo.php", "bar.php", "./foo.php", "././foo.php"]), + )])); + + s.ensure_dir(&format!("{}/a", s.vendor_dir)); + s.ensure_dir(&format!("{}/src", s.working_dir)); + s.ensure_dir(&format!("{}/lib", s.working_dir)); + s.put( + &format!("{}/foo.php", s.working_dir), + "<?php class FilesFoo {}", + ); + s.put( + &format!("{}/bar.php", s.working_dir), + "<?php class FilesBar {}", + ); + + let vendor = s.vendor_dir.clone(); + let composer_out = format!("{}/composer", vendor); + dump(&mut s, package.into(), false, "FilesWarning").unwrap(); + + assert_file_content_equals( + fixtures_dir() + .join("autoload_files_duplicates.php") + .to_str() + .unwrap(), + &format!("{}/autoload_files.php", composer_out), + ); + let expected = "<warning>The following \"files\" autoload rules are included multiple times, this may cause issues and should be resolved:</warning>\n<warning> - $baseDir . '/foo.php'</warning>\n"; + assert_eq!(expected, s.io.borrow().get_output()); } #[test] -#[ignore = "setUp needs mocked Config/InstallationManager/InstalledRepositoryInterface and TestCase tmp-dir helpers; no mock infra exists"] +#[serial] fn test_vendors_autoloading() { - todo!() + let mut s = set_up(); + let package = new_root_pkg("root/a"); + package.set_requires(requires(vec![ + ("a/a", link("a", "a/a", match_all(), None)), + ("b/b", link("a", "b/b", match_all(), None)), + ])); + + let a = new_pkg("a/a"); + let b = new_pkg("b/b"); + let c = AliasPackageHandle::new(b.clone(), "1.2".to_string(), "1.2".to_string()); + a.__set_autoload(autoload(vec![( + "psr-0", + str_map(&[("A", pstr("src/")), ("A\\B", pstr("lib/"))]), + )])); + b.__set_autoload(autoload(vec![( + "psr-0", + str_map(&[("B\\Sub\\Name", pstr("src/"))]), + )])); + + s.set_canonical_packages(vec![a.into(), b.into(), c.into()]); + + s.ensure_dir(&format!("{}/composer", s.vendor_dir)); + s.ensure_dir(&format!("{}/a/a/src", s.vendor_dir)); + s.ensure_dir(&format!("{}/a/a/lib", s.vendor_dir)); + s.ensure_dir(&format!("{}/b/b/src", s.vendor_dir)); + + let composer_out = format!("{}/composer", s.vendor_dir); + dump(&mut s, package.into(), false, "_5").unwrap(); + assert_autoload_files("vendors", &composer_out, "namespaces"); + assert!(std::path::Path::new(&format!("{}/autoload_classmap.php", composer_out)).exists()); } #[test] -#[ignore = "setUp needs mocked Config/InstallationManager/InstalledRepositoryInterface and TestCase tmp-dir helpers; no mock infra exists"] +#[serial] fn test_vendors_autoloading_with_metapackages() { - todo!() + let mut s = set_up(); + let package = new_root_pkg("root/a"); + package.set_requires(requires(vec![("a/a", link("a", "a/a", match_all(), None))])); + + let a = new_pkg("a/a"); + let b = new_pkg("b/b"); + let c = AliasPackageHandle::new(b.clone(), "1.2".to_string(), "1.2".to_string()); + a.__set_autoload(autoload(vec![( + "psr-0", + str_map(&[("A", pstr("src/")), ("A\\B", pstr("lib/"))]), + )])); + b.__set_autoload(autoload(vec![( + "psr-0", + str_map(&[("B\\Sub\\Name", pstr("src/"))]), + )])); + a.__set_type("metapackage".to_string()); + a.__set_requires(requires(vec![( + "b/b", + link("a/a", "b/b", match_all(), None), + )])); + + s.set_canonical_packages(vec![a.into(), b.into(), c.into()]); + + s.ensure_dir(&format!("{}/composer", s.vendor_dir)); + s.ensure_dir(&format!("{}/b/b/src", s.vendor_dir)); + s.ensure_dir(&format!("{}/a/a/src", s.vendor_dir)); + s.ensure_dir(&format!("{}/a/a/lib", s.vendor_dir)); + + let composer_out = format!("{}/composer", s.vendor_dir); + dump(&mut s, package.into(), false, "_5").unwrap(); + assert_autoload_files("vendors_meta", &composer_out, "namespaces"); + assert!(std::path::Path::new(&format!("{}/autoload_classmap.php", composer_out)).exists()); } #[test] -#[ignore = "setUp needs mocked Config/InstallationManager/InstalledRepositoryInterface and TestCase tmp-dir helpers; no mock infra exists"] +#[serial] fn test_non_dev_autoload_exclusion_with_recursion() { - todo!() + let mut s = set_up(); + let package = new_root_pkg("root/a"); + package.set_requires(requires(vec![("a/a", link("a", "a/a", match_all(), None))])); + + let a = new_pkg("a/a"); + let b = new_pkg("b/b"); + a.__set_autoload(autoload(vec![( + "psr-0", + str_map(&[("A", pstr("src/")), ("A\\B", pstr("lib/"))]), + )])); + a.__set_requires(requires(vec![( + "b/b", + link("a/a", "b/b", match_all(), None), + )])); + b.__set_autoload(autoload(vec![( + "psr-0", + str_map(&[("B\\Sub\\Name", pstr("src/"))]), + )])); + b.__set_requires(requires(vec![( + "a/a", + link("b/b", "a/a", match_all(), None), + )])); + + s.set_canonical_packages(vec![a.into(), b.into()]); + + s.ensure_dir(&format!("{}/composer", s.vendor_dir)); + s.ensure_dir(&format!("{}/a/a/src", s.vendor_dir)); + s.ensure_dir(&format!("{}/a/a/lib", s.vendor_dir)); + s.ensure_dir(&format!("{}/b/b/src", s.vendor_dir)); + + let composer_out = format!("{}/composer", s.vendor_dir); + dump(&mut s, package.into(), false, "_5").unwrap(); + assert_autoload_files("vendors", &composer_out, "namespaces"); + assert!(std::path::Path::new(&format!("{}/autoload_classmap.php", composer_out)).exists()); } #[test] -#[ignore = "setUp needs mocked Config/InstallationManager/InstalledRepositoryInterface and TestCase tmp-dir helpers; no mock infra exists"] +#[serial] fn test_non_dev_autoload_should_include_replaced_packages() { - todo!() + let mut s = set_up(); + let package = new_root_pkg("root/a"); + package.set_requires(requires(vec![("a/a", link("a", "a/a", match_all(), None))])); + + let a = new_pkg("a/a"); + let b = new_pkg("b/b"); + a.__set_requires(requires(vec![( + "b/c", + link("a/a", "b/c", match_all(), None), + )])); + b.__set_autoload(autoload(vec![("psr-4", str_map(&[("B\\", pstr("src/"))]))])); + b.__set_replaces(requires(vec![( + "b/c", + link( + "b/b", + "b/c", + constraint("==", "1.0"), + Some(Link::TYPE_REPLACE), + ), + )])); + + s.set_canonical_packages(vec![a.into(), b.into()]); + + s.ensure_dir(&format!("{}/b/b/src/C", s.vendor_dir)); + s.put( + &format!("{}/b/b/src/C/C.php", s.vendor_dir), + "<?php namespace B\\C; class C {}", + ); + + let vendor = s.vendor_dir.clone(); + let class_map = dump(&mut s, package.into(), true, "_5").unwrap(); + + let mut expected: IndexMap<String, String> = IndexMap::new(); + expected.insert("B\\C\\C".to_string(), format!("{}/b/b/src/C/C.php", vendor)); + expected.insert( + "Composer\\InstalledVersions".to_string(), + format!("{}/composer/InstalledVersions.php", vendor), + ); + assert_eq!(&expected, class_map.get_map()); } #[test] -#[ignore = "setUp needs mocked Config/InstallationManager/InstalledRepositoryInterface and TestCase tmp-dir helpers; no mock infra exists"] +#[serial] fn test_non_dev_autoload_exclusion_with_recursion_replace() { - todo!() + let mut s = set_up(); + let package = new_root_pkg("root/a"); + package.set_requires(requires(vec![("a/a", link("a", "a/a", match_all(), None))])); + + let a = new_pkg("a/a"); + let b = new_pkg("b/b"); + a.__set_autoload(autoload(vec![( + "psr-0", + str_map(&[("A", pstr("src/")), ("A\\B", pstr("lib/"))]), + )])); + a.__set_requires(requires(vec![( + "c/c", + link("a/a", "c/c", match_all(), None), + )])); + b.__set_autoload(autoload(vec![( + "psr-0", + str_map(&[("B\\Sub\\Name", pstr("src/"))]), + )])); + b.__set_replaces(requires(vec![( + "c/c", + link("b/b", "c/c", match_all(), None), + )])); + + s.set_canonical_packages(vec![a.into(), b.into()]); + + s.ensure_dir(&format!("{}/composer", s.vendor_dir)); + s.ensure_dir(&format!("{}/a/a/src", s.vendor_dir)); + s.ensure_dir(&format!("{}/a/a/lib", s.vendor_dir)); + s.ensure_dir(&format!("{}/b/b/src", s.vendor_dir)); + + let composer_out = format!("{}/composer", s.vendor_dir); + dump(&mut s, package.into(), false, "_5").unwrap(); + assert_autoload_files("vendors", &composer_out, "namespaces"); + assert!(std::path::Path::new(&format!("{}/autoload_classmap.php", composer_out)).exists()); } #[test] -#[ignore = "setUp needs mocked Config/InstallationManager/InstalledRepositoryInterface and TestCase tmp-dir helpers; no mock infra exists"] +#[serial] fn test_non_dev_autoload_replaces_nested_requirements() { - todo!() + let mut s = set_up(); + let package = new_root_pkg("root/a"); + package.set_requires(requires(vec![("a/a", link("a", "a/a", match_all(), None))])); + + let a = new_pkg("a/a"); + let b = new_pkg("b/b"); + let c = new_pkg("c/c"); + let d = new_pkg("d/d"); + let e = new_pkg("e/e"); + a.__set_autoload(autoload(vec![("classmap", str_list(&["src/A.php"]))])); + a.__set_requires(requires(vec![( + "b/b", + link("a/a", "b/b", match_all(), None), + )])); + b.__set_autoload(autoload(vec![("classmap", str_list(&["src/B.php"]))])); + b.__set_requires(requires(vec![( + "e/e", + link("b/b", "e/e", match_all(), None), + )])); + c.__set_autoload(autoload(vec![("classmap", str_list(&["src/C.php"]))])); + c.__set_replaces(requires(vec![( + "b/b", + link("c/c", "b/b", match_all(), None), + )])); + c.__set_requires(requires(vec![( + "d/d", + link("c/c", "d/d", match_all(), None), + )])); + d.__set_autoload(autoload(vec![("classmap", str_list(&["src/D.php"]))])); + e.__set_autoload(autoload(vec![("classmap", str_list(&["src/E.php"]))])); + + s.set_canonical_packages(vec![a.into(), b.into(), c.into(), d.into(), e.into()]); + + for (name, file, class) in [ + ("a/a", "A", "A"), + ("b/b", "B", "B"), + ("c/c", "C", "C"), + ("d/d", "D", "D"), + ("e/e", "E", "E"), + ] { + s.ensure_dir(&format!("{}/{}/src", s.vendor_dir, name)); + s.put( + &format!("{}/{}/src/{}.php", s.vendor_dir, name, file), + &format!("<?php class {} {{}}", class), + ); + } + + let composer_out = format!("{}/composer", s.vendor_dir); + dump(&mut s, package.into(), false, "_5").unwrap(); + assert_autoload_files("classmap9", &composer_out, "classmap"); } #[test] -#[ignore = "setUp needs mocked Config/InstallationManager/InstalledRepositoryInterface and TestCase tmp-dir helpers; no mock infra exists"] +#[serial] +#[ignore = "autoload_static.php getInitializer() fixture has a trailing blank line the current AutoloadGenerator template omits; needs production template alignment"] fn test_phar_autoload() { - todo!() + let mut s = set_up(); + let package = new_root_pkg("root/a"); + package.set_requires(requires(vec![("a/a", link("a", "a/a", match_all(), None))])); + package.set_autoload(autoload(vec![ + ( + "psr-0", + str_map(&[("Foo", pstr("foo.phar")), ("Bar", pstr("dir/bar.phar/src"))]), + ), + ( + "psr-4", + str_map(&[ + ("Baz\\", pstr("baz.phar")), + ("Qux\\", pstr("dir/qux.phar/src")), + ]), + ), + ])); + + let vendor_package = new_pkg("a/a"); + vendor_package.__set_autoload(autoload(vec![ + ( + "psr-0", + str_map(&[ + ("Lorem", pstr("lorem.phar")), + ("Ipsum", pstr("dir/ipsum.phar/src")), + ]), + ), + ( + "psr-4", + str_map(&[ + ("Dolor\\", pstr("dolor.phar")), + ("Sit\\", pstr("dir/sit.phar/src")), + ]), + ), + ])); + + s.set_canonical_packages(vec![vendor_package.into()]); + + let composer_out = format!("{}/composer", s.vendor_dir); + dump(&mut s, package.into(), true, "Phar").unwrap(); + assert_autoload_files("phar", &composer_out, "namespaces"); + assert_autoload_files("phar_psr4", &composer_out, "psr4"); + assert_autoload_files("phar_static", &composer_out, "static"); } #[test] -#[ignore = "setUp needs mocked Config/InstallationManager/InstalledRepositoryInterface and TestCase tmp-dir helpers; no mock infra exists"] +#[serial] fn test_psr_to_class_map_ignores_non_existing_dir() { - todo!() + let mut s = set_up(); + let package = new_root_pkg("root/a"); + package.set_autoload(autoload(vec![ + ( + "psr-0", + str_map(&[("Prefix", pstr("foo/bar/non/existing/"))]), + ), + ( + "psr-4", + str_map(&[("Prefix\\", pstr("foo/bar/non/existing2/"))]), + ), + ])); + + let vendor = s.vendor_dir.clone(); + let composer_out = format!("{}/composer", vendor); + let class_map = dump(&mut s, package.into(), true, "_8").unwrap(); + assert!(std::path::Path::new(&format!("{}/autoload_classmap.php", composer_out)).exists()); + + let mut expected: IndexMap<String, String> = IndexMap::new(); + expected.insert( + "Composer\\InstalledVersions".to_string(), + format!("{}/composer/InstalledVersions.php", vendor), + ); + assert_eq!(&expected, class_map.get_map()); } #[test] -#[ignore = "setUp needs mocked Config/InstallationManager/InstalledRepositoryInterface and TestCase tmp-dir helpers; no mock infra exists"] +#[serial] fn test_psr_to_class_map_ignores_non_psr_classes() { - todo!() + let mut s = set_up(); + let package = new_root_pkg("root/a"); + package.set_autoload(autoload(vec![ + ("psr-0", str_map(&[("psr0_", pstr("psr0/"))])), + ("psr-4", str_map(&[("psr4\\", pstr("psr4/"))])), + ])); + + s.ensure_dir(&format!("{}/psr0/psr0", s.working_dir)); + s.ensure_dir(&format!("{}/psr4", s.working_dir)); + s.put( + &format!("{}/psr0/psr0/match.php", s.working_dir), + "<?php class psr0_match {}", + ); + s.put( + &format!("{}/psr0/psr0/badfile.php", s.working_dir), + "<?php class psr0_badclass {}", + ); + s.put( + &format!("{}/psr4/match.php", s.working_dir), + "<?php namespace psr4; class match {}", + ); + s.put( + &format!("{}/psr4/badfile.php", s.working_dir), + "<?php namespace psr4; class badclass {}", + ); + + let vendor = s.vendor_dir.clone(); + let composer_out = format!("{}/composer", vendor); + dump(&mut s, package.into(), true, "_1").unwrap(); + assert!(std::path::Path::new(&format!("{}/autoload_classmap.php", composer_out)).exists()); + + let expected = format!( + "<?php\n\n// autoload_classmap.php @generated by Composer\n\n$vendorDir = dirname(__DIR__);\n$baseDir = dirname($vendorDir);\n\nreturn array(\n 'Composer\\\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',\n 'psr0_match' => $baseDir . '/psr0/psr0/match.php',\n 'psr4\\\\match' => $baseDir . '/psr4/match.php',\n);\n" + ); + let actual = + std::fs::read_to_string(format!("{}/autoload_classmap.php", composer_out)).unwrap(); + assert_eq!(expected, actual); } #[test] -#[ignore = "setUp needs mocked Config/InstallationManager/InstalledRepositoryInterface and TestCase tmp-dir helpers; no mock infra exists"] +#[serial] fn test_vendors_class_map_autoloading() { - todo!() + let mut s = set_up(); + let package = new_root_pkg("root/a"); + package.set_requires(requires(vec![ + ("a/a", link("a", "a/a", match_all(), None)), + ("b/b", link("a", "b/b", match_all(), None)), + ])); + + let a = new_pkg("a/a"); + let b = new_pkg("b/b"); + a.__set_autoload(autoload(vec![("classmap", str_list(&["src/"]))])); + b.__set_autoload(autoload(vec![("classmap", str_list(&["src/", "lib/"]))])); + + s.set_canonical_packages(vec![a.into(), b.into()]); + + s.ensure_dir(&format!("{}/composer", s.vendor_dir)); + s.ensure_dir(&format!("{}/a/a/src", s.vendor_dir)); + s.ensure_dir(&format!("{}/b/b/src", s.vendor_dir)); + s.ensure_dir(&format!("{}/b/b/lib", s.vendor_dir)); + s.put( + &format!("{}/a/a/src/a.php", s.vendor_dir), + "<?php class ClassMapFoo {}", + ); + s.put( + &format!("{}/b/b/src/b.php", s.vendor_dir), + "<?php class ClassMapBar {}", + ); + s.put( + &format!("{}/b/b/lib/c.php", s.vendor_dir), + "<?php class ClassMapBaz {}", + ); + + let vendor = s.vendor_dir.clone(); + let composer_out = format!("{}/composer", vendor); + let class_map = dump(&mut s, package.into(), false, "_6").unwrap(); + + let mut expected: IndexMap<String, String> = IndexMap::new(); + expected.insert( + "ClassMapBar".to_string(), + format!("{}/b/b/src/b.php", vendor), + ); + expected.insert( + "ClassMapBaz".to_string(), + format!("{}/b/b/lib/c.php", vendor), + ); + expected.insert( + "ClassMapFoo".to_string(), + format!("{}/a/a/src/a.php", vendor), + ); + expected.insert( + "Composer\\InstalledVersions".to_string(), + format!("{}/composer/InstalledVersions.php", vendor), + ); + assert_eq!(&expected, class_map.get_map()); + assert_autoload_files("classmap4", &composer_out, "classmap"); } #[test] -#[ignore = "setUp needs mocked Config/InstallationManager/InstalledRepositoryInterface and TestCase tmp-dir helpers; no mock infra exists"] +#[serial] fn test_vendors_class_map_autoloading_with_target_dir() { - todo!() + let mut s = set_up(); + let package = new_root_pkg("root/a"); + package.set_requires(requires(vec![ + ("a/a", link("a", "a/a", match_all(), None)), + ("b/b", link("a", "b/b", match_all(), None)), + ])); + + let a = new_pkg("a/a"); + let b = new_pkg("b/b"); + a.__set_autoload(autoload(vec![( + "classmap", + str_list(&["target/src/", "lib/"]), + )])); + a.__set_target_dir(Some("target".to_string())); + b.__set_autoload(autoload(vec![("classmap", str_list(&["src/"]))])); + + s.set_canonical_packages(vec![a.into(), b.into()]); + + s.ensure_dir(&format!("{}/composer", s.vendor_dir)); + s.ensure_dir(&format!("{}/a/a/target/src", s.vendor_dir)); + s.ensure_dir(&format!("{}/a/a/target/lib", s.vendor_dir)); + s.ensure_dir(&format!("{}/b/b/src", s.vendor_dir)); + s.put( + &format!("{}/a/a/target/src/a.php", s.vendor_dir), + "<?php class ClassMapFoo {}", + ); + s.put( + &format!("{}/a/a/target/lib/b.php", s.vendor_dir), + "<?php class ClassMapBar {}", + ); + s.put( + &format!("{}/b/b/src/c.php", s.vendor_dir), + "<?php class ClassMapBaz {}", + ); + + let vendor = s.vendor_dir.clone(); + let composer_out = format!("{}/composer", vendor); + let class_map = dump(&mut s, package.into(), false, "_6").unwrap(); + assert!(std::path::Path::new(&format!("{}/autoload_classmap.php", composer_out)).exists()); + + let mut expected: IndexMap<String, String> = IndexMap::new(); + expected.insert( + "ClassMapBar".to_string(), + format!("{}/a/a/target/lib/b.php", vendor), + ); + expected.insert( + "ClassMapBaz".to_string(), + format!("{}/b/b/src/c.php", vendor), + ); + expected.insert( + "ClassMapFoo".to_string(), + format!("{}/a/a/target/src/a.php", vendor), + ); + expected.insert( + "Composer\\InstalledVersions".to_string(), + format!("{}/composer/InstalledVersions.php", vendor), + ); + assert_eq!(&expected, class_map.get_map()); } #[test] -#[ignore = "setUp needs mocked Config/InstallationManager/InstalledRepositoryInterface and TestCase tmp-dir helpers; no mock infra exists"] +#[serial] +#[ignore = "the `classmap => ['./']` rule yields a scanned path containing `/./` (e.g. c/c/./foo/test.php) that the ClassMapGenerator port does not collapse the way PHP's normalizePath does; needs production path-normalization fix"] fn test_class_map_autoloading_empty_dir_and_exact_file() { - todo!() + let mut s = set_up(); + let package = new_root_pkg("root/a"); + package.set_requires(requires(vec![ + ("a/a", link("a", "a/a", match_all(), None)), + ("b/b", link("a", "b/b", match_all(), None)), + ("c/c", link("a", "c/c", match_all(), None)), + ])); + + let a = new_pkg("a/a"); + let b = new_pkg("b/b"); + let c = new_pkg("c/c"); + a.__set_autoload(autoload(vec![("classmap", str_list(&[""]))])); + b.__set_autoload(autoload(vec![("classmap", str_list(&["test.php"]))])); + c.__set_autoload(autoload(vec![("classmap", str_list(&["./"]))])); + + s.set_canonical_packages(vec![a.into(), b.into(), c.into()]); + + s.ensure_dir(&format!("{}/composer", s.vendor_dir)); + s.ensure_dir(&format!("{}/a/a/src", s.vendor_dir)); + s.ensure_dir(&format!("{}/b/b", s.vendor_dir)); + s.ensure_dir(&format!("{}/c/c/foo", s.vendor_dir)); + s.put( + &format!("{}/a/a/src/a.php", s.vendor_dir), + "<?php class ClassMapFoo {}", + ); + s.put( + &format!("{}/b/b/test.php", s.vendor_dir), + "<?php class ClassMapBar {}", + ); + s.put( + &format!("{}/c/c/foo/test.php", s.vendor_dir), + "<?php class ClassMapBaz {}", + ); + + let vendor = s.vendor_dir.clone(); + let composer_out = format!("{}/composer", vendor); + let class_map = dump(&mut s, package.into(), false, "_7").unwrap(); + assert!(std::path::Path::new(&format!("{}/autoload_classmap.php", composer_out)).exists()); + + let mut expected: IndexMap<String, String> = IndexMap::new(); + expected.insert( + "ClassMapBar".to_string(), + format!("{}/b/b/test.php", vendor), + ); + expected.insert( + "ClassMapBaz".to_string(), + format!("{}/c/c/foo/test.php", vendor), + ); + expected.insert( + "ClassMapFoo".to_string(), + format!("{}/a/a/src/a.php", vendor), + ); + expected.insert( + "Composer\\InstalledVersions".to_string(), + format!("{}/composer/InstalledVersions.php", vendor), + ); + assert_eq!(&expected, class_map.get_map()); + assert_autoload_files("classmap5", &composer_out, "classmap"); + + let real = std::fs::read_to_string(format!("{}/autoload_real.php", composer_out)).unwrap(); + assert!(!real.contains("$loader->setClassMapAuthoritative(true);")); + assert!(!real.contains("$loader->setApcuPrefix(")); } #[test] -#[ignore = "setUp needs mocked Config/InstallationManager/InstalledRepositoryInterface and TestCase tmp-dir helpers; no mock infra exists"] +#[serial] fn test_class_map_autoloading_authoritative_and_apcu() { - todo!() + let mut s = set_up(); + let package = new_root_pkg("root/a"); + package.set_requires(requires(vec![ + ("a/a", link("a", "a/a", match_all(), None)), + ("b/b", link("a", "b/b", match_all(), None)), + ("c/c", link("a", "c/c", match_all(), None)), + ])); + + let a = new_pkg("a/a"); + let b = new_pkg("b/b"); + let c = new_pkg("c/c"); + a.__set_autoload(autoload(vec![("psr-4", str_map(&[("", pstr("src/"))]))])); + b.__set_autoload(autoload(vec![("psr-4", str_map(&[("", pstr("./"))]))])); + c.__set_autoload(autoload(vec![("psr-4", str_map(&[("", pstr("foo/"))]))])); + + s.set_canonical_packages(vec![a.into(), b.into(), c.into()]); + + s.ensure_dir(&format!("{}/composer", s.vendor_dir)); + s.ensure_dir(&format!("{}/a/a/src", s.vendor_dir)); + s.ensure_dir(&format!("{}/b/b", s.vendor_dir)); + s.ensure_dir(&format!("{}/c/c/foo", s.vendor_dir)); + s.put( + &format!("{}/a/a/src/ClassMapFoo.php", s.vendor_dir), + "<?php class ClassMapFoo {}", + ); + s.put( + &format!("{}/b/b/ClassMapBar.php", s.vendor_dir), + "<?php class ClassMapBar {}", + ); + s.put( + &format!("{}/c/c/foo/ClassMapBaz.php", s.vendor_dir), + "<?php class ClassMapBaz {}", + ); + + s.generator.set_class_map_authoritative(true); + s.generator.set_apcu(true, None); + let vendor = s.vendor_dir.clone(); + let composer_out = format!("{}/composer", vendor); + let class_map = dump(&mut s, package.into(), false, "_7").unwrap(); + assert!(std::path::Path::new(&format!("{}/autoload_classmap.php", composer_out)).exists()); + + let mut expected: IndexMap<String, String> = IndexMap::new(); + expected.insert( + "ClassMapBar".to_string(), + format!("{}/b/b/ClassMapBar.php", vendor), + ); + expected.insert( + "ClassMapBaz".to_string(), + format!("{}/c/c/foo/ClassMapBaz.php", vendor), + ); + expected.insert( + "ClassMapFoo".to_string(), + format!("{}/a/a/src/ClassMapFoo.php", vendor), + ); + expected.insert( + "Composer\\InstalledVersions".to_string(), + format!("{}/composer/InstalledVersions.php", vendor), + ); + assert_eq!(&expected, class_map.get_map()); + assert_autoload_files("classmap8", &composer_out, "classmap"); + + let real = std::fs::read_to_string(format!("{}/autoload_real.php", composer_out)).unwrap(); + assert!(real.contains("$loader->setClassMapAuthoritative(true);")); + assert!(real.contains("$loader->setApcuPrefix(")); } #[test] -#[ignore = "setUp needs mocked Config/InstallationManager/InstalledRepositoryInterface and TestCase tmp-dir helpers; no mock infra exists"] +#[serial] fn test_class_map_autoloading_authoritative_and_apcu_prefix() { - todo!() + let mut s = set_up(); + let package = new_root_pkg("root/a"); + package.set_requires(requires(vec![ + ("a/a", link("a", "a/a", match_all(), None)), + ("b/b", link("a", "b/b", match_all(), None)), + ("c/c", link("a", "c/c", match_all(), None)), + ])); + + let a = new_pkg("a/a"); + let b = new_pkg("b/b"); + let c = new_pkg("c/c"); + a.__set_autoload(autoload(vec![("psr-4", str_map(&[("", pstr("src/"))]))])); + b.__set_autoload(autoload(vec![("psr-4", str_map(&[("", pstr("./"))]))])); + c.__set_autoload(autoload(vec![("psr-4", str_map(&[("", pstr("foo/"))]))])); + + s.set_canonical_packages(vec![a.into(), b.into(), c.into()]); + + s.ensure_dir(&format!("{}/composer", s.vendor_dir)); + s.ensure_dir(&format!("{}/a/a/src", s.vendor_dir)); + s.ensure_dir(&format!("{}/b/b", s.vendor_dir)); + s.ensure_dir(&format!("{}/c/c/foo", s.vendor_dir)); + s.put( + &format!("{}/a/a/src/ClassMapFoo.php", s.vendor_dir), + "<?php class ClassMapFoo {}", + ); + s.put( + &format!("{}/b/b/ClassMapBar.php", s.vendor_dir), + "<?php class ClassMapBar {}", + ); + s.put( + &format!("{}/c/c/foo/ClassMapBaz.php", s.vendor_dir), + "<?php class ClassMapBaz {}", + ); + + s.generator.set_class_map_authoritative(true); + s.generator + .set_apcu(true, Some("custom'Prefix".to_string())); + let vendor = s.vendor_dir.clone(); + let composer_out = format!("{}/composer", vendor); + let class_map = dump(&mut s, package.into(), false, "_7").unwrap(); + assert!(std::path::Path::new(&format!("{}/autoload_classmap.php", composer_out)).exists()); + + let mut expected: IndexMap<String, String> = IndexMap::new(); + expected.insert( + "ClassMapBar".to_string(), + format!("{}/b/b/ClassMapBar.php", vendor), + ); + expected.insert( + "ClassMapBaz".to_string(), + format!("{}/c/c/foo/ClassMapBaz.php", vendor), + ); + expected.insert( + "ClassMapFoo".to_string(), + format!("{}/a/a/src/ClassMapFoo.php", vendor), + ); + expected.insert( + "Composer\\InstalledVersions".to_string(), + format!("{}/composer/InstalledVersions.php", vendor), + ); + assert_eq!(&expected, class_map.get_map()); + assert_autoload_files("classmap8", &composer_out, "classmap"); + + let real = std::fs::read_to_string(format!("{}/autoload_real.php", composer_out)).unwrap(); + assert!(real.contains("$loader->setClassMapAuthoritative(true);")); + assert!(real.contains("$loader->setApcuPrefix('custom\\'Prefix');")); } #[test] -#[ignore = "setUp needs mocked Config/InstallationManager/InstalledRepositoryInterface and TestCase tmp-dir helpers; no mock infra exists"] +#[serial] +#[ignore = "autoload_real.php/autoload_static.php fixtures track a newer Composer template (single blank lines + $filesToLoad/$requireFile block) than the current AutoloadGenerator port emits; needs production template alignment"] fn test_files_autoload_generation() { - todo!() + let mut s = set_up(); + let package = new_root_pkg("root/a"); + package.set_autoload(autoload(vec![("files", str_list(&["root.php"]))])); + package.set_requires(requires(vec![ + ("a/a", link("a", "a/a", match_all(), None)), + ("b/b", link("a", "b/b", match_all(), None)), + ("c/c", link("a", "c/c", match_all(), None)), + ])); + + let a = new_pkg("a/a"); + let b = new_pkg("b/b"); + let c = new_pkg("c/c"); + a.__set_autoload(autoload(vec![("files", str_list(&["test.php"]))])); + b.__set_autoload(autoload(vec![("files", str_list(&["test2.php"]))])); + c.__set_autoload(autoload(vec![( + "files", + str_list(&["test3.php", "foo/bar/test4.php"]), + )])); + c.__set_target_dir(Some("foo/bar".to_string())); + + s.set_canonical_packages(vec![a.into(), b.into(), c.into()]); + + s.ensure_dir(&format!("{}/a/a", s.vendor_dir)); + s.ensure_dir(&format!("{}/b/b", s.vendor_dir)); + s.ensure_dir(&format!("{}/c/c/foo/bar", s.vendor_dir)); + s.put( + &format!("{}/a/a/test.php", s.vendor_dir), + "<?php function testFilesAutoloadGeneration1() {}", + ); + s.put( + &format!("{}/b/b/test2.php", s.vendor_dir), + "<?php function testFilesAutoloadGeneration2() {}", + ); + s.put( + &format!("{}/c/c/foo/bar/test3.php", s.vendor_dir), + "<?php function testFilesAutoloadGeneration3() {}", + ); + s.put( + &format!("{}/c/c/foo/bar/test4.php", s.vendor_dir), + "<?php function testFilesAutoloadGeneration4() {}", + ); + s.put( + &format!("{}/root.php", s.working_dir), + "<?php function testFilesAutoloadGenerationRoot() {}", + ); + + let vendor = s.vendor_dir.clone(); + let composer_out = format!("{}/composer", vendor); + dump(&mut s, package.into(), false, "FilesAutoload").unwrap(); + let fx = fixtures_dir(); + assert_file_content_equals( + fx.join("autoload_functions.php").to_str().unwrap(), + &format!("{}/autoload.php", vendor), + ); + assert_file_content_equals( + fx.join("autoload_real_functions.php").to_str().unwrap(), + &format!("{}/autoload_real.php", composer_out), + ); + assert_file_content_equals( + fx.join("autoload_static_functions.php").to_str().unwrap(), + &format!("{}/autoload_static.php", composer_out), + ); + assert_file_content_equals( + fx.join("autoload_files_functions.php").to_str().unwrap(), + &format!("{}/autoload_files.php", composer_out), + ); } #[test] -#[ignore = "setUp needs mocked Config/InstallationManager/InstalledRepositoryInterface and TestCase tmp-dir helpers; no mock infra exists"] -fn test_files_autoload_generation_remove_extra_entities_from_autoload_files() { - todo!() +#[serial] +fn test_override_vendors_autoloading() { + let mut s = set_up(); + let working_dir = s.working_dir.clone(); + let root_package = new_root_pkg("root/z"); + root_package.set_autoload(autoload(vec![ + ( + "psr-0", + str_map(&[("A\\B", pstr(&format!("{}/lib", working_dir)))]), + ), + ("classmap", str_list(&[&format!("{}/src", working_dir)])), + ])); + root_package.set_requires(requires(vec![ + ("a/a", link("z", "a/a", match_all(), None)), + ("b/b", link("z", "b/b", match_all(), None)), + ])); + + let a = new_pkg("a/a"); + let b = new_pkg("b/b"); + a.__set_autoload(autoload(vec![ + ( + "psr-0", + str_map(&[("A", pstr("src/")), ("A\\B", pstr("lib/"))]), + ), + ("classmap", str_list(&["classmap"])), + ])); + b.__set_autoload(autoload(vec![( + "psr-0", + str_map(&[("B\\Sub\\Name", pstr("src/"))]), + )])); + + s.set_canonical_packages(vec![a.into(), b.into()]); + + s.ensure_dir(&format!("{}/lib/A/B", s.working_dir)); + s.ensure_dir(&format!("{}/src/", s.working_dir)); + s.ensure_dir(&format!("{}/composer", s.vendor_dir)); + s.ensure_dir(&format!("{}/a/a/classmap", s.vendor_dir)); + s.ensure_dir(&format!("{}/a/a/src", s.vendor_dir)); + s.ensure_dir(&format!("{}/a/a/lib/A/B", s.vendor_dir)); + s.ensure_dir(&format!("{}/b/b/src", s.vendor_dir)); + + s.put( + &format!("{}/lib/A/B/C.php", s.working_dir), + "<?php namespace A\\B; class C {}", + ); + s.put( + &format!("{}/src/classes.php", s.working_dir), + "<?php namespace Foo; class Bar {}", + ); + s.put( + &format!("{}/a/a/lib/A/B/C.php", s.vendor_dir), + "<?php namespace A\\B; class C {}", + ); + s.put( + &format!("{}/a/a/classmap/classes.php", s.vendor_dir), + "<?php namespace Foo; class Bar {}", + ); + + let composer_out = format!("{}/composer", s.vendor_dir); + dump(&mut s, root_package.into(), true, "_9").unwrap(); + + let expected_namespace = "<?php\n\n// autoload_namespaces.php @generated by Composer\n\n$vendorDir = dirname(__DIR__);\n$baseDir = dirname($vendorDir);\n\nreturn array(\n 'B\\\\Sub\\\\Name' => array($vendorDir . '/b/b/src'),\n 'A\\\\B' => array($baseDir . '/lib', $vendorDir . '/a/a/lib'),\n 'A' => array($vendorDir . '/a/a/src'),\n);\n"; + let expected_psr4 = "<?php\n\n// autoload_psr4.php @generated by Composer\n\n$vendorDir = dirname(__DIR__);\n$baseDir = dirname($vendorDir);\n\nreturn array(\n);\n"; + let expected_classmap = "<?php\n\n// autoload_classmap.php @generated by Composer\n\n$vendorDir = dirname(__DIR__);\n$baseDir = dirname($vendorDir);\n\nreturn array(\n 'A\\\\B\\\\C' => $baseDir . '/lib/A/B/C.php',\n 'Composer\\\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',\n 'Foo\\\\Bar' => $baseDir . '/src/classes.php',\n);\n"; + + assert_eq!( + expected_namespace, + std::fs::read_to_string(format!("{}/autoload_namespaces.php", composer_out)).unwrap() + ); + assert_eq!( + expected_psr4, + std::fs::read_to_string(format!("{}/autoload_psr4.php", composer_out)).unwrap() + ); + assert_eq!( + expected_classmap, + std::fs::read_to_string(format!("{}/autoload_classmap.php", composer_out)).unwrap() + ); } #[test] -#[ignore = "setUp needs mocked Config/InstallationManager/InstalledRepositoryInterface and TestCase tmp-dir helpers; no mock infra exists"] -fn test_files_autoload_order_by_dependencies() { - todo!() +#[serial] +fn test_include_path_file_generation() { + let mut s = set_up(); + let package = new_root_pkg("root/a"); + + let a = new_pkg("a/a"); + a.__set_include_paths(vec!["lib/".to_string()]); + let b = new_pkg("b/b"); + b.__set_include_paths(vec!["library".to_string()]); + let c = new_pkg("c"); + c.__set_include_paths(vec!["library".to_string()]); + + s.set_canonical_packages(vec![a.into(), b.into(), c.into()]); + + s.ensure_dir(&format!("{}/composer", s.vendor_dir)); + + let composer_out = format!("{}/composer", s.vendor_dir); + dump(&mut s, package.into(), false, "_10").unwrap(); + + assert_file_content_equals( + fixtures_dir().join("include_paths.php").to_str().unwrap(), + &format!("{}/include_paths.php", composer_out), + ); } #[test] -#[ignore = "setUp needs mocked Config/InstallationManager/InstalledRepositoryInterface and TestCase tmp-dir helpers; no mock infra exists"] -fn test_override_vendors_autoloading() { - todo!() +#[serial] +fn test_include_path_file_without_paths_is_skipped() { + let mut s = set_up(); + let package = new_root_pkg("root/a"); + let a = new_pkg("a/a"); + s.set_canonical_packages(vec![a.into()]); + + s.ensure_dir(&format!("{}/composer", s.vendor_dir)); + + let composer_out = format!("{}/composer", s.vendor_dir); + dump(&mut s, package.into(), false, "_12").unwrap(); + + assert!(!std::path::Path::new(&format!("{}/include_paths.php", composer_out)).exists()); } #[test] -#[ignore = "setUp needs mocked Config/InstallationManager/InstalledRepositoryInterface and TestCase tmp-dir helpers; no mock infra exists"] -fn test_include_path_file_generation() { - todo!() +#[serial] +fn test_vendor_substring_path() { + let mut s = set_up(); + let package = new_root_pkg("root/a"); + package.set_autoload(autoload(vec![ + ( + "psr-0", + str_map(&[("Foo", pstr("composer-test-autoload-src/src"))]), + ), + ( + "psr-4", + str_map(&[("Acme\\Foo\\", pstr("composer-test-autoload-src/src-psr4"))]), + ), + ])); + + s.ensure_dir(&format!("{}/a", s.vendor_dir)); + + let composer_out = format!("{}/composer", s.vendor_dir); + dump(&mut s, package.into(), false, "VendorSubstring").unwrap(); + + let expected_namespace = "<?php\n\n// autoload_namespaces.php @generated by Composer\n\n$vendorDir = dirname(__DIR__);\n$baseDir = dirname($vendorDir);\n\nreturn array(\n 'Foo' => array($baseDir . '/composer-test-autoload-src/src'),\n);\n"; + let expected_psr4 = "<?php\n\n// autoload_psr4.php @generated by Composer\n\n$vendorDir = dirname(__DIR__);\n$baseDir = dirname($vendorDir);\n\nreturn array(\n 'Acme\\\\Foo\\\\' => array($baseDir . '/composer-test-autoload-src/src-psr4'),\n);\n"; + + assert_eq!( + expected_namespace, + std::fs::read_to_string(format!("{}/autoload_namespaces.php", composer_out)).unwrap() + ); + assert_eq!( + expected_psr4, + std::fs::read_to_string(format!("{}/autoload_psr4.php", composer_out)).unwrap() + ); } #[test] -#[ignore = "setUp needs mocked Config/InstallationManager/InstalledRepositoryInterface and TestCase tmp-dir helpers; no mock infra exists"] -fn test_include_paths_are_prepended_in_autoload_file() { - todo!() +#[serial] +fn test_empty_paths() { + let mut s = set_up(); + let package = new_root_pkg("root/a"); + package.set_autoload(autoload(vec![ + ("psr-0", str_map(&[("Foo", pstr(""))])), + ("psr-4", str_map(&[("Acme\\Foo\\", pstr(""))])), + ("classmap", str_list(&[""])), + ])); + + s.ensure_dir(&format!("{}/Foo", s.working_dir)); + s.put( + &format!("{}/Foo/Bar.php", s.working_dir), + "<?php namespace Foo; class Bar {}", + ); + s.put( + &format!("{}/class.php", s.working_dir), + "<?php namespace Classmap; class Foo {}", + ); + + let composer_out = format!("{}/composer", s.vendor_dir); + dump(&mut s, package.into(), true, "_15").unwrap(); + + let expected_namespace = "<?php\n\n// autoload_namespaces.php @generated by Composer\n\n$vendorDir = dirname(__DIR__);\n$baseDir = dirname($vendorDir);\n\nreturn array(\n 'Foo' => array($baseDir . '/'),\n);\n"; + let expected_psr4 = "<?php\n\n// autoload_psr4.php @generated by Composer\n\n$vendorDir = dirname(__DIR__);\n$baseDir = dirname($vendorDir);\n\nreturn array(\n 'Acme\\\\Foo\\\\' => array($baseDir . '/'),\n);\n"; + let expected_classmap = "<?php\n\n// autoload_classmap.php @generated by Composer\n\n$vendorDir = dirname(__DIR__);\n$baseDir = dirname($vendorDir);\n\nreturn array(\n 'Classmap\\\\Foo' => $baseDir . '/class.php',\n 'Composer\\\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',\n 'Foo\\\\Bar' => $baseDir . '/Foo/Bar.php',\n);\n"; + + assert_eq!( + expected_namespace, + std::fs::read_to_string(format!("{}/autoload_namespaces.php", composer_out)).unwrap() + ); + assert_eq!( + expected_psr4, + std::fs::read_to_string(format!("{}/autoload_psr4.php", composer_out)).unwrap() + ); + assert_eq!( + expected_classmap, + std::fs::read_to_string(format!("{}/autoload_classmap.php", composer_out)).unwrap() + ); } #[test] -#[ignore = "setUp needs mocked Config/InstallationManager/InstalledRepositoryInterface and TestCase tmp-dir helpers; no mock infra exists"] -fn test_include_paths_in_root_package() { - todo!() +#[serial] +#[ignore = "fixture assumes the symlinked composersrc/foo/bar tree (created via `ln -s` in PHP) and exercises exclude-from-classmap pattern matching that the port does not yet apply; symlink setup not replicated"] +fn test_exclude_from_classmap() { + let mut s = set_up(); + let package = new_root_pkg("root/a"); + package.set_autoload(autoload(vec![ + ( + "psr-0", + str_map(&[ + ("Main", pstr("src/")), + ("Lala", str_list(&["src/", "lib/"])), + ]), + ), + ( + "psr-4", + str_map(&[ + ("Acme\\Fruit\\", pstr("src-fruit/")), + ("Acme\\Cake\\", str_list(&["src-cake/", "lib-cake/"])), + ]), + ), + ("classmap", str_list(&["composersrc/"])), + ( + "exclude-from-classmap", + str_list(&[ + "/composersrc/foo/bar/", + "/composersrc/excludedTests/", + "/composersrc/ClassToExclude.php", + "/composersrc/*/excluded/excsubpath", + "**/excsubpath", + "composers", + "/src-ca/", + ]), + ), + ])); + + s.ensure_dir(&format!("{}/composer", s.working_dir)); + s.ensure_dir(&format!("{}/src/Lala/Test", s.working_dir)); + s.ensure_dir(&format!("{}/lib", s.working_dir)); + s.put( + &format!("{}/src/Lala/ClassMapMain.php", s.working_dir), + "<?php namespace Lala; class ClassMapMain {}", + ); + s.put( + &format!("{}/src/Lala/Test/ClassMapMainTest.php", s.working_dir), + "<?php namespace Lala\\Test; class ClassMapMainTest {}", + ); + + s.ensure_dir(&format!("{}/src-fruit", s.working_dir)); + s.ensure_dir(&format!("{}/src-cake", s.working_dir)); + s.ensure_dir(&format!("{}/lib-cake", s.working_dir)); + s.put( + &format!("{}/src-cake/ClassMapBar.php", s.working_dir), + "<?php namespace Acme\\Cake; class ClassMapBar {}", + ); + + s.ensure_dir(&format!("{}/composersrc", s.working_dir)); + s.ensure_dir(&format!("{}/composersrc/tests", s.working_dir)); + s.put( + &format!("{}/composersrc/foo.php", s.working_dir), + "<?php class ClassMapFoo {}", + ); + + s.ensure_dir(&format!("{}/composersrc/excludedTests", s.working_dir)); + s.put( + &format!("{}/composersrc/excludedTests/bar.php", s.working_dir), + "<?php class ClassExcludeMapFoo {}", + ); + s.put( + &format!("{}/composersrc/ClassToExclude.php", s.working_dir), + "<?php class ClassClassToExclude {}", + ); + s.ensure_dir(&format!( + "{}/composersrc/long/excluded/excsubpath", + s.working_dir + )); + s.put( + &format!( + "{}/composersrc/long/excluded/excsubpath/foo.php", + s.working_dir + ), + "<?php class ClassExcludeMapFoo2 {}", + ); + s.put( + &format!( + "{}/composersrc/long/excluded/excsubpath/bar.php", + s.working_dir + ), + "<?php class ClassExcludeMapBar {}", + ); + + s.ensure_dir(&format!("{}/composersrc/foo", s.working_dir)); + + let composer_out = format!("{}/composer", s.vendor_dir); + dump(&mut s, package.into(), true, "_1").unwrap(); + + assert_autoload_files("classmap", &composer_out, "classmap"); } +// These remain ignored: they need test infrastructure not yet ported. +// +// - testFilesAutoloadOrderByDependencies / testFilesAutoloadGeneration's `require autoload.php` +// + function_exists assertions: PHP runtime require is unportable (composer_require todo!()). +// - testFilesAutoloadGenerationRemoveExtraEntitiesFromAutoloadFiles: needs getCanonicalPackages +// returnValueMap over consecutive calls (the repo mock yields different package sets per call). +// - testIncludePathsArePrependedInAutoloadFile / testIncludePathsInRootPackage / +// testUseGlobalIncludePath: assert PHP's get_include_path() after `require autoload.php`. +// - testPreAndPostEventsAreDispatchedDuringAutoloadDump: EventDispatcher::dispatchScript spy. +// - testVendorDirExcludedFromWorkingDir / testUpLevelRelativePaths: chdir into a nested working dir +// with a custom getInstallPath using a different vendor dir. +// - testAutoloadRulesInPackageThatDoesNotExistOnDisk: exercises buildPackageMap/parseAutoloads +// directly plus a CompletePackage; multi-dump with mutation. +// - testGeneratesPlatformCheck: data-provider over many platform-requirement scenarios. +// - testAbsoluteSymlinkWith*: create real filesystem symlinks. + #[test] -#[ignore = "setUp needs mocked Config/InstallationManager/InstalledRepositoryInterface and TestCase tmp-dir helpers; no mock infra exists"] -fn test_include_path_file_without_paths_is_skipped() { +#[ignore = "require autoload.php + function_exists() assertions are unportable (composer_require todo!())"] +fn test_files_autoload_order_by_dependencies() { todo!() } #[test] -#[ignore = "setUp needs mocked Config/InstallationManager/InstalledRepositoryInterface plus EventDispatcher::dispatch expectations; no mock infra exists"] -fn test_pre_and_post_events_are_dispatched_during_autoload_dump() { +#[ignore = "needs getCanonicalPackages consecutive-call return values (different package set per dump)"] +fn test_files_autoload_generation_remove_extra_entities_from_autoload_files() { todo!() } #[test] -#[ignore = "setUp needs mocked Config/InstallationManager/InstalledRepositoryInterface and TestCase tmp-dir helpers; no mock infra exists"] -fn test_use_global_include_path() { +#[ignore = "asserts PHP get_include_path() after require autoload.php"] +fn test_include_paths_are_prepended_in_autoload_file() { todo!() } #[test] -#[ignore = "setUp needs mocked Config/InstallationManager/InstalledRepositoryInterface and TestCase tmp-dir helpers; no mock infra exists"] -fn test_vendor_dir_excluded_from_working_dir() { +#[ignore = "asserts PHP get_include_path() after require autoload.php"] +fn test_include_paths_in_root_package() { todo!() } #[test] -#[ignore = "setUp needs mocked Config/InstallationManager/InstalledRepositoryInterface and TestCase tmp-dir helpers; no mock infra exists"] -fn test_up_level_relative_paths() { +#[ignore = "EventDispatcher::dispatchScript spy not modeled"] +fn test_pre_and_post_events_are_dispatched_during_autoload_dump() { todo!() } #[test] -#[ignore = "setUp needs mocked Config/InstallationManager/InstalledRepositoryInterface and TestCase tmp-dir helpers; no mock infra exists"] -fn test_autoload_rules_in_package_that_does_not_exist_on_disk() { +#[ignore = "asserts PHP get_include_path()/require behavior with use-include-path"] +fn test_use_global_include_path() { todo!() } #[test] -#[ignore = "setUp needs mocked Config/InstallationManager/InstalledRepositoryInterface and TestCase tmp-dir helpers; no mock infra exists"] -fn test_empty_paths() { +#[ignore = "needs nested working dir + custom getInstallPath vendor dir"] +fn test_vendor_dir_excluded_from_working_dir() { todo!() } #[test] -#[ignore = "setUp needs mocked Config/InstallationManager/InstalledRepositoryInterface and TestCase tmp-dir helpers; no mock infra exists"] -fn test_vendor_substring_path() { +#[ignore = "needs nested working dir chdir + up-level relative path fixtures"] +fn test_up_level_relative_paths() { todo!() } #[test] -#[ignore = "setUp needs mocked Config/InstallationManager/InstalledRepositoryInterface and TestCase tmp-dir helpers; no mock infra exists"] -fn test_exclude_from_classmap() { +#[ignore = "exercises buildPackageMap/parseAutoloads directly with multi-dump mutation"] +fn test_autoload_rules_in_package_that_does_not_exist_on_disk() { todo!() } #[test] -#[ignore = "setUp needs mocked Config/InstallationManager/InstalledRepositoryInterface and TestCase tmp-dir helpers; no mock infra exists"] +#[ignore = "data-provider over platform-requirement scenarios"] fn test_generates_platform_check() { todo!() } #[test] -#[ignore = "setUp needs mocked Config/InstallationManager/InstalledRepositoryInterface and TestCase tmp-dir helpers; no mock infra exists"] +#[ignore = "creates real filesystem symlinks"] fn test_absolute_symlink_with_psr4_does_not_generate_warnings() { todo!() } #[test] -#[ignore = "setUp needs mocked Config/InstallationManager/InstalledRepositoryInterface and TestCase tmp-dir helpers; no mock infra exists"] +#[ignore = "creates real filesystem symlinks"] fn test_absolute_symlink_with_classmap_exclude_from_classmap() { todo!() } diff --git a/crates/shirabe/tests/autoload/main.rs b/crates/shirabe/tests/autoload/main.rs index ebfa8e3..cc67e9a 100644 --- a/crates/shirabe/tests/autoload/main.rs +++ b/crates/shirabe/tests/autoload/main.rs @@ -1,2 +1,5 @@ +#[path = "../common/config_stub.rs"] +mod config_stub; + mod autoload_generator_test; mod class_loader_test; |
