diff options
| author | nsfisis <nsfisis@gmail.com> | 2026-05-11 02:36:42 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2026-05-11 02:36:42 +0900 |
| commit | 4e99773a3d203e73b8bf6464490d05649a269fa7 (patch) | |
| tree | 7a6f1a7f773a14ea72dc2f9ff4124badd345833d /crates/mozart/src/commands/update.rs | |
| parent | 4df5f8491320e5795718cf0222e80fa27e57c8ad (diff) | |
| download | php-mozart-4e99773a3d203e73b8bf6464490d05649a269fa7.tar.gz php-mozart-4e99773a3d203e73b8bf6464490d05649a269fa7.tar.zst php-mozart-4e99773a3d203e73b8bf6464490d05649a269fa7.zip | |
test(commands): remove per-command tests
Diffstat (limited to 'crates/mozart/src/commands/update.rs')
| -rw-r--r-- | crates/mozart/src/commands/update.rs | 664 |
1 files changed, 0 insertions, 664 deletions
diff --git a/crates/mozart/src/commands/update.rs b/crates/mozart/src/commands/update.rs index 334e221..a893ffd 100644 --- a/crates/mozart/src/commands/update.rs +++ b/crates/mozart/src/commands/update.rs @@ -1799,667 +1799,3 @@ pub async fn run( Ok(()) } - -#[cfg(test)] -mod tests { - use super::*; - - fn make_locked_package(name: &str, version: &str) -> lockfile::LockedPackage { - lockfile::LockedPackage { - name: name.to_string(), - version: version.to_string(), - version_normalized: Some(format!("{}.0", version)), - source: None, - dist: None, - require: indexmap::IndexMap::new(), - require_dev: indexmap::IndexMap::new(), - conflict: indexmap::IndexMap::new(), - provide: indexmap::IndexMap::new(), - replace: indexmap::IndexMap::new(), - suggest: None, - package_type: Some("library".to_string()), - autoload: None, - autoload_dev: None, - license: None, - description: None, - homepage: None, - keywords: None, - authors: None, - support: None, - funding: None, - time: None, - extra_fields: indexmap::IndexMap::new(), - } - } - - fn minimal_lock(packages: Vec<lockfile::LockedPackage>) -> lockfile::LockFile { - lockfile::LockFile { - readme: lockfile::LockFile::default_readme(), - content_hash: "abc123".to_string(), - packages, - packages_dev: Some(vec![]), - aliases: vec![], - minimum_stability: "stable".to_string(), - stability_flags: serde_json::json!({}), - prefer_stable: false, - prefer_lowest: false, - platform: serde_json::json!({}), - platform_dev: serde_json::json!({}), - plugin_api_version: Some("2.6.0".to_string()), - } - } - - fn make_resolved_package(name: &str, version: &str) -> ResolvedPackage { - ResolvedPackage { - name: name.to_string(), - version: version.to_string(), - version_normalized: format!("{}.0", version), - is_dev: false, - alias_of_normalized: None, - } - } - - fn test_console() -> std::sync::Arc<std::sync::Mutex<Box<dyn IoInterface>>> { - std::sync::Arc::new(std::sync::Mutex::new( - Box::new(mozart_core::console::Console::new( - 0, false, false, false, false, - )) as Box<dyn IoInterface>, - )) - } - - #[test] - fn test_parse_minimum_stability_stable() { - assert_eq!( - package::Stability::parse("stable"), - package::Stability::Stable - ); - assert_eq!( - package::Stability::parse("STABLE"), - package::Stability::Stable - ); - assert_eq!( - package::Stability::parse("Stable"), - package::Stability::Stable - ); - } - - #[test] - fn test_parse_minimum_stability_rc() { - assert_eq!(package::Stability::parse("RC"), package::Stability::RC); - assert_eq!(package::Stability::parse("rc"), package::Stability::RC); - } - - #[test] - fn test_parse_minimum_stability_beta() { - assert_eq!(package::Stability::parse("beta"), package::Stability::Beta); - assert_eq!(package::Stability::parse("BETA"), package::Stability::Beta); - } - - #[test] - fn test_parse_minimum_stability_alpha() { - assert_eq!( - package::Stability::parse("alpha"), - package::Stability::Alpha - ); - assert_eq!( - package::Stability::parse("ALPHA"), - package::Stability::Alpha - ); - } - - #[test] - fn test_parse_minimum_stability_dev() { - assert_eq!(package::Stability::parse("dev"), package::Stability::Dev); - assert_eq!(package::Stability::parse("DEV"), package::Stability::Dev); - } - - #[test] - fn test_parse_minimum_stability_unknown_defaults_to_stable() { - assert_eq!( - package::Stability::parse("unknown"), - package::Stability::Stable - ); - assert_eq!(package::Stability::parse(""), package::Stability::Stable); - } - - #[test] - fn test_compute_update_changes_all_new() { - // No old lock: all packages in new lock should be Install - let new_lock = minimal_lock(vec![ - make_locked_package("psr/log", "3.0.0"), - make_locked_package("monolog/monolog", "3.8.0"), - ]); - - let changes = compute_update_changes(None, &new_lock, false); - - assert_eq!(changes.len(), 2); - for change in &changes { - assert!( - matches!(change.kind, ChangeKind::Install { .. }), - "Expected Install, got {:?} for {}", - change.kind, - change.name - ); - } - } - - #[test] - fn test_compute_update_changes_update() { - // Old lock has psr/log at 3.0.0; new lock has it at 3.0.1 -> Update - let old_lock = minimal_lock(vec![make_locked_package("psr/log", "3.0.0")]); - let new_lock = minimal_lock(vec![make_locked_package("psr/log", "3.0.1")]); - - let changes = compute_update_changes(Some(&old_lock), &new_lock, false); - - assert_eq!(changes.len(), 1); - assert_eq!(changes[0].name, "psr/log"); - assert!(matches!( - &changes[0].kind, - ChangeKind::Update { - old_version, - new_version - } if old_version == "3.0.0" && new_version == "3.0.1" - )); - } - - #[test] - fn test_compute_update_changes_remove() { - // Old lock has monolog; new lock doesn't -> Remove - let old_lock = minimal_lock(vec![ - make_locked_package("psr/log", "3.0.0"), - make_locked_package("monolog/monolog", "3.8.0"), - ]); - let new_lock = minimal_lock(vec![make_locked_package("psr/log", "3.0.0")]); - - let changes = compute_update_changes(Some(&old_lock), &new_lock, false); - - assert_eq!(changes.len(), 1); - assert_eq!(changes[0].name, "monolog/monolog"); - assert!(matches!( - &changes[0].kind, - ChangeKind::Uninstall { old_version } if old_version == "3.8.0" - )); - } - - #[test] - fn test_compute_update_changes_unchanged_not_in_result() { - // Same version in both locks -> no changes - let old_lock = minimal_lock(vec![make_locked_package("psr/log", "3.0.0")]); - let new_lock = minimal_lock(vec![make_locked_package("psr/log", "3.0.0")]); - - let changes = compute_update_changes(Some(&old_lock), &new_lock, false); - - assert!( - changes.is_empty(), - "Unchanged packages should not appear in changes list" - ); - } - - #[test] - fn test_compute_update_changes_mixed() { - // Mixed scenario: install, update, remove, unchanged - let old_lock = minimal_lock(vec![ - make_locked_package("psr/log", "3.0.0"), // unchanged - make_locked_package("monolog/monolog", "3.7.0"), // will be updated - make_locked_package("old/package", "1.0.0"), // will be removed - ]); - let new_lock = minimal_lock(vec![ - make_locked_package("psr/log", "3.0.0"), // unchanged - make_locked_package("monolog/monolog", "3.8.0"), // updated - make_locked_package("new/package", "2.0.0"), // installed - ]); - - let changes = compute_update_changes(Some(&old_lock), &new_lock, false); - - // 3 changes: update monolog, remove old/package, install new/package - assert_eq!(changes.len(), 3); - - let monolog = changes - .iter() - .find(|c| c.name == "monolog/monolog") - .unwrap(); - assert!(matches!( - &monolog.kind, - ChangeKind::Update { old_version, new_version } - if old_version == "3.7.0" && new_version == "3.8.0" - )); - - let removed = changes.iter().find(|c| c.name == "old/package").unwrap(); - assert!(matches!(&removed.kind, ChangeKind::Uninstall { .. })); - - let installed = changes.iter().find(|c| c.name == "new/package").unwrap(); - assert!(matches!(&installed.kind, ChangeKind::Install { .. })); - } - - #[test] - fn test_compute_update_changes_dev_packages_included() { - // dev_mode=true: dev packages are also compared - let mut old_lock = minimal_lock(vec![make_locked_package("psr/log", "3.0.0")]); - old_lock.packages_dev = Some(vec![make_locked_package("phpunit/phpunit", "10.0.0")]); - - let mut new_lock = minimal_lock(vec![make_locked_package("psr/log", "3.0.0")]); - new_lock.packages_dev = Some(vec![make_locked_package("phpunit/phpunit", "11.0.0")]); - - let changes = compute_update_changes(Some(&old_lock), &new_lock, true); - - assert_eq!(changes.len(), 1); - assert_eq!(changes[0].name, "phpunit/phpunit"); - assert!(matches!(&changes[0].kind, ChangeKind::Update { .. })); - } - - #[test] - fn test_compute_update_changes_dev_packages_excluded_when_no_dev() { - // dev_mode=false: dev packages are ignored - let mut old_lock = minimal_lock(vec![make_locked_package("psr/log", "3.0.0")]); - old_lock.packages_dev = Some(vec![make_locked_package("phpunit/phpunit", "10.0.0")]); - - let mut new_lock = minimal_lock(vec![make_locked_package("psr/log", "3.0.0")]); - new_lock.packages_dev = Some(vec![make_locked_package("phpunit/phpunit", "11.0.0")]); - - let changes = compute_update_changes(Some(&old_lock), &new_lock, false); - - // No changes because we're not including dev packages - assert!( - changes.is_empty(), - "Dev packages should not appear in changes when dev_mode=false" - ); - } - - #[test] - fn test_apply_partial_update_keeps_non_specified_packages() { - // old lock has psr/log 3.0.0 and monolog 3.7.0 - // resolver found psr/log 3.0.1 and monolog 3.8.0 - // we only want to update monolog - // expected: psr/log stays at 3.0.0, monolog becomes 3.8.0 - - let old_lock = minimal_lock(vec![ - make_locked_package("psr/log", "3.0.0"), - make_locked_package("monolog/monolog", "3.7.0"), - ]); - - let resolved = vec![ - make_resolved_package("psr/log", "3.0.1"), - make_resolved_package("monolog/monolog", "3.8.0"), - ]; - - let update_packages = vec!["monolog/monolog".to_string()]; - let result = apply_partial_update(resolved, &old_lock, &update_packages); - - let psr = result.iter().find(|p| p.name == "psr/log").unwrap(); - assert_eq!( - psr.version, "3.0.0", - "psr/log should be kept at old version" - ); - - let monolog = result.iter().find(|p| p.name == "monolog/monolog").unwrap(); - assert_eq!( - monolog.version, "3.8.0", - "monolog/monolog should use new version" - ); - } - - #[test] - fn test_apply_partial_update_case_insensitive() { - // update_packages uses mixed case, package names may be lowercase - let old_lock = minimal_lock(vec![make_locked_package("psr/log", "3.0.0")]); - let resolved = vec![make_resolved_package("psr/log", "3.0.1")]; - - // Not updating psr/log (not in update list); should revert to 3.0.0 - let update_packages = vec!["MonoLog/Monolog".to_string()]; - let result = apply_partial_update(resolved, &old_lock, &update_packages); - - let psr = result.iter().find(|p| p.name == "psr/log").unwrap(); - assert_eq!(psr.version, "3.0.0"); - } - - #[test] - fn test_apply_partial_update_new_package_in_update_list() { - // A brand new package resolved that is in the update list should use the new version - let old_lock = minimal_lock(vec![make_locked_package("psr/log", "3.0.0")]); - let resolved = vec![ - make_resolved_package("psr/log", "3.0.0"), - make_resolved_package("new/package", "1.0.0"), - ]; - - let update_packages = vec!["new/package".to_string()]; - let result = apply_partial_update(resolved, &old_lock, &update_packages); - - let new_pkg = result.iter().find(|p| p.name == "new/package").unwrap(); - assert_eq!(new_pkg.version, "1.0.0"); - } - - #[test] - fn test_apply_partial_update_full_update_mode() { - // If update_packages is empty, it should behave like full update (no swapping) - let old_lock = minimal_lock(vec![make_locked_package("psr/log", "3.0.0")]); - let resolved = vec![make_resolved_package("psr/log", "3.0.1")]; - - // Empty update list means... everything is not in the update set, - // so old versions are preserved. This is the expected behavior for partial mode - // when packages is empty (which shouldn't happen - full update is separate path). - let update_packages: Vec<String> = vec![]; - let result = apply_partial_update(resolved, &old_lock, &update_packages); - - // When update_packages is empty, nothing is in the update set, so old versions revert - let psr = result.iter().find(|p| p.name == "psr/log").unwrap(); - assert_eq!(psr.version, "3.0.0"); - } - - #[test] - fn test_glob_matches_exact() { - assert!(glob_matches("monolog/monolog", "monolog/monolog")); - assert!(!glob_matches("monolog/monolog", "monolog/logger")); - } - - #[test] - fn test_glob_matches_case_insensitive() { - assert!(glob_matches("Monolog/Monolog", "monolog/monolog")); - assert!(glob_matches("symfony/*", "Symfony/Console")); - } - - #[test] - fn test_glob_matches_vendor_wildcard() { - assert!(glob_matches("symfony/*", "symfony/console")); - assert!(glob_matches("symfony/*", "symfony/http-kernel")); - assert!(!glob_matches("symfony/*", "monolog/monolog")); - } - - #[test] - fn test_glob_matches_wildcard_in_name() { - assert!(glob_matches("monolog/mono*", "monolog/monolog")); - assert!(!glob_matches("monolog/mono*", "monolog/logger")); - } - - #[test] - fn test_glob_matches_wildcard_no_slash() { - // Without a '/' the pattern still works as a full name match - assert!(!glob_matches("symfony/*", "monolog/monolog")); - } - - #[test] - fn test_glob_matches_different_segment_count() { - // "vendor/*" has 2 segments; "monolog" has only 1: no match - assert!(!glob_matches("vendor/*", "monolog")); - // Pattern with 1 segment vs name with 2 segments: no match - assert!(!glob_matches("monolog", "monolog/monolog")); - } - - #[test] - fn test_expand_wildcards_no_wildcard_passthrough() { - let lock = minimal_lock(vec![make_locked_package("psr/log", "3.0.0")]); - let root_requires: IndexSet<String> = ["psr/log", "nonexistent/pkg"] - .into_iter() - .map(String::from) - .collect(); - let specs = vec!["psr/log".to_string(), "nonexistent/pkg".to_string()]; - let result = expand_wildcards(&specs, &lock, &root_requires, test_console()); - assert_eq!(result, vec!["psr/log", "nonexistent/pkg"]); - } - - #[test] - fn test_expand_wildcards_vendor_star() { - let lock = minimal_lock(vec![ - make_locked_package("symfony/console", "7.0.0"), - make_locked_package("symfony/http-kernel", "7.0.0"), - make_locked_package("monolog/monolog", "3.8.0"), - ]); - let specs = vec!["symfony/*".to_string()]; - let root_requires: IndexSet<String> = IndexSet::new(); - let mut result = expand_wildcards(&specs, &lock, &root_requires, test_console()); - result.sort(); - assert_eq!(result, vec!["symfony/console", "symfony/http-kernel"]); - } - - #[test] - fn test_expand_wildcards_no_match_emits_warning() { - let lock = minimal_lock(vec![make_locked_package("psr/log", "3.0.0")]); - let specs = vec!["unknown/*".to_string()]; - let root_requires: IndexSet<String> = IndexSet::new(); - // Should return empty (no match), no panic - let result = expand_wildcards(&specs, &lock, &root_requires, test_console()); - assert!(result.is_empty()); - } - - #[test] - fn test_expand_wildcards_deduplication() { - let lock = minimal_lock(vec![make_locked_package("psr/log", "3.0.0")]); - let specs = vec!["psr/log".to_string(), "psr/log".to_string()]; - let root_requires: IndexSet<String> = IndexSet::new(); - let result = expand_wildcards(&specs, &lock, &root_requires, test_console()); - assert_eq!(result.len(), 1); - assert_eq!(result[0], "psr/log"); - } - - #[test] - fn test_expand_wildcards_also_checks_dev() { - let mut lock = minimal_lock(vec![make_locked_package("psr/log", "3.0.0")]); - lock.packages_dev = Some(vec![make_locked_package("phpunit/phpunit", "11.0.0")]); - let specs = vec!["phpunit/*".to_string()]; - let root_requires: IndexSet<String> = IndexSet::new(); - let result = expand_wildcards(&specs, &lock, &root_requires, test_console()); - assert_eq!(result, vec!["phpunit/phpunit"]); - } - - #[test] - fn test_expand_with_direct_deps_adds_require() { - // monolog/monolog requires psr/log - let mut pkg = make_locked_package("monolog/monolog", "3.8.0"); - pkg.require - .insert("psr/log".to_string(), "^3.0".to_string()); - - let lock = minimal_lock(vec![pkg, make_locked_package("psr/log", "3.0.0")]); - - let result = expand_with_direct_dependencies( - vec!["monolog/monolog".to_string()], - &lock, - &IndexSet::new(), - &IndexMap::new(), - ); - let mut result_sorted = result.clone(); - result_sorted.sort(); - assert!(result_sorted.contains(&"monolog/monolog".to_string())); - assert!(result_sorted.contains(&"psr/log".to_string())); - } - - #[test] - fn test_expand_with_direct_deps_skips_platform() { - let mut pkg = make_locked_package("monolog/monolog", "3.8.0"); - pkg.require.insert("php".to_string(), ">=8.1".to_string()); - pkg.require.insert("ext-json".to_string(), "*".to_string()); - pkg.require - .insert("psr/log".to_string(), "^3.0".to_string()); - - let lock = minimal_lock(vec![pkg, make_locked_package("psr/log", "3.0.0")]); - - let result = expand_with_direct_dependencies( - vec!["monolog/monolog".to_string()], - &lock, - &IndexSet::new(), - &IndexMap::new(), - ); - // Should NOT include php or ext-json - assert!(!result.contains(&"php".to_string())); - assert!(!result.contains(&"ext-json".to_string())); - assert!(result.contains(&"psr/log".to_string())); - } - - #[test] - fn test_expand_with_direct_deps_no_duplicates() { - // Both packages in the list require psr/log - let mut pkg_a = make_locked_package("foo/a", "1.0.0"); - pkg_a - .require - .insert("psr/log".to_string(), "^3.0".to_string()); - let mut pkg_b = make_locked_package("foo/b", "1.0.0"); - pkg_b - .require - .insert("psr/log".to_string(), "^3.0".to_string()); - - let lock = minimal_lock(vec![pkg_a, pkg_b, make_locked_package("psr/log", "3.0.0")]); - - let result = expand_with_direct_dependencies( - vec!["foo/a".to_string(), "foo/b".to_string()], - &lock, - &IndexSet::new(), - &IndexMap::new(), - ); - let psr_count = result.iter().filter(|s| s.as_str() == "psr/log").count(); - assert_eq!(psr_count, 1, "psr/log should appear only once"); - } - - #[test] - fn test_expand_all_deps_transitive() { - // a -> b -> c - let mut pkg_a = make_locked_package("foo/a", "1.0.0"); - pkg_a - .require - .insert("foo/b".to_string(), "^1.0".to_string()); - let mut pkg_b = make_locked_package("foo/b", "1.0.0"); - pkg_b - .require - .insert("foo/c".to_string(), "^1.0".to_string()); - let pkg_c = make_locked_package("foo/c", "1.0.0"); - - let lock = minimal_lock(vec![pkg_a, pkg_b, pkg_c]); - - let result = - expand_with_all_dependencies(vec!["foo/a".to_string()], &lock, &IndexMap::new()); - assert!(result.contains(&"foo/a".to_string())); - assert!(result.contains(&"foo/b".to_string())); - assert!(result.contains(&"foo/c".to_string())); - } - - #[test] - fn test_expand_all_deps_no_infinite_loop() { - // Circular reference: a -> b -> a - let mut pkg_a = make_locked_package("foo/a", "1.0.0"); - pkg_a - .require - .insert("foo/b".to_string(), "^1.0".to_string()); - let mut pkg_b = make_locked_package("foo/b", "1.0.0"); - pkg_b - .require - .insert("foo/a".to_string(), "^1.0".to_string()); - - let lock = minimal_lock(vec![pkg_a, pkg_b]); - - // Must not loop infinitely - let result = - expand_with_all_dependencies(vec!["foo/a".to_string()], &lock, &IndexMap::new()); - assert!(result.contains(&"foo/a".to_string())); - assert!(result.contains(&"foo/b".to_string())); - assert_eq!(result.len(), 2); - } - - #[test] - fn test_expand_packages_wildcard_with_direct_deps() { - // symfony/* expands to symfony/console; symfony/console requires psr/log - let mut console_pkg = make_locked_package("symfony/console", "7.0.0"); - console_pkg - .require - .insert("psr/log".to_string(), "^3.0".to_string()); - - let lock = minimal_lock(vec![console_pkg, make_locked_package("psr/log", "3.0.0")]); - - let result = expand_packages( - &["symfony/*".to_string()], - Some(&lock), - true, // with_dependencies - false, // with_all_dependencies - &IndexSet::new(), - &IndexMap::new(), - test_console(), - ); - - assert!(result.contains(&"symfony/console".to_string())); - assert!(result.contains(&"psr/log".to_string())); - } - - #[test] - fn test_apply_minimal_changes_pins_all() { - // Resolver found psr/log 3.0.1, but old lock has 3.0.0 - // apply_minimal_changes should pin back to 3.0.0 - let old_lock = minimal_lock(vec![make_locked_package("psr/log", "3.0.0")]); - let resolved = vec![make_resolved_package("psr/log", "3.0.1")]; - - let result = apply_minimal_changes(resolved, &old_lock); - let psr = result.iter().find(|p| p.name == "psr/log").unwrap(); - assert_eq!( - psr.version, "3.0.0", - "minimal-changes should pin to locked version" - ); - } - - #[tokio::test] - #[ignore] - async fn test_update_full_e2e() { - use mozart_core::package::RawPackageData; - use mozart_core::repository::lockfile::{LockFileGenerationRequest, generate_lock_file}; - use mozart_core::repository::resolver::{ResolveRequest, resolve}; - - let composer_json_content = - r#"{"name": "test/project", "require": {"monolog/monolog": "^3.0"}}"#; - let composer_json: RawPackageData = serde_json::from_str(composer_json_content).unwrap(); - - let request = ResolveRequest { - root_name: String::new(), - root_version: None, - require: vec![("monolog/monolog".to_string(), "^3.0".to_string())], - require_dev: vec![], - include_dev: false, - minimum_stability: package::Stability::Stable, - stability_flags: IndexMap::new(), - prefer_stable: true, - prefer_lowest: false, - platform: PlatformConfig::new(), - ignore_platform_reqs: false, - ignore_platform_req_list: vec![], - repositories: std::sync::Arc::new( - mozart_core::repository::repository::RepositorySet::with_packagist( - mozart_core::repository::cache::Cache::new( - std::env::temp_dir().join("mozart-test-cache"), - false, - ), - ), - ), - temporary_constraints: IndexMap::new(), - raw_repositories: vec![], - root_provide: IndexMap::new(), - root_replace: IndexMap::new(), - root_conflict: IndexMap::new(), - locked_package_names: IndexSet::new(), - locked_packages: Vec::new(), - block_abandoned: false, - root_branch_alias: None, - preferred_versions: IndexMap::new(), - block_insecure: false, - }; - - let resolved = resolve(&request).await.expect("Resolution should succeed"); - assert!(!resolved.is_empty()); - assert!(resolved.iter().any(|p| p.name == "monolog/monolog")); - - let lock = generate_lock_file(&LockFileGenerationRequest { - resolved_packages: resolved, - composer_json_content: composer_json_content.to_string(), - composer_json, - include_dev: false, - repositories: std::sync::Arc::new( - mozart_core::repository::repository::RepositorySet::with_packagist( - mozart_core::repository::cache::Cache::new( - std::env::temp_dir().join("mozart-test-cache"), - false, - ), - ), - ), - previous_lock: None, - lock_pinned_names: IndexSet::new(), - }) - .await - .expect("Lock file generation should succeed"); - - assert!(!lock.content_hash.is_empty()); - assert!(!lock.packages.is_empty()); - assert!(lock.packages.iter().any(|p| p.name == "monolog/monolog")); - } -} |
