aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe/tests
AgeCommit message (Collapse)Author
2026-07-17refactor(tests-async): unify duplicated tokio runtime bridgesnsfisis
11 downloader/installer integration-test files each redefined an identical current_thread `run()` helper to block on async code. Extract one shared multi_thread Runtime into tests/common/async_runtime.rs so concurrent #[test] threads can all block_on it, matching the direction item 7 (top-level Runtime) will take in production code.
2026-07-17refactor(http-downloader): drop the job table for a &self Semaphore corensfisis
Replaces Job/Request/JobHandle/id_gen/running_jobs/max_jobs with a tokio::sync::Semaphore permit held for the duration of each request. get/add/copy/add_copy are now &self (add/add_copy are also genuinely async); a shared execute()/dispatch() core replaces add_job/run_rfs_job/start_job/settle_job, returning the Response directly instead of deferring to wait()/count_active_jobs()/ get_response() (all removed — confirmed zero callers, same for the now-unused STATUS_* constants). get()/copy() stay synchronous rather than becoming async wrappers around add()/add_copy(), bridging via the existing sync_executor instead of the curl_runtime() introduced for CurlDownloader: their callers (~35 files reaching HttpDownloader) are mostly plain sync fns with no async boundary anywhere in the call chain, and forcing that propagation now would pull forward the dedicated async-propagation task. curl-eligible requests still route through curl_runtime() inside dispatch(), same as before — nesting sync_executor::block_on (no real reactor) around curl_runtime().block_on() (a real, separate Runtime) is safe; it's only nesting curl_runtime() inside itself that would panic. CurlDownloader no longer needs Rc<RefCell<>> wrapping despite the original design sketch: since item 2 made all of its methods &self, a plain Option<CurlDownloader> field works fine under HttpDownloader's own &self methods. get/add/copy/add_copy becoming &self (rather than &mut self) requires no changes at any of their ~35 calling files: RefMut/Ref both deref to a type that can call &self methods just fine. Verified manually against real network I/O (sandbox disabled): `shirabe show -a` (get()'s sync_executor-bridged path) and `shirabe create-project` (add_copy()'s genuinely async path via file_downloader.rs) both complete correctly with no hang.
2026-07-16refactor(remote-filesystem): return headers from copy/get_contentsnsfisis
Wrap RemoteFilesystem in Rc<RefCell<>> inside HttpDownloader, in prep for the upcoming &self conversion of add()/get(). copy()/get_contents() now bundle the response headers into their return value instead of requiring a follow-up get_last_headers() call, since two separate calls through a shared RefCell could otherwise race: nothing would guarantee the reader observes the headers from its own request rather than one clobbered by a concurrently borrowed call. get_last_headers() itself is left in place, mirroring RemoteFilesystem::getLastHeaders() in PHP.
2026-07-16fix(proxy-manager): correct singleton lifecycle and simplify to a plain Mutexnsfisis
reset() eagerly rebuilt the ProxyManager singleton immediately, capturing env vars before a caller could set them for the next request. PHP's reset() just nulls the static instance; getInstance() lazily constructs on next use. Match that so proxy env vars set after reset() are observed. get_instance() also ensured the singleton was constructed under its own lock, dropped that lock, and returned the bare Mutex; every caller then took a second, independent lock. A reset() landing in that gap would leave the caller observing None and panicking on .as_ref().unwrap(), a state the old eager-reconstructing reset() could not produce. Return the already-locked MutexGuard from get_instance() instead, so construction and use happen under one lock, and update all call sites accordingly. Holding that guard across a loop body then deadlocked in diagnose_command, since check_http_proxy transitively re-enters get_instance() via HttpDownloader -> CurlDownloader, and std::sync::Mutex is not reentrant. Re-acquire the lock fresh each iteration with a short-lived guard instead. Finally, Mutex::new is a const fn, so the OnceLock wrapper around it was unnecessary indirection; a bare static Mutex<Option<ProxyManager>> initializes to the same state without the get_or_init/get dance. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-16refactor(locker-test): reuse test_case's installation_manager helpernsfisis
locker_test.rs defined its own installation_manager, identical to test_case.rs's (both build a bare InstallationManager over a mock HttpDownloader). Expose the shared one via pub(crate) and drop the duplicate. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-16test(plugin): port capability-query tests, record remaining TODO(phase-d) ↵nsfisis
reasons Implement test_incapable_plugin_is_correctly_detected and test_querying_non_provided_capability_returns_null_safely against a real PluginManager, using hand-written PluginInterface/Capable stubs in place of PHPUnit's ad-hoc mocks. Wire the shared config_stub test helper into the plugin test binary, and derive Debug on the SetUp struct per this project's convention. The remaining plugin_installer_test.rs cases stay #[ignore]d: install/update/uninstall wiring in PluginInstaller and class instantiation in PluginManager::register_package are still TODO(plugin) stubs, so no plugin ever actually gets registered. Each now records its blocking TODO(plugin) site via // TODO(phase-d). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-16test: update TODO reason for unported test casesnsfisis
No test logic changes.
2026-07-16test(downloader): record TODO(phase-d) reasons and port two git-downloader testsnsfisis
zip/git/file downloader tests that were already #[ignore]d for a documented reason lacked the required in-body // TODO(phase-d) comment; record it for each. Two git_downloader_test.rs cases, test_download_uses_various_protocols_and_sets_push_url_for_github and test_update_doesnt_throws_runtime_exception_if_git_command_fails_at_first_but_is_able_to_recover, had been left as todo!() with a TODO(phase-d) claiming ComposerMirror::process_git_url's github regex lacks PCRE delimiters and panics. That regex already has delimiters and does not panic (verified directly), and other tests in this same file already use Package::set_source_mirrors to give a real package a mirror-prefixed getSourceUrls() list, so the stated blocker no longer applies. Port both tests using that existing technique instead of recording a TODO(phase-d) for them. No other test logic changes. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-16test(util): port remaining todo!() tests in util test suitensfisis
Implement previously-todo!() tests in auth_helper_test.rs, process_executor_test.rs, remote_filesystem_test.rs, and stream_context_factory_test.rs by porting the corresponding PHPUnit test methods. Extend IOStub with writeRaw/setAuthentication call tracking and askAndValidate/getAuthentication overrides to model the PHPUnit mocks these tests rely on, deduping the resulting call-recording fields into a small generic CallRecorder<T> helper instead of repeating the same RefCell<Vec<T>> push/borrow().clone() boilerplate five times. testStoreAuthWithPromptInvalidAnswer and testPromptAuthIfNeededMultipleBitbucketDownloads had initially lost the ported PHPUnit mock's argument/call-count assertions (askAndValidate's exact prompt string, and hasAuthentication/getAuthentication's exactly(2) call counts), silently narrowing what the tests verify; IOStub now records these calls and the tests assert on them, matching upstream. Tests left unportable (PHP set_error_handler machinery, closures in data providers, network/subclass-mock dependencies, etc.) keep #[ignore] with a single // TODO(phase-d) reason recorded in the function body. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-11chore: use fully-qualified name for Rc/RefCellnsfisis
2026-07-05feat(global-command): wire resetComposer and Application::run proxyingnsfisis
Application::find/reset_composer and the shared ApplicationHandle are now available, so GlobalCommand can reset the composer instance before building the sub-command input and proxy execution through the full Application::run dispatch, matching PHP's behavior. Un-ignores the tests that only depended on this wiring, and re-points the remaining ignores at their real (unrelated) blockers.
2026-07-05feat(validating-array-loader): implement LoaderInterfacensfisis
Convert errors/warnings/config to RefCell so load() can satisfy the trait's &self signature, matching upstream's `instanceof ValidatingArrayLoader` check in VcsRepository. This makes the InvalidPackageException downcast path in VcsRepository reachable for the first time instead of being permanently dead code.
2026-07-05feat(remote-filesystem): support file:// URLs in get_remote_contentsnsfisis
get_remote_contents was a full stub always returning None, so any file:// download raised a TransportException. Read local files directly for the file scheme, mirroring PHP's file_get_contents transparently handling the file:// stream wrapper. Also fixes file_get_contents5 to strip the file:// prefix like the 0-arg variant already did.
2026-07-04fix(event-dispatcher): avoid reentrant RefCell panicsnsfisis
Two related "already borrowed" panics reachable from AutoloadGenerator::dump() (which holds the local-repository, installation-manager, and config RefCells for the duration of its own statement, per the temporary-lifetime-extension pattern fixed separately in create_project_command.rs): - ensure_bin_dir_is_in_path called config.borrow_mut() to read "bin-dir", but Config::get only needs &self; use borrow() so it can coexist with an outer borrow instead of conflicting with it. - make_autoloader's real body needed composer_handle.borrow_mut() plus the same local-repository/installation-manager RefCells the caller already holds mutably, which cannot be made reentrant-safe without a larger restructuring. Since all 3 call sites already discard its return value, and its only effect (registering a Composer-generated ClassLoader for autoloading during event-listener PHP execution) is unobservable in this port — there's no embedded PHP interpreter to register it into, and class_exists for user-defined classes is a hardcoded-false shim so the caller's very next check always treats the class as unavailable regardless — make it a genuine no-op. This unblocks the post-autoload-dump event for any script listener naming a PHP class (e.g. Illuminate\Foundation\ComposerScripts), which every create-project/install run reaches once real packages get installed. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-04fix(pcre): restore missing regex delimiters in ported patternsnsfisis
Several Preg::*() call sites lost their PHP delimiter (and in one case the `i` modifier) during porting, since preg_*() expects the delimiter to be preserved in the caller's pattern literal and stripped internally. This made compile_php_pattern panic or silently misparse the pattern. Un-ignore the Version tests that were blocked by this bug.
2026-07-04test: ignore broken testsnsfisis
2026-07-02chore(lint): ban std::io::Read/Write, Any, Command use importsnsfisis
Extends no_banned_use to cover std::any::Any, std::io::Read/Write, and std::process::Command, and teaches the linter to allow `as _` imports so trait methods can still be brought into scope without binding the banned name. Fully qualifies all existing usages across the codebase.
2026-07-01test(repository-manager): port testFilterRepoWrappingnsfisis
PathRepository already implements RepositoryInterface and create_repository already handles the "path" class, so the prior ignore reason no longer applies; verify the FilterRepository/PathRepository wrapping via RepositoryInterfaceHandle::is/downcast_rc.
2026-07-01test(application): port two doRun script-command testsnsfisis
Port testNoPluginsDisablesPluginsWhenScriptCommandsExist and testScriptCommandTakesPriorityOverAbbreviatedBuiltinCommand. Both stay #[ignore]d because do_run panics at the script-registration todo!() (application.rs:2461) when composer.json has scripts. Add a test-only ApplicationHandle::__get_composer accessor so the first test's getPluginManager assertions can be expressed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01test(archive-manager): port testArchiveTar and testArchiveCustomFileNamensfisis
Wire a git downloader into the test's DownloadManager (mirroring Factory::createDownloadManager) so the archive path clones the package source as PHP does. Both remain #[ignore]'d on PharData tar archiving (new_with_format/build_from_iterator are todo!() in the php-shim). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01test(downloader): port ZipDownloader testErrorMessagesnsfisis
The faithful port drives a real HttpDownloader + Loop over a file:// dist URL, but RemoteFilesystem::get_remote_contents is a phase-c stub returning None, so the download fails with a "could not be downloaded" TransportException before reaching the ZipArchive "is not a zip archive" path. Kept #[ignore] with the corrected reason (the previous curl_multi_init note was wrong, file:// never uses curl). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01test(remote-filesystem): port get_contents, copy, bitbucket downloadnsfisis
These three tests exercise getContents/copy against a file:// URL (and a real network download for BitBucket). They remain #[ignore] because get_remote_contents has no stream/file layer yet (TODO(phase-c)) and returns None, so the calls raise a TransportException. The ignore reasons are updated to reflect the actual failure point. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01test(autoload): port 5 AutoloadGenerator testsnsfisis
Port testVendorDirExcludedFromWorkingDir, testUpLevelRelativePaths, testGeneratesPlatformCheck (all 12 data-provider rows), and both testAbsoluteSymlinkWith* tests from the Composer suite. testVendorDirExcludedFromWorkingDir passes. The other four expose behavioral gaps in shirabe (exclude-from-classmap with up-level/symlink paths, psr-4 symlink warnings, get_platform_check provider matching), so they keep their fully-ported bodies but are marked #[ignore] with the specific incompatibility rather than weakening expectations. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30refactor(git): replace is_callable with RunCommandOutput traitnsfisis
Model Git::runCommand's mixed $commandOutput parameter with the RunCommandOutput trait (one impl per PHP mode: discard, by-ref capture, callable handler), mirroring ProcessExecutor's IntoExecOutput. This moves the is_callable($commandOutput) value-inspection into the type system and drops the dependency on the shim's incomplete is_callable. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29feat(audit): implement get_packages non-locked branchnsfisis
Port AuditCommand::getPackages's non-locked path: build an InstalledRepository from the local repository and return its packages, filtered by RootPackage requires when --no-dev is set. The prior TODO(phase-c) assumption (InstalledRepository::new vs get_local_repository type mismatch) no longer holds since both sides use RepositoryInterfaceHandle. Enables the two previously ignored audit command tests. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29feat(package): implement RootAliasPackage root getters via owned returnsnsfisis
It is faithful to PHP's by-value array/string semantics. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29fix(advisory): pass IO as shared handle to Auditor::auditnsfisis
Auditor::audit took io as &mut dyn IOInterface, forcing the audit and installer post-audit call sites to hold a borrow_mut() on the shared IO RefCell for the whole call. During advisory fetching the repositories write to their own clones of the same handle, so the borrow_mut() collided with their borrow() and panicked with 'RefCell already mutably borrowed' on 'audit --locked'. Take the Rc<RefCell<dyn IOInterface>> handle instead so writes borrow briefly and never overlap. Un-ignore the locked-audit regression test that this unblocks. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29refactor(json): replace seld/jsonlint with serde_jsonnsfisis
Validate JSON syntax with serde_json's parse errors in JsonFile, and detect duplicate keys in ConfigValidator with a hand-written serde visitor, dropping the now-unused JsonParser/Lexer/DuplicateKeyException ports. ParsingException is kept as the thrown error type and downcast signal. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28test(show): clarify ignore reason for empty platform sectionnsfisis
The platform: section is empty because PlatformRepository::get_packages routes to ArrayRepository::initialize instead of its own initialize, which needs the still-todo!() runtime::constant() shim. Record the real blocker. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28fix(repository): flatten InstalledRepository and unwrap filter repos in shownsfisis
flattenRepositories must recurse into InstalledRepository (which extends CompositeRepository in PHP) and ShowCommand must unwrap FilterRepository when categorizing repos. Without this, installed/locked/platform packages all fell through to the "available" bucket, dropping the version column and per-section grouping. Un-ignores 10 show_command tests. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28fix(installer): execute install/update/uninstall ops in execute_batchnsfisis
execute_batch only awaited prepare(), leaving the install/update/ uninstall + cleanup + repo.write promise chain as a todo!() stub, so packages were downloaded to cache but never installed into the target directory. Wire the operation step (mirroring PHP's promise chain), propagate errors from the install/update/uninstall wrappers instead of swallowing them with .ok()?, and write the repo after each op. Un-ignore the create-project functional tests and the install/remove command tests this unblocks. The remaining --no-install case still fails on a separate install-path bug; its ignore reason is updated to match.
2026-06-28test(installer): port InstallerTest unit and integration harnessnsfisis
Port composer/tests/Composer/Test/InstallerTest.php. testInstaller (the provideInstaller cases) is fully ported and passes; the three integration tests port doTestIntegration in full (the .test fixture loader, FactoryMock, the in-process console Application with install/update commands, and the PHPUnit assertStringMatchesFormat matcher) and remain #[ignore]'d since the install pipeline is not yet executable end-to-end. Add test-only `__`-seams to the concrete types the test depends on, since their consumers (e.g. Locker takes the concrete InstallationManager) and the subclass-style mocks have no trait to mock: InstallationManager (recording mock + as_any), Factory (__create_mock), VersionGuesser, and InstalledFilesystemRepository. The production path (mock: false) is unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28test(functional): port AllFunctionalTest integration harnessnsfisis
Implements the todo!() stubs in all_functional_test.rs by faithfully porting parseTestFile, cleanOutput and the inline %regex% EXPECT matcher, plus a subprocess runner that drives CARGO_BIN_EXE_shirabe (in place of PHP's composer.phar) over the reused Fixtures/functional .test files. The five fixtures are wired as individual #[serial] #[ignore] tests with per-fixture reasons: the two create-project cases need network + a real git clone, and the three update cases need the not-yet-implemented Plugin API. test_build_phar stays an ignored stub since Rust has no phar build. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28refactor: add linternsfisis
2026-06-28test(json): drop JsonFormatterTest stubnsfisis
JsonFormatter is intentionally unported in crates/shirabe/src/json, so the ignored todo!() stub test serves no purpose. Remove the file and its module declaration. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28test(downloader): cfg-gate XzDownloaderTest skip on Windows/32bitnsfisis
Replace the todo!() markTestSkipped placeholders in set_up with a compile-time cfg gate on the test function, mirroring PHP's setUp skips on Windows and 32bit. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28test(command): port HomeCommandTest useCaseProvider casesnsfisis
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28test(command): port DiagnoseCommandTest casesnsfisis
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28test(tests): use mockall for hand-written interface mocksnsfisis
Replace hand-written mock/stub structs that re-implemented PHPUnit mock-builder behavior (record-and-verify, manual call counters, unreachable!() guards) with mockall::mock! locals across: - package/loader: MockLoader, VersionGuesserMock - command: ArchiveManager/RepositoryManager/EventDispatcher mocks - util: ConfigSource/AuthJson mocks (auth_helper, bitbucket, github, forgejo, gitlab) - repository/vcs: github_driver NullConfigSource - installer: CountingInstaller, RecordingBinaryInstaller, and the DownloadManager mock (formerly common/downloader_stub.rs, now deleted) - downloader: download_manager create_downloader_mock Verification (counts/args) now lives in mockall expectations checked on drop. installation_manager BinaryInstaller is left hand-written because its as_binary_presence_interface seam returns Some(&mut self), which mockall cannot express; io_stub and io_mock are left as-is. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28test(util/git): port interactive Bitbucket OAuth runCommand testnsfisis
Implement the four privateBitbucketWithOauthProvider cases that were stubbed as an ignored todo!(). Extend IOStub with per-question askAndHideAnswer responses and auth pre-seeding so the stateful OAuth flow can be driven without willReturnCallback, and inject a mock HttpDownloader plus no-op config sources to mirror PHPUnit's Config mock. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28test(repository): port testRepositoryWritesInstalledPhpnsfisis
Implement the previously-ignored test, which dumps installed.php via FilesystemRepository::write and byte-matches the Composer fixture. The package link setters needed by configureLinks are now reachable through the __set_provides/__set_replaces test hatches, so the PHP getPackage + configureLinks shape can be reproduced faithfully. Also switch both InstallationManager stubs in this file to a single mockall mock, replacing the hand-rolled impls and call counter. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28test(console): correct inaccurate test skip reasonsnsfisis
setCatchErrors is an old-Symfony compatibility shim that exists in neither Composer's PHP class nor Shirabe, and setAutoExit(false) is the default in Shirabe, so neither is a reason a test is unportable. Drop those mentions and point the application_test ignores at the real blocker: do_run's script-command registration is still a todo!(). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28test(console): port DocumentationTest::testCommandnsfisis
Add __base_application accessor on ApplicationHandle so the test can build an ApplicationDescription the way console commands do. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28test(package/archiver): port testGitExcludesnsfisis
Process::fromShellCommandline and ZipArchive are now ported, so the git pipeline + zip reading have faithful equivalents. Kept #[ignore]d: the finder applies .gitattributes rules through BaseExcludeFilter::generate_pattern, whose (?=$|/) look-ahead regexes the regex crate cannot compile (same blocker as test_manual_excludes); also needs a git executable. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28test(package/version): port testFindRecommendedRequireVersionnsfisis
Ported faithfully via PackageHandle::new + __set_extra (now available on PackageHandle). Kept #[ignore]d: date-based cases expose a shirabe_semver normalize divergence (v20121020 -> 20121020.0.0.0), not a test-port issue. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28test(downloader): port Fossil/Hg testRemovensfisis
The FilesystemMock seam (already used by FileDownloaderTest) intercepts removeDirectoryAsync before any rm -rf, so the prior execute_async blocker no longer applies. getDownloaderMock gains the optional filesystem param. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28test(factory): port testDefaultValuesAreAsExpectednsfisis
The IOMock and ConfigStubBuilder helpers now cover the writeError verification and the get('disable-tls')=>true stub the PHP test needs. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28test(config): port testProhibitedUrlsWarningVerifyPeernsfisis
The IOMock helper is now available, so the verify_peer/verify_peer_name SSL warning case can be exercised instead of left as todo!(). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28test(command/status): port testLocallyModifiedPackagesnsfisis
Replace the todo!() stub with a faithful port of StatusCommandTest's data-provided locally-modified-packages cases (source/dist), kept #[ignore]d since install does not yet populate vendor/ offline. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28test(util): port MetadataMinifier expand testnsfisis
minify is intentionally unported, so only the expand half of testMinifyExpand() is exercised. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>