aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe/tests/package
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/package
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/package')
-rw-r--r--crates/shirabe/tests/package/archiver/archivable_files_finder_test.rs236
-rw-r--r--crates/shirabe/tests/package/archiver/archive_manager_test.rs10
-rw-r--r--crates/shirabe/tests/package/archiver/phar_archiver_test.rs125
-rw-r--r--crates/shirabe/tests/package/archiver/zip_archiver_test.rs176
-rw-r--r--crates/shirabe/tests/package/base_package_test.rs41
-rw-r--r--crates/shirabe/tests/package/dumper/array_dumper_test.rs13
6 files changed, 535 insertions, 66 deletions
diff --git a/crates/shirabe/tests/package/archiver/archivable_files_finder_test.rs b/crates/shirabe/tests/package/archiver/archivable_files_finder_test.rs
index 48f0fc5..aed0dc3 100644
--- a/crates/shirabe/tests/package/archiver/archivable_files_finder_test.rs
+++ b/crates/shirabe/tests/package/archiver/archivable_files_finder_test.rs
@@ -1,45 +1,235 @@
//! ref: composer/tests/Composer/Test/Package/Archiver/ArchivableFilesFinderTest.php
-/// Builds a temp directory tree of fixture files under a unique tmp dir; the Filesystem and
-/// getUniqueTmpDirectory infrastructure is not ported.
-#[allow(dead_code)]
-fn set_up() -> String {
- todo!()
-}
+use shirabe::package::archiver::ArchivableFilesFinder;
+use shirabe::util::Filesystem;
+use shirabe_external_packages::composer::pcre::Preg;
+use shirabe_php_shim::{dirname, file_put_contents, preg_quote};
+use tempfile::TempDir;
-#[allow(dead_code)]
-fn tear_down(_sources: &str) {
- // Removes the temp directory tree created in set_up.
- todo!()
+struct SetUp {
+ _sources_dir: TempDir,
+ sources: String,
+ fs: Filesystem,
}
-#[allow(dead_code)]
-struct TearDown {
- sources: String,
+fn set_up() -> SetUp {
+ let mut fs = Filesystem::new(None);
+
+ let sources_dir = TempDir::new().unwrap();
+ let sources = fs.normalize_path(&sources_dir.path().canonicalize().unwrap().to_string_lossy());
+
+ let file_tree = [
+ ".foo",
+ "A/prefixA.foo",
+ "A/prefixB.foo",
+ "A/prefixC.foo",
+ "A/prefixD.foo",
+ "A/prefixE.foo",
+ "A/prefixF.foo",
+ "B/sub/prefixA.foo",
+ "B/sub/prefixB.foo",
+ "B/sub/prefixC.foo",
+ "B/sub/prefixD.foo",
+ "B/sub/prefixE.foo",
+ "B/sub/prefixF.foo",
+ "C/prefixA.foo",
+ "C/prefixB.foo",
+ "C/prefixC.foo",
+ "C/prefixD.foo",
+ "C/prefixE.foo",
+ "C/prefixF.foo",
+ "D/prefixA",
+ "D/prefixB",
+ "D/prefixC",
+ "D/prefixD",
+ "D/prefixE",
+ "D/prefixF",
+ "E/subtestA.foo",
+ "F/subtestA.foo",
+ "G/subtestA.foo",
+ "H/subtestA.foo",
+ "I/J/subtestA.foo",
+ "K/dirJ/subtestA.foo",
+ "toplevelA.foo",
+ "toplevelB.foo",
+ "prefixA.foo",
+ "prefixB.foo",
+ "prefixC.foo",
+ "prefixD.foo",
+ "prefixE.foo",
+ "prefixF.foo",
+ "parameters.yml",
+ "parameters.yml.dist",
+ "!important!.txt",
+ "!important_too!.txt",
+ "#weirdfile",
+ ];
+
+ for relative_path in file_tree {
+ let path = format!("{}/{}", sources, relative_path);
+ fs.ensure_directory_exists(&dirname(&path)).unwrap();
+ file_put_contents(&path, b"");
+ }
+
+ SetUp {
+ _sources_dir: sources_dir,
+ sources,
+ fs,
+ }
}
-impl Drop for TearDown {
- fn drop(&mut self) {
- tear_down(&self.sources);
+fn get_archivable_files(set_up: &SetUp, finder: ArchivableFilesFinder) -> Vec<String> {
+ let mut files: Vec<String> = vec![];
+ for file in finder {
+ if !file.is_dir() {
+ let real_path = file.canonicalize().unwrap();
+ files.push(Preg::replace(
+ &format!("#^{}#", preg_quote(&set_up.sources, Some('#'))),
+ "",
+ &set_up.fs.normalize_path(&real_path.to_string_lossy()),
+ ));
+ }
}
+
+ files.sort();
+
+ files
+}
+
+fn assert_archivable_files(set_up: &SetUp, finder: ArchivableFilesFinder, expected_files: &[&str]) {
+ let actual_files = get_archivable_files(set_up, finder);
+
+ let expected_files: Vec<String> = expected_files.iter().map(|s| s.to_string()).collect();
+ assert_eq!(expected_files, actual_files);
}
-// These set up a temp directory tree (including a git repo) and assert the files the finder
-// selects with manual/git/skip excludes; the git-backed fixture setup is not ported.
-#[ignore = "setUp needs TestCase::getUniqueTmpDirectory to build the on-disk fixture tree; not ported"]
+// The manual exclude patterns (e.g. `.*`, `prefixC.*`) compile, via ComposerExcludeFilter, to
+// look-ahead regexes like `(?=[^\.])...(?=$|/)`, which the regex crate cannot compile.
+#[ignore = "ComposerExcludeFilter builds look-ahead regexes the regex crate does not support"]
#[test]
fn test_manual_excludes() {
- todo!()
+ let set_up = set_up();
+
+ let excludes = vec![
+ "prefixB.foo".to_string(),
+ "!/prefixB.foo".to_string(),
+ "/prefixA.foo".to_string(),
+ "prefixC.*".to_string(),
+ "!*/*/*/prefixC.foo".to_string(),
+ ".*".to_string(),
+ ];
+
+ let finder = ArchivableFilesFinder::new(&set_up.sources, excludes, false).unwrap();
+
+ assert_archivable_files(
+ &set_up,
+ finder,
+ &[
+ "/!important!.txt",
+ "/!important_too!.txt",
+ "/#weirdfile",
+ "/A/prefixA.foo",
+ "/A/prefixD.foo",
+ "/A/prefixE.foo",
+ "/A/prefixF.foo",
+ "/B/sub/prefixA.foo",
+ "/B/sub/prefixC.foo",
+ "/B/sub/prefixD.foo",
+ "/B/sub/prefixE.foo",
+ "/B/sub/prefixF.foo",
+ "/C/prefixA.foo",
+ "/C/prefixD.foo",
+ "/C/prefixE.foo",
+ "/C/prefixF.foo",
+ "/D/prefixA",
+ "/D/prefixB",
+ "/D/prefixC",
+ "/D/prefixD",
+ "/D/prefixE",
+ "/D/prefixF",
+ "/E/subtestA.foo",
+ "/F/subtestA.foo",
+ "/G/subtestA.foo",
+ "/H/subtestA.foo",
+ "/I/J/subtestA.foo",
+ "/K/dirJ/subtestA.foo",
+ "/parameters.yml",
+ "/parameters.yml.dist",
+ "/prefixB.foo",
+ "/prefixD.foo",
+ "/prefixE.foo",
+ "/prefixF.foo",
+ "/toplevelA.foo",
+ "/toplevelB.foo",
+ ],
+ );
}
-#[ignore = "setUp needs TestCase::getUniqueTmpDirectory plus skipIfNotExecutable/Process::fromShellCommandline/PharData/RecursiveIteratorIterator; none ported"]
+// getArchivedFiles drives a git pipeline (Process::fromShellCommandline) and reads the produced
+// zip back through PharData + RecursiveIteratorIterator; neither the process helper nor the zip
+// archive reader is ported, so this case cannot run.
+#[ignore = "getArchivedFiles needs a git process pipeline plus PharData/RecursiveIteratorIterator zip reading; not ported"]
#[test]
fn test_git_excludes() {
todo!()
}
-#[ignore = "setUp needs TestCase::getUniqueTmpDirectory to build the on-disk fixture tree; not ported"]
#[test]
fn test_skip_excludes() {
- todo!()
+ let set_up = set_up();
+
+ let excludes = vec!["prefixB.foo".to_string()];
+
+ let finder = ArchivableFilesFinder::new(&set_up.sources, excludes, true).unwrap();
+
+ assert_archivable_files(
+ &set_up,
+ finder,
+ &[
+ "/!important!.txt",
+ "/!important_too!.txt",
+ "/#weirdfile",
+ "/.foo",
+ "/A/prefixA.foo",
+ "/A/prefixB.foo",
+ "/A/prefixC.foo",
+ "/A/prefixD.foo",
+ "/A/prefixE.foo",
+ "/A/prefixF.foo",
+ "/B/sub/prefixA.foo",
+ "/B/sub/prefixB.foo",
+ "/B/sub/prefixC.foo",
+ "/B/sub/prefixD.foo",
+ "/B/sub/prefixE.foo",
+ "/B/sub/prefixF.foo",
+ "/C/prefixA.foo",
+ "/C/prefixB.foo",
+ "/C/prefixC.foo",
+ "/C/prefixD.foo",
+ "/C/prefixE.foo",
+ "/C/prefixF.foo",
+ "/D/prefixA",
+ "/D/prefixB",
+ "/D/prefixC",
+ "/D/prefixD",
+ "/D/prefixE",
+ "/D/prefixF",
+ "/E/subtestA.foo",
+ "/F/subtestA.foo",
+ "/G/subtestA.foo",
+ "/H/subtestA.foo",
+ "/I/J/subtestA.foo",
+ "/K/dirJ/subtestA.foo",
+ "/parameters.yml",
+ "/parameters.yml.dist",
+ "/prefixA.foo",
+ "/prefixB.foo",
+ "/prefixC.foo",
+ "/prefixD.foo",
+ "/prefixE.foo",
+ "/prefixF.foo",
+ "/toplevelA.foo",
+ "/toplevelB.foo",
+ ],
+ );
}
diff --git a/crates/shirabe/tests/package/archiver/archive_manager_test.rs b/crates/shirabe/tests/package/archiver/archive_manager_test.rs
index 2712da6..fdc4bf0 100644
--- a/crates/shirabe/tests/package/archiver/archive_manager_test.rs
+++ b/crates/shirabe/tests/package/archiver/archive_manager_test.rs
@@ -29,31 +29,31 @@ impl Drop for TearDown {
// the filename-derivation helpers over packages; the archiving and fixture setup are not
// ported.
#[test]
-#[ignore = "setupPackage requires CompletePackage::setSourceType, not exposed on the package handle API; also needs Factory-built ArchiveManager (set_up) which is unported"]
+#[ignore = "needs the Factory/FactoryMock-built ArchiveManager (createDownloadManager/createHttpDownloader/FactoryMock::createConfig) in set_up, which is unported"]
fn test_unknown_format() {
todo!()
}
#[test]
-#[ignore = "needs setupGitRepo + PharData tar archiving and Factory-built ArchiveManager (set_up), and setupPackage's setSourceType which is not exposed on the package handle API"]
+#[ignore = "needs setupGitRepo + PharData tar archiving and the Factory/FactoryMock-built ArchiveManager (set_up), which is unported"]
fn test_archive_tar() {
todo!()
}
#[test]
-#[ignore = "needs setupGitRepo + PharData tar archiving and Factory-built ArchiveManager (set_up), and setupPackage's setSourceType which is not exposed on the package handle API"]
+#[ignore = "needs setupGitRepo + PharData tar archiving and the Factory/FactoryMock-built ArchiveManager (set_up), which is unported"]
fn test_archive_custom_file_name() {
todo!()
}
#[test]
-#[ignore = "setupPackage requires CompletePackage::setSourceType, not exposed on the package handle API; also needs Factory-built ArchiveManager (set_up) which is unported"]
+#[ignore = "needs the Factory/FactoryMock-built ArchiveManager (createDownloadManager/createHttpDownloader/FactoryMock::createConfig) in set_up, which is unported"]
fn test_get_package_filename_parts() {
todo!()
}
#[test]
-#[ignore = "setupPackage requires CompletePackage::setSourceType, not exposed on the package handle API; also needs Factory-built ArchiveManager (set_up) which is unported"]
+#[ignore = "needs the Factory/FactoryMock-built ArchiveManager (createDownloadManager/createHttpDownloader/FactoryMock::createConfig) in set_up, which is unported"]
fn test_get_package_filename() {
todo!()
}
diff --git a/crates/shirabe/tests/package/archiver/phar_archiver_test.rs b/crates/shirabe/tests/package/archiver/phar_archiver_test.rs
index 385177b..fe6185d 100644
--- a/crates/shirabe/tests/package/archiver/phar_archiver_test.rs
+++ b/crates/shirabe/tests/package/archiver/phar_archiver_test.rs
@@ -1,13 +1,130 @@
//! ref: composer/tests/Composer/Test/Package/Archiver/PharArchiverTest.php
-#[ignore = "setUp/setupDummyRepo need TestCase::getUniqueTmpDirectory plus Filesystem to build the on-disk fixture tree; not ported"]
+use shirabe::package::archiver::{ArchiverInterface, PharArchiver};
+use shirabe::package::handle::CompletePackageHandle;
+use shirabe::util::{Filesystem, Platform};
+use shirabe_php_shim::{dirname, file_exists, file_put_contents, mkdir, realpath};
+use tempfile::TempDir;
+
+// ref: ArchiverTestCase.
+struct ArchiverTestCase {
+ filesystem: Filesystem,
+ test_dir: String,
+ _test_dir_guard: TempDir,
+}
+
+impl ArchiverTestCase {
+ fn set_up() -> Self {
+ let guard = TempDir::new().unwrap();
+ let test_dir = guard.path().to_string_lossy().to_string();
+ Self {
+ filesystem: Filesystem::new(None),
+ test_dir,
+ _test_dir_guard: guard,
+ }
+ }
+
+ fn setup_package(&self) -> CompletePackageHandle {
+ let package = CompletePackageHandle::new(
+ "archivertest/archivertest".to_string(),
+ "master".to_string(),
+ "master".to_string(),
+ );
+ package.set_source_url(Some(realpath(&self.test_dir).unwrap_or_default()));
+ package.set_source_reference(Some("master".to_string()));
+ package.__set_source_type(Some("git".to_string()));
+
+ package
+ }
+
+ fn setup_dummy_repo(&self) {
+ let current_work_dir = Platform::get_cwd(false).unwrap();
+ std::env::set_current_dir(&self.test_dir).unwrap();
+
+ self.write_file("file.txt", "content", &current_work_dir);
+ self.write_file("foo/bar/baz", "content", &current_work_dir);
+ self.write_file("foo/bar/ignoreme", "content", &current_work_dir);
+ self.write_file("x/baz", "content", &current_work_dir);
+ self.write_file("x/includeme", "content", &current_work_dir);
+
+ std::env::set_current_dir(&current_work_dir).unwrap();
+ }
+
+ fn write_file(&self, path: &str, content: &str, current_work_dir: &str) {
+ if !file_exists(dirname(path)) {
+ mkdir(&dirname(path), 0o777, true);
+ }
+
+ let result = file_put_contents(path, content.as_bytes());
+ if result.is_none() {
+ std::env::set_current_dir(current_work_dir).unwrap();
+ panic!("Could not save file.");
+ }
+ }
+}
+
+#[ignore = "PharArchiver::archive builds the archive via PharData, which is todo!() in the php-shim"]
#[test]
fn test_tar_archive() {
- todo!()
+ let mut test_case = ArchiverTestCase::set_up();
+
+ test_case.setup_dummy_repo();
+ let package = test_case.setup_package();
+ let target_dir = TempDir::new().unwrap();
+ let target = format!(
+ "{}/composer_archiver_test.tar",
+ target_dir.path().to_string_lossy()
+ );
+
+ let archiver = PharArchiver::new();
+ archiver
+ .archive(
+ package.get_source_url().unwrap(),
+ target.clone(),
+ "tar".to_string(),
+ vec![
+ "foo/bar".to_string(),
+ "baz".to_string(),
+ "!/foo/bar/baz".to_string(),
+ ],
+ false,
+ )
+ .unwrap();
+ assert!(file_exists(&target));
+
+ test_case
+ .filesystem
+ .remove_directory(dirname(&target))
+ .unwrap();
}
-#[ignore = "setUp/setupDummyRepo need TestCase::getUniqueTmpDirectory plus Filesystem to build the on-disk fixture tree; not ported"]
+#[ignore = "PharArchiver::archive builds the archive via PharData, which is todo!() in the php-shim"]
#[test]
fn test_zip_archive() {
- todo!()
+ let mut test_case = ArchiverTestCase::set_up();
+
+ test_case.setup_dummy_repo();
+ let package = test_case.setup_package();
+ let target_dir = TempDir::new().unwrap();
+ let target = format!(
+ "{}/composer_archiver_test.zip",
+ target_dir.path().to_string_lossy()
+ );
+
+ let archiver = PharArchiver::new();
+ archiver
+ .archive(
+ package.get_source_url().unwrap(),
+ target.clone(),
+ "zip".to_string(),
+ vec![],
+ false,
+ )
+ .unwrap();
+ assert!(file_exists(&target));
+
+ test_case
+ .filesystem
+ .remove_directory(dirname(&target))
+ .unwrap();
}
diff --git a/crates/shirabe/tests/package/archiver/zip_archiver_test.rs b/crates/shirabe/tests/package/archiver/zip_archiver_test.rs
index 5b51ce9..7785976 100644
--- a/crates/shirabe/tests/package/archiver/zip_archiver_test.rs
+++ b/crates/shirabe/tests/package/archiver/zip_archiver_test.rs
@@ -1,46 +1,174 @@
//! ref: composer/tests/Composer/Test/Package/Archiver/ZipArchiverTest.php
-/// Creates the Filesystem/ProcessExecutor and a unique tmp testDir; that infrastructure is
-/// not ported. Returns testDir.
-#[allow(dead_code)]
-fn set_up() -> String {
- todo!()
-}
-
-/// Unlinks the zip files collected in filesToCleanup, then (parent) removes testDir.
-#[allow(dead_code)]
-fn tear_down(_files_to_cleanup: &[String], _test_dir: &str) {
- todo!()
-}
+use indexmap::IndexMap;
+use shirabe::package::archiver::{ArchiverInterface, ZipArchiver};
+use shirabe::package::handle::CompletePackageHandle;
+use shirabe::util::Platform;
+use shirabe_php_shim::{
+ ZipArchive, class_exists, dirname, file_exists, file_put_contents, mkdir, realpath,
+ sys_get_temp_dir, unlink,
+};
+use tempfile::TempDir;
-#[allow(dead_code)]
-struct TearDown {
- files_to_cleanup: Vec<String>,
+// ref: ArchiverTestCase. Holds the unique tmp testDir plus the ZipArchiverTest cleanup list.
+struct ArchiverTestCase {
test_dir: String,
+ _test_dir_guard: TempDir,
+ files_to_cleanup: Vec<String>,
}
-impl Drop for TearDown {
+impl Drop for ArchiverTestCase {
fn drop(&mut self) {
- tear_down(&self.files_to_cleanup, &self.test_dir);
+ for file in &self.files_to_cleanup {
+ unlink(file);
+ }
}
}
-// ZipArchiver::archive builds a zip via ZipArchive, which is todo!() in the php-shim.
+impl ArchiverTestCase {
+ fn set_up() -> Self {
+ let guard = TempDir::new().unwrap();
+ let test_dir = guard.path().to_string_lossy().to_string();
+ Self {
+ test_dir,
+ _test_dir_guard: guard,
+ files_to_cleanup: vec![],
+ }
+ }
+
+ fn setup_package(&self) -> CompletePackageHandle {
+ let package = CompletePackageHandle::new(
+ "archivertest/archivertest".to_string(),
+ "master".to_string(),
+ "master".to_string(),
+ );
+ package.set_source_url(Some(realpath(&self.test_dir).unwrap_or_default()));
+ package.set_source_reference(Some("master".to_string()));
+ package.__set_source_type(Some("git".to_string()));
+
+ package
+ }
+ fn assert_zip_archive(&mut self, mut files: IndexMap<String, Option<String>>) {
+ if !class_exists("ZipArchive") {
+ // markTestSkipped('Cannot run ZipArchiverTest, missing class "ZipArchive".')
+ return;
+ }
+
+ self.setup_dummy_repo(&mut files);
+ let package = self.setup_package();
+ let target = format!("{}/composer_archiver_test.zip", sys_get_temp_dir());
+ self.files_to_cleanup.push(target.clone());
+
+ let archiver = ZipArchiver::new();
+ archiver
+ .archive(
+ package.get_source_url().unwrap(),
+ target.clone(),
+ "zip".to_string(),
+ vec![],
+ false,
+ )
+ .unwrap();
+ assert!(file_exists(&target));
+ let mut zip = ZipArchive::new();
+ let res = zip.open(&target, 0);
+ assert!(res.is_ok(), "Failed asserting that Zip file can be opened");
+
+ let mut zip_contents: IndexMap<String, Option<String>> = IndexMap::new();
+ for i in 0..zip.num_files {
+ let path = zip.get_name_index(i);
+ zip_contents.insert(path.clone(), zip.get_from_name(&path));
+ }
+ zip.close();
+
+ let files: IndexMap<String, Option<String>> = files;
+ assert_eq!(
+ files, zip_contents,
+ "Failed asserting that Zip created with the ZipArchiver contains all files from the repository."
+ );
+ }
+
+ fn setup_dummy_repo(&self, files: &mut IndexMap<String, Option<String>>) {
+ let current_work_dir = Platform::get_cwd(false).unwrap();
+ std::env::set_current_dir(&self.test_dir).unwrap();
+ let paths: Vec<String> = files.keys().cloned().collect();
+ for path in paths {
+ if files[&path].is_none() {
+ files.insert(path.clone(), Some("content".to_string()));
+ }
+ self.write_file(&path, files[&path].clone().unwrap(), &current_work_dir);
+ }
+
+ std::env::set_current_dir(&current_work_dir).unwrap();
+ }
+
+ fn write_file(&self, path: &str, content: String, current_work_dir: &str) {
+ if !file_exists(dirname(path)) {
+ mkdir(&dirname(path), 0o777, true);
+ }
+
+ let result = file_put_contents(path, content.as_bytes());
+ if result.is_none() {
+ std::env::set_current_dir(current_work_dir).unwrap();
+ panic!("Could not save file.");
+ }
+ }
+}
+
+#[ignore = "ZipArchiver::archive and the ZipArchive reader (open/get_from_name/...) are todo!() in the php-shim"]
#[test]
-#[ignore = "ArchiverTestCase infrastructure (setup_package/setup_dummy_repo/test_dir) not ported; ZipArchive shim lacks get_from_name"]
fn test_simple_files() {
- todo!()
+ let mut test_case = ArchiverTestCase::set_up();
+
+ let mut files: IndexMap<String, Option<String>> = IndexMap::new();
+ files.insert("file.txt".to_string(), None);
+ files.insert("foo/bar/baz".to_string(), None);
+ files.insert("x/baz".to_string(), None);
+ files.insert("x/includeme".to_string(), None);
+
+ if !Platform::is_windows() {
+ files.insert(
+ format!("zfoo{}/file.txt", Platform::get_cwd(false).unwrap()),
+ None,
+ );
+ }
+
+ test_case.assert_zip_archive(files);
}
+#[ignore = "ZipArchiver::archive and the ZipArchive reader (open/get_from_name/...) are todo!() in the php-shim"]
#[test]
-#[ignore = "ArchiverTestCase infrastructure (setup_package/setup_dummy_repo/test_dir) not ported; ZipArchive shim lacks get_from_name"]
fn test_gitignore_exclude_negation() {
- todo!()
+ for include in ["!/docs", "!/docs/"] {
+ let mut test_case = ArchiverTestCase::set_up();
+
+ let mut files: IndexMap<String, Option<String>> = IndexMap::new();
+ files.insert(
+ ".gitignore".to_string(),
+ Some(format!("/*\n.*\n!.git*\n{}", include)),
+ );
+ files.insert("docs/README.md".to_string(), Some("# The doc".to_string()));
+
+ test_case.assert_zip_archive(files);
+ }
}
+#[ignore = "ZipArchiver::archive and the ZipArchive reader (open/get_from_name/...) are todo!() in the php-shim"]
#[test]
-#[ignore = "ArchiverTestCase infrastructure (setup_package/setup_dummy_repo/test_dir) not ported; ZipArchive shim lacks get_from_name"]
fn test_folder_with_backslashes() {
- todo!()
+ if Platform::is_windows() {
+ // markTestSkipped('Folder names cannot contain backslashes on Windows.')
+ return;
+ }
+
+ let mut test_case = ArchiverTestCase::set_up();
+
+ let mut files: IndexMap<String, Option<String>> = IndexMap::new();
+ files.insert(
+ "folder\\with\\backslashes/README.md".to_string(),
+ Some("# doc".to_string()),
+ );
+
+ test_case.assert_zip_archive(files);
}
diff --git a/crates/shirabe/tests/package/base_package_test.rs b/crates/shirabe/tests/package/base_package_test.rs
index 1056de1..16d3a5b 100644
--- a/crates/shirabe/tests/package/base_package_test.rs
+++ b/crates/shirabe/tests/package/base_package_test.rs
@@ -1,7 +1,10 @@
//! ref: composer/tests/Composer/Test/Package/BasePackageTest.php
+use shirabe::package::DisplayMode;
use shirabe::package::base_package::package_names_to_regexp;
+use shirabe::package::handle::PackageHandle;
use shirabe::repository::{ArrayRepository, RepositoryInterfaceHandle};
+use shirabe_semver::version_parser::VersionParser;
use crate::test_case::get_package;
@@ -31,14 +34,40 @@ fn test_set_another_repository() {
assert!(package.set_repository(repository2.clone()).is_err());
}
-// In PHP this mocks isDev()/getSourceType()/getPrettyVersion()/getSourceReference()
-// on an abstract BasePackage to drive getFullPrettyVersion(). Reproducing those exact
-// getter values requires mocking; a real package cannot carry the pretty version
-// "PrettyVersion" together with isDev() == true.
-#[ignore = "requires mocking isDev/getSourceType/getPrettyVersion/getSourceReference on an abstract BasePackage; no mock infrastructure exists and a real package cannot carry prettyVersion \"PrettyVersion\" with isDev() == true"]
+// PHP mocks isDev()/getSourceType()/getPrettyVersion()/getSourceReference() on an abstract
+// BasePackage. A real Package reproduces the same observable getters: a "dev-master" version makes
+// isDev() true, while the pretty version is an independent constructor argument.
#[test]
fn test_format_version_for_dev_package() {
- todo!()
+ let cases: Vec<(&str, bool, &str)> = vec![
+ ("v2.1.0-RC2", true, "PrettyVersion v2.1.0-RC2"),
+ (
+ "bbf527a27356414bfa9bf520f018c5cb7af67c77",
+ true,
+ "PrettyVersion bbf527a",
+ ),
+ ("v1.0.0", false, "PrettyVersion v1.0.0"),
+ (
+ "bbf527a27356414bfa9bf520f018c5cb7af67c77",
+ false,
+ "PrettyVersion bbf527a27356414bfa9bf520f018c5cb7af67c77",
+ ),
+ ];
+
+ for (source_reference, truncate, expected) in cases {
+ let package = PackageHandle::new(
+ "dummy/pkg".to_string(),
+ VersionParser.normalize("dev-master", None).unwrap(),
+ "PrettyVersion".to_string(),
+ );
+ package.__set_source_type(Some("git".to_string()));
+ package.set_source_reference(Some(source_reference.to_string()));
+
+ assert_eq!(
+ expected,
+ package.get_full_pretty_version(truncate, DisplayMode::SourceRefIfDev)
+ );
+ }
}
#[test]
diff --git a/crates/shirabe/tests/package/dumper/array_dumper_test.rs b/crates/shirabe/tests/package/dumper/array_dumper_test.rs
index 64880f1..1e5fd05 100644
--- a/crates/shirabe/tests/package/dumper/array_dumper_test.rs
+++ b/crates/shirabe/tests/package/dumper/array_dumper_test.rs
@@ -79,11 +79,16 @@ fn test_dump_abandoned_replacement() {
);
}
-// PHP drives ~25 heterogeneous setters dynamically (set{ucfirst(method)}) across strings,
-// arrays, a DateTime and Link maps, then checks the corresponding dumped key. Reproducing
-// that dynamic dispatch faithfully would require per-case wiring for every property type.
+// PHP drives 26 heterogeneous setters dynamically (set{ucfirst(method)}) across strings,
+// arrays, a DateTime and Link maps, then checks the corresponding dumped key. Three of the
+// data sets cannot be expressed faithfully because the ported production types were narrowed
+// from PHP's loose `array`: the `authors` set passes plain strings (Rust set_authors wants
+// Vec<IndexMap<String,String>>), `scripts` passes a bare string value (set_scripts wants
+// IndexMap<String,Vec<String>>), and `funding` passes a single map (set_funding wants
+// Vec<IndexMap<String,PhpMixed>>); the dumper additionally re-wraps each of these. Porting the
+// remaining 23 would drop those three cases, so testKeys stays unported (all-or-nothing).
#[test]
-#[ignore = "RootPackageHandle lacks set_type/set_release_date/set_binaries/set_php_ext setters required by the data provider's type/time/bin/php-ext cases"]
+#[ignore = "authors/scripts/funding data sets pass loosely-typed PHP arrays the narrowed Rust set_authors/set_scripts/set_funding types cannot represent, and the dumper re-wraps them; faithful all-or-nothing port blocked without loosening those production types"]
fn test_keys() {
todo!()
}