diff options
| author | nsfisis <nsfisis@gmail.com> | 2026-06-25 17:49:35 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2026-06-26 00:20:05 +0900 |
| commit | d4ec1dcb6fc04ff029ded35cc2fcc14f3bbc02ad (patch) | |
| tree | 0a85bd085961fcdfd5570cafc3b44ba5eb8cb152 /crates/shirabe/tests/downloader/hg_downloader_test.rs | |
| parent | 22d0b327368e5f39de6f381046c081d08efdba15 (diff) | |
| download | php-shirabe-d4ec1dcb6fc04ff029ded35cc2fcc14f3bbc02ad.tar.gz php-shirabe-d4ec1dcb6fc04ff029ded35cc2fcc14f3bbc02ad.tar.zst php-shirabe-d4ec1dcb6fc04ff029ded35cc2fcc14f3bbc02ad.zip | |
test: port 32 command/repository/downloader tests
Add create_installed_json/create_composer_lock test helpers. Port command (8),
repository path/forgejo/perforce/vcs (11), and fossil/hg/download_manager (13)
tests. Fix production porting bugs: root_package_loader/forgejo_url/version_bumper
regex delimiters, repository_manager create_repository_by_class, array_loader
isset, licenses_command RefCell borrow; implement disk_free_space and
touch2/touch3 via libc.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Diffstat (limited to 'crates/shirabe/tests/downloader/hg_downloader_test.rs')
| -rw-r--r-- | crates/shirabe/tests/downloader/hg_downloader_test.rs | 172 |
1 files changed, 156 insertions, 16 deletions
diff --git a/crates/shirabe/tests/downloader/hg_downloader_test.rs b/crates/shirabe/tests/downloader/hg_downloader_test.rs index 67a13cb..c331533 100644 --- a/crates/shirabe/tests/downloader/hg_downloader_test.rs +++ b/crates/shirabe/tests/downloader/hg_downloader_test.rs @@ -1,8 +1,28 @@ //! ref: composer/tests/Composer/Test/Downloader/HgDownloaderTest.php +use std::cell::RefCell; +use std::rc::Rc; + +use shirabe::config::Config; +use shirabe::downloader::VcsDownloader; +use shirabe::downloader::hg_downloader::HgDownloader; +use shirabe::io::IOInterface; +use shirabe::package::handle::{CompletePackageHandle, PackageInterfaceHandle}; +use shirabe::util::ProcessExecutor; use shirabe::util::filesystem::Filesystem; +use shirabe_semver::VersionParser; use tempfile::TempDir; +use crate::io_stub::IOStub; +use crate::process_executor_mock::{cmd, get_process_executor_mock}; + +fn run<F: std::future::Future>(future: F) -> F::Output { + tokio::runtime::Builder::new_current_thread() + .build() + .unwrap() + .block_on(future) +} + fn set_up() -> TempDir { TempDir::new().unwrap() } @@ -30,48 +50,165 @@ impl Drop for TearDown { } } -// Every case constructs an HgDownloader with a mocked IO/Config and a mocked -// ProcessExecutor to feed hg command output; a real HttpDownloader reaches -// curl_multi_init (todo!()), and ProcessExecutor mocking is not available. +/// ref: TestCase::getMockBuilder('Composer\Package\PackageInterface')->getMock() +/// +/// A real CompletePackage seeded with the stubbed values is a faithful stand-in +/// for a PackageInterface mock as long as `getSourceUrls()` equals +/// `[getSourceUrl()]`, which holds for every non-ignored case here. +fn get_package(source_reference: Option<&str>, source_url: Option<&str>) -> PackageInterfaceHandle { + let norm_version = VersionParser.normalize("1.0.0", None).unwrap(); + let package = + CompletePackageHandle::new("dummy/pkg".to_string(), norm_version, "1.0.0".to_string()); + package.__set_source_type(Some("hg".to_string())); + package.set_source_reference(source_reference.map(|s| s.to_string())); + package.set_source_url(source_url.map(|s| s.to_string())); + package.into() +} + +/// ref: HgDownloaderTest::getDownloaderMock +/// +/// PHP uses a `getMockBuilder('Composer\Config')->getMock()`, whose `get()` +/// returns null for everything; a default real `Config` resolves the only +/// relevant key (`secure-http`) compatibly for the https URLs used here. +fn get_downloader_mock( + io: Option<Rc<RefCell<dyn IOInterface>>>, + config: Option<Config>, + process: Rc<RefCell<ProcessExecutor>>, +) -> HgDownloader { + let io = + io.unwrap_or_else(|| Rc::new(RefCell::new(IOStub::new())) as Rc<RefCell<dyn IOInterface>>); + let config = Rc::new(RefCell::new( + config.unwrap_or_else(|| Config::new(false, None)), + )); + let fs = Rc::new(RefCell::new(Filesystem::new(None))); + HgDownloader::new(io, config, process, fs) +} #[test] -#[ignore = "needs PHPUnit mocks of IOInterface/Config/Filesystem/PackageInterface for getDownloaderMock; not available"] fn test_download_for_package_without_source_reference() { let working_dir = set_up(); let _tear_down = TearDown::new(working_dir.path().to_path_buf()); let _ = &working_dir; - todo!() + + let package = get_package(None, None); + + let (process, _guard) = get_process_executor_mock(vec![], false, Default::default()); + let mut downloader = get_downloader_mock(None, None, process); + + let result = run(downloader.install(package, "/path")); + let e = result.expect_err("missing source reference should throw"); + assert!(e.to_string().contains("missing reference information")); } #[test] -#[ignore = "needs ProcessExecutorMock with expects() command-sequence assertions and PHPUnit PackageInterface mock; not available"] fn test_download() { let working_dir = set_up(); let _tear_down = TearDown::new(working_dir.path().to_path_buf()); - let _ = &working_dir; - todo!() + + let working_dir_str = working_dir.path().to_string_lossy().into_owned(); + let package = get_package(Some("ref"), Some("https://mercurial.dev/l3l0/composer")); + + let (process, _guard) = get_process_executor_mock( + vec![ + cmd(vec![ + "hg", + "clone", + "--", + "https://mercurial.dev/l3l0/composer", + &working_dir_str, + ]), + cmd(vec!["hg", "up", "--", "ref"]), + ], + true, + Default::default(), + ); + + let mut downloader = get_downloader_mock(None, None, process); + run(downloader.install(package, &working_dir_str)).unwrap(); } #[test] -#[ignore = "needs PHPUnit mocks of IOInterface/Config/Filesystem/PackageInterface for getDownloaderMock; not available"] fn test_updatefor_package_without_source_reference() { let working_dir = set_up(); let _tear_down = TearDown::new(working_dir.path().to_path_buf()); let _ = &working_dir; - todo!() + + let initial_package = get_package(Some("ref"), None); + let source_package = get_package(None, None); + + let (process, _guard) = get_process_executor_mock(vec![], false, Default::default()); + let mut downloader = get_downloader_mock(None, None, process); + + let result = run(async { + downloader + .prepare( + "update", + source_package.clone(), + "/path", + Some(initial_package.clone()), + ) + .await?; + downloader + .update(initial_package.clone(), source_package.clone(), "/path") + .await?; + downloader + .cleanup("update", source_package, "/path", Some(initial_package)) + .await + }); + + let e = result.expect_err("missing source reference should throw"); + assert!(e.to_string().contains("missing reference information")); } #[test] -#[ignore = "needs ProcessExecutorMock with expects() command-sequence assertions and PHPUnit PackageInterface mock; not available"] fn test_update() { let working_dir = set_up(); let _tear_down = TearDown::new(working_dir.path().to_path_buf()); - let _ = &working_dir; - todo!() + + let working_dir_str = working_dir.path().to_string_lossy().into_owned(); + + let mut fs = Filesystem::new(None); + fs.ensure_directory_exists(&format!("{}/.hg", working_dir_str)) + .unwrap(); + + let package = get_package(Some("ref"), Some("https://github.com/l3l0/composer")); + + let (process, _guard) = get_process_executor_mock( + vec![ + cmd(vec!["hg", "st"]), + cmd(vec!["hg", "pull", "--", "https://github.com/l3l0/composer"]), + cmd(vec!["hg", "up", "--", "ref"]), + ], + true, + Default::default(), + ); + + let mut downloader = get_downloader_mock(None, None, process); + run(async { + downloader + .prepare( + "update", + package.clone(), + &working_dir_str, + Some(package.clone()), + ) + .await + .unwrap(); + downloader + .update(package.clone(), package.clone(), &working_dir_str) + .await + .unwrap(); + downloader + .cleanup("update", package.clone(), &working_dir_str, Some(package)) + .await + .unwrap(); + }); } +#[ignore = "PHP mocks Filesystem::removeDirectoryAsync; with a real Filesystem the actual \ + removeDirectoryAsync drives its own ProcessExecutor for `rm -rf` through the \ + unported execute_async mock seam"] #[test] -#[ignore = "needs ProcessExecutorMock and PHPUnit Filesystem mock with removeDirectoryAsync expectation; not available"] fn test_remove() { let working_dir = set_up(); let _tear_down = TearDown::new(working_dir.path().to_path_buf()); @@ -80,10 +217,13 @@ fn test_remove() { } #[test] -#[ignore = "needs PHPUnit mocks of IOInterface/Config/Filesystem for getDownloaderMock; not available"] fn test_get_installation_source() { let working_dir = set_up(); let _tear_down = TearDown::new(working_dir.path().to_path_buf()); let _ = &working_dir; - todo!() + + let (process, _guard) = get_process_executor_mock(vec![], false, Default::default()); + let downloader = get_downloader_mock(None, None, process); + + assert_eq!("source", downloader.get_installation_source()); } |
