aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe/tests/installer_test.rs
AgeCommit message (Collapse)Author
2026-07-24fix(installer-test): port InstallerTest::setUp's chdir(__DIR__)nsfisis
PHP's InstallerTest::setUp() does chdir(__DIR__) before every test so relative "type": "path" repository URLs in fixtures resolve against composer/tests/Composer/Test; tearDown() restores the previous cwd. This was never ported, only the env-var clears were, so any fixture declaring a relative path repo failed at PathRepository::initialize() with "the `url` supplied for the path (...) repository does not exist" — not a missing PathRepository feature, just an unset cwd. Turned TearDown into a real guard that captures and chdirs on construction and restores on Drop. Since set_current_dir is process-wide state and tests run concurrently by default, added #[serial] to test_installer (the only call site not already inside a #[serial] macro-generated fn) so no two TearDown-holding tests can race on cwd; serial_test's plain #[serial] shares one unnamed lock across the whole binary, so this is sufficient.
2026-07-24fix(pool-builder): use plain getPackages() on locked repositorynsfisis
PoolBuilder::build_pool() and warn_about_non_matching_update_allow_list() called get_canonical_packages() on the locked repository during a partial update, but PHP's PoolBuilder uses the plain getPackages(). get_canonical_packages() unwraps AliasPackage down to its base package, discarding the alias's own version identity. Locker::get_locked_repository() wraps a lock entry with extra.branch-alias in a single CompleteAliasPackage rather than adding a separate base object, so canonicalizing it silently dropped the locked branch-alias version (e.g. 2.2.x-dev), leaving only the raw dev-master version behind. For a package excluded from the partial update's allow-list, that meant its locked branch-alias version could no longer satisfy the root's constraint, producing a spurious solver conflict instead of keeping the package pinned exactly as locked. Fixed the same bug in AuditCommand's --locked package listing, which had the identical get_canonical_packages()/getPackages() mismatch against AuditCommand.php.
2026-07-24fix(dependency-resolver): query real PHP for ext-* version/loaded checksnsfisis
Two shim gaps made the extension-related branches of solver-problem messages wrong: - phpversion($ext) with a non-empty extension can't be known statically (it's shirabe-php-shim's todo!()); Problem::get_missing_package_reason now calls shirabe_php_rpc::phpversion, the same RPC bridge platform::runtime::Runtime::get_extension_version already uses. - extension_loaded's hardcoded allowlist was missing "pcre", a mandatory always-compiled-in PHP extension, so ext-pcre was misreported as "missing from your system" instead of "disabled by your platform config" whenever a platform override disabled it. Also fix XdebugHandler::getAllIniFiles() always returning `[""]` (a php-runtime stub): create_extension_hint()'s early-return guard (`paths[0] empty && len==1`) fired unconditionally, silently dropping the entire "To enable extensions..." hint from every solver-problem message that mentions missing extensions. shirabe-external-packages can't depend on shirabe-php-rpc (shirabe-php-rpc already depends on shirabe-external-packages), so IniHelper::get_all() queries a new get_all_ini_files RPC command directly instead of going through the stub. This exposed that XdebugHandler is never constructed with a name because bin/composer's restart-without-Xdebug bootstrap was never ported to main.rs, making COMPOSER_ORIGINAL_INIS-driven behavior unreachable; documented with a TODO(phase-c) and updated ini_helper_test.rs's ignore reasons (and ignored test_with_no_ini, which only passed before by coincidence with the old stub's constant output) to match.
2026-07-24fix(installer-test): classify EXPECT-LOCK by PHP truthiness, not string matchnsfisis
PHP's readTestFile splits sections with a regex that leaves a section's own trailing newline attached when it is the file's last section (verified against real PHP); for install-without-lock.test and update-without-lock.test, --EXPECT-LOCK-- is that last section, so its raw content is "false\n", not "false". PHP's `$expectLock === 'false'` check therefore also misses, but PHP falls through to JsonFile::parseJson("false\n"), which json_decodes to boolean false anyway, and every downstream check in doTestIntegration branches on PHP truthiness of $expectLock, so the outcome is unaffected either way. The Rust port only mirrored the literal string comparison, so the same "false\n" produced ExpectLock::Json(Value::Bool(false)) instead of ExpectLock::Never, and do_test_integration's Json arm unconditionally read composer.lock, panicking because config.lock=false means no lock file is ever written. Parse EXPECT-LOCK as JSON first and classify by PHP truthiness of the result, matching what doTestIntegration actually checks instead of the raw string.
2026-07-24fix(php-shim): keep literal '>' outside tags in strip_tagsnsfisis
The b'>' match arm in strip_tags's state machine never pushed the character to the output buffer when encountered outside a tag (state 0), unlike every other special-character arm (!, ?, -, and the catch-all) which does push in that state. Every literal '>' not part of an HTML-like tag was silently dropped. This corrupted "=>" into "=" in Composer's operation trace strings (e.g. "Upgrading foo/bar (1.0.0 => 1.1.0)"), which go through strip_tags to remove the <info>/<comment> markup before comparison, un-ignoring 82 integration tests that were asserting on that exact arrow.
2026-07-24fix(locker): return stability-flags as int, not stringnsfisis
Locker::get_stability_flags returned IndexMap<String, String>, converting each value via PhpMixed::as_string(), which only matches the String variant. composer.lock's "stability-flags" values are always JSON integers (BasePackage::STABILITIES), so every flag silently decoded to "" and installer.rs's downstream .parse::<i64>() defaulted it to 0 (stable). This made any locked package pinned via a non-stable stability-flags entry look "unacceptable" during `composer install`, silently dropping it from the solver's pool instead of fixing/requiring it — turning a real dependency conflict into a spurious "lock file needs changes" result. Return i64 directly, matching RootPackageInterface::get_stability_flags and set_lock_data's existing convention for this same PHP array shape.
2026-07-24fix(installer-test): match Locker content-hash encoding to lock hashnsfisis
do_test_integration built the Locker's composer.json content string with serde_json::to_string, which doesn't escape slashes, while the fixture's auto-computed lock "hash" field used JsonFile::encode_with_options with slashes escaped (mirroring PHP's json_encode default). Since virtually every package name contains a "/", this made Locker::isFresh() spuriously report every such lock as stale, unignoring 12 fixtures that depended on the lock being recognized as fresh during `install`.
2026-07-24test(installer): split integration tests into one #[test] per fixturensfisis
Replace the three loop-based test functions (each iterating all fixtures with a shared SKIP_INSTALLER_* skip list) with macro-generated per-fixture test functions, so a single failing or panicking fixture no longer hides the pass/fail status of the rest. Known-failing fixtures keep their TODO(phase-d) reasons via #[ignore] on their own test instead of a shared skip list. All generated tests are #[serial] since they mutate global env vars (COMPOSER_POOL_OPTIMIZER, COMPOSER_FUND) that would otherwise race across parallel test threads. This is an interim structure for triaging the ~131 ignored fixtures one at a time; it should be reverted to a single loop-based test per group (matching Composer's directory-scanned fixtures) once they are resolved.
2026-07-20test(ignore): document root causes for unannotated #[ignore] testsnsfisis
74 tests carried a bare #[ignore] with no explanation. Re-ran each: 25 now pass and had the attribute removed; the remaining 49 got a concise reason (todo!() stubs, regex-crate PCRE gaps, PhpMixed type mismatches, config bool-coercion bugs, missing skipped_load wiring in PoolBuilder, etc.) so future work can find and fix them by grep. No production code or test logic/assertions were changed. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-19fix(root-package-loader): un-ignore 4 tests by fixing stability-flag isset() ↵nsfisis
port extract_stability_flags ported PHP's `isset($stabilityFlags[$name]) && $stabilityFlags[$name] > $stability` as `unwrap_or(i64::MAX) > stability`, so the check always short-circuited to "already more unstable" and no flag (e.g. from an explicit `*@dev` requirement) was ever recorded. Fixed using Option::is_some_and, a direct translation of PHP's isset() && ... check. Also fixes tests/common/test_case.rs's shared installation_manager() helper, which built a real InstallationManager::new instead of the __new_mock constructor (mirroring PHP's FactoryMock::createInstallationManager()), so it always had zero installers registered and wrote install-path: null into fixture installed.json files. Un-ignores test_reinstall_command, test_locally_modified_packages_from_source/ _from_dist, and test_package_still_present_error_when_no_install_flag_used — the first three were already passing (their #[ignore] reasons were stale), the last is fixed by the test_case.rs change above. Updates the #[ignore] reasons on installer_test.rs's three fixture-driven integration tests to reflect their current state: the install pipeline now runs end-to-end, but the ~189-fixture installer/ set still hits several independent, unrelated bugs/gaps that need case-by-case triage rather than a single fix. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-19fix(test-harness): set COMPOSER_TESTS_ARE_RUNNING so interactive tests ↵nsfisis
actually run Without this, Application::do_run force-disabled interactivity whenever stdin wasn't a tty (as under cargo test), so ApplicationTester runs with set_inputs silently produced non-interactive default output instead of consuming the answers, masking real behavior as several stale #[ignore]s blaming already-implemented ProcessExecutor/Process todo!()s. Port composer/tests/bootstrap.php's env setup into a bootstrap() helper called from get_application_tester(), un-ignore the now-passing init/update command tests, and update init_command_test's expected schema-validation wording to match the jsonschema crate (already the accepted wording per 541a8b4f, not an unported gap).
2026-07-18perf(regex): eliminate per-call clone overhead in preg_* dispatchnsfisis
regex::Regex::clone() does not share the underlying meta engine's search-cache pool, so every fresh clone pays a ~10us warmup cost on its first use. Two changes together eliminate this across nearly all preg_* call sites: - A php_regex! macro resolves PHP-style patterns to a per-call-site &'static regex::Regex (via regex-macro's LazyLock), applied at the majority of call sites throughout the codebase. - Call sites still passing dynamic pattern strings go through PATTERN_CACHE, which now stores Arc<(Regex, bool)> and hands out Arc::clone()s instead of cloning the Regex itself. PregPattern::resolve() returns a ResolvedPattern enum (Arc or 'static reference) rather than an owned Regex, so neither path ever clones the Regex proper. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-11chore: use fully-qualified name for Rc/RefCellnsfisis
2026-07-04test: ignore broken testsnsfisis
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-22test: port more test casesnsfisis
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21test(tests): expand stub macros into plain test functionsnsfisis
The per-file stub!/encode_stub!/etc. macros generated #[ignore]d test functions but obscured the individual test bodies. Expanding them inline removes the macro indirection so future ports can fill in each function directly. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21test(tests): port setUp/tearDown as set_up/tear_down with TearDownnsfisis
Port PHP setUp/tearDown across the ported integration tests using same-named set_up()/tear_down() functions and a TearDown struct whose Drop runs tear_down(). Fixture-init setUp returns its fixtures; tmpdir-style setUp/tearDown carry state in TearDown fields. Parts that depend on unported infrastructure (PHPUnit mocks, Config::merge, the PHP error handler) stay todo!() and are only wired into ignored stubs to avoid breaking live tests. Also fix shirabe-php-shim putenv to handle the no-'=' form (PHP unsets the variable), which Platform::clear_env relies on for the env-clearing tearDowns. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21test: port downloader/installer/io/json/event-dispatcher/functional stubsnsfisis
All ignored: these mock IO/HttpDownloader (curl)/ProcessExecutor/installers, use ZipArchive/JsonManipulator todo!()s, need Symfony console or schema validation, reflect into ClassLoader, or run end-to-end install/functional fixtures. Wires up the event_dispatcher test target. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21test: add empty test filesnsfisis