diff --git a/crates/uv/tests/lock_scenarios.rs b/crates/uv/tests/lock_scenarios.rs index d4c673975..0c487434f 100644 --- a/crates/uv/tests/lock_scenarios.rs +++ b/crates/uv/tests/lock_scenarios.rs @@ -7,6 +7,7 @@ #![allow(clippy::needless_raw_string_hashes)] use anyhow::Result; +use assert_cmd::assert::OutputAssertExt; use assert_fs::prelude::*; use insta::assert_snapshot; @@ -108,6 +109,17 @@ fn fork_allows_non_conflicting_non_overlapping_dependencies() -> Result<()> { ); }); + // Assert the idempotence of `uv lock` + context + .lock() + .env_remove("UV_EXCLUDE_NEWER") + .arg("--index-url") + .arg("https://astral-sh.github.io/packse/0.3.31/simple-html/") + .assert() + .success(); + let lock2 = fs_err::read_to_string(context.temp_dir.join("uv.lock"))?; + assert_eq!(lock2, lock); + Ok(()) } @@ -203,6 +215,17 @@ fn fork_allows_non_conflicting_repeated_dependencies() -> Result<()> { ); }); + // Assert the idempotence of `uv lock` + context + .lock() + .env_remove("UV_EXCLUDE_NEWER") + .arg("--index-url") + .arg("https://astral-sh.github.io/packse/0.3.31/simple-html/") + .assert() + .success(); + let lock2 = fs_err::read_to_string(context.temp_dir.join("uv.lock"))?; + assert_eq!(lock2, lock); + Ok(()) } @@ -308,6 +331,17 @@ fn fork_basic() -> Result<()> { ); }); + // Assert the idempotence of `uv lock` + context + .lock() + .env_remove("UV_EXCLUDE_NEWER") + .arg("--index-url") + .arg("https://astral-sh.github.io/packse/0.3.31/simple-html/") + .assert() + .success(); + let lock2 = fs_err::read_to_string(context.temp_dir.join("uv.lock"))?; + assert_eq!(lock2, lock); + Ok(()) } @@ -627,6 +661,17 @@ fn fork_filter_sibling_dependencies() -> Result<()> { ); }); + // Assert the idempotence of `uv lock` + context + .lock() + .env_remove("UV_EXCLUDE_NEWER") + .arg("--index-url") + .arg("https://astral-sh.github.io/packse/0.3.31/simple-html/") + .assert() + .success(); + let lock2 = fs_err::read_to_string(context.temp_dir.join("uv.lock"))?; + assert_eq!(lock2, lock); + Ok(()) } @@ -766,6 +811,17 @@ fn fork_incomplete_markers() -> Result<()> { ); }); + // Assert the idempotence of `uv lock` + context + .lock() + .env_remove("UV_EXCLUDE_NEWER") + .arg("--index-url") + .arg("https://astral-sh.github.io/packse/0.3.31/simple-html/") + .assert() + .success(); + let lock2 = fs_err::read_to_string(context.temp_dir.join("uv.lock"))?; + assert_eq!(lock2, lock); + Ok(()) } @@ -885,6 +941,17 @@ fn fork_marker_accrue() -> Result<()> { ); }); + // Assert the idempotence of `uv lock` + context + .lock() + .env_remove("UV_EXCLUDE_NEWER") + .arg("--index-url") + .arg("https://astral-sh.github.io/packse/0.3.31/simple-html/") + .assert() + .success(); + let lock2 = fs_err::read_to_string(context.temp_dir.join("uv.lock"))?; + assert_eq!(lock2, lock); + Ok(()) } @@ -1112,6 +1179,17 @@ fn fork_marker_inherit_combined_allowed() -> Result<()> { ); }); + // Assert the idempotence of `uv lock` + context + .lock() + .env_remove("UV_EXCLUDE_NEWER") + .arg("--index-url") + .arg("https://astral-sh.github.io/packse/0.3.31/simple-html/") + .assert() + .success(); + let lock2 = fs_err::read_to_string(context.temp_dir.join("uv.lock"))?; + assert_eq!(lock2, lock); + Ok(()) } @@ -1264,6 +1342,17 @@ fn fork_marker_inherit_combined_disallowed() -> Result<()> { ); }); + // Assert the idempotence of `uv lock` + context + .lock() + .env_remove("UV_EXCLUDE_NEWER") + .arg("--index-url") + .arg("https://astral-sh.github.io/packse/0.3.31/simple-html/") + .assert() + .success(); + let lock2 = fs_err::read_to_string(context.temp_dir.join("uv.lock"))?; + assert_eq!(lock2, lock); + Ok(()) } @@ -1417,6 +1506,17 @@ fn fork_marker_inherit_combined() -> Result<()> { ); }); + // Assert the idempotence of `uv lock` + context + .lock() + .env_remove("UV_EXCLUDE_NEWER") + .arg("--index-url") + .arg("https://astral-sh.github.io/packse/0.3.31/simple-html/") + .assert() + .success(); + let lock2 = fs_err::read_to_string(context.temp_dir.join("uv.lock"))?; + assert_eq!(lock2, lock); + Ok(()) } @@ -1544,6 +1644,17 @@ fn fork_marker_inherit_isolated() -> Result<()> { ); }); + // Assert the idempotence of `uv lock` + context + .lock() + .env_remove("UV_EXCLUDE_NEWER") + .arg("--index-url") + .arg("https://astral-sh.github.io/packse/0.3.31/simple-html/") + .assert() + .success(); + let lock2 = fs_err::read_to_string(context.temp_dir.join("uv.lock"))?; + assert_eq!(lock2, lock); + Ok(()) } @@ -1688,6 +1799,17 @@ fn fork_marker_inherit_transitive() -> Result<()> { ); }); + // Assert the idempotence of `uv lock` + context + .lock() + .env_remove("UV_EXCLUDE_NEWER") + .arg("--index-url") + .arg("https://astral-sh.github.io/packse/0.3.31/simple-html/") + .assert() + .success(); + let lock2 = fs_err::read_to_string(context.temp_dir.join("uv.lock"))?; + assert_eq!(lock2, lock); + Ok(()) } @@ -1803,6 +1925,17 @@ fn fork_marker_inherit() -> Result<()> { ); }); + // Assert the idempotence of `uv lock` + context + .lock() + .env_remove("UV_EXCLUDE_NEWER") + .arg("--index-url") + .arg("https://astral-sh.github.io/packse/0.3.31/simple-html/") + .assert() + .success(); + let lock2 = fs_err::read_to_string(context.temp_dir.join("uv.lock"))?; + assert_eq!(lock2, lock); + Ok(()) } @@ -1945,6 +2078,17 @@ fn fork_marker_limited_inherit() -> Result<()> { ); }); + // Assert the idempotence of `uv lock` + context + .lock() + .env_remove("UV_EXCLUDE_NEWER") + .arg("--index-url") + .arg("https://astral-sh.github.io/packse/0.3.31/simple-html/") + .assert() + .success(); + let lock2 = fs_err::read_to_string(context.temp_dir.join("uv.lock"))?; + assert_eq!(lock2, lock); + Ok(()) } @@ -2072,6 +2216,17 @@ fn fork_marker_selection() -> Result<()> { ); }); + // Assert the idempotence of `uv lock` + context + .lock() + .env_remove("UV_EXCLUDE_NEWER") + .arg("--index-url") + .arg("https://astral-sh.github.io/packse/0.3.31/simple-html/") + .assert() + .success(); + let lock2 = fs_err::read_to_string(context.temp_dir.join("uv.lock"))?; + assert_eq!(lock2, lock); + Ok(()) } @@ -2222,6 +2377,17 @@ fn fork_marker_track() -> Result<()> { ); }); + // Assert the idempotence of `uv lock` + context + .lock() + .env_remove("UV_EXCLUDE_NEWER") + .arg("--index-url") + .arg("https://astral-sh.github.io/packse/0.3.31/simple-html/") + .assert() + .success(); + let lock2 = fs_err::read_to_string(context.temp_dir.join("uv.lock"))?; + assert_eq!(lock2, lock); + Ok(()) } @@ -2340,6 +2506,17 @@ fn fork_non_fork_marker_transitive() -> Result<()> { ); }); + // Assert the idempotence of `uv lock` + context + .lock() + .env_remove("UV_EXCLUDE_NEWER") + .arg("--index-url") + .arg("https://astral-sh.github.io/packse/0.3.31/simple-html/") + .assert() + .success(); + let lock2 = fs_err::read_to_string(context.temp_dir.join("uv.lock"))?; + assert_eq!(lock2, lock); + Ok(()) } @@ -2755,6 +2932,17 @@ fn preferences_dependent_forking() -> Result<()> { ); }); + // Assert the idempotence of `uv lock` + context + .lock() + .env_remove("UV_EXCLUDE_NEWER") + .arg("--index-url") + .arg("https://astral-sh.github.io/packse/0.3.31/simple-html/") + .assert() + .success(); + let lock2 = fs_err::read_to_string(context.temp_dir.join("uv.lock"))?; + assert_eq!(lock2, lock); + Ok(()) } @@ -2825,6 +3013,17 @@ fn fork_requires_python_full_prerelease() -> Result<()> { ); }); + // Assert the idempotence of `uv lock` + context + .lock() + .env_remove("UV_EXCLUDE_NEWER") + .arg("--index-url") + .arg("https://astral-sh.github.io/packse/0.3.31/simple-html/") + .assert() + .success(); + let lock2 = fs_err::read_to_string(context.temp_dir.join("uv.lock"))?; + assert_eq!(lock2, lock); + Ok(()) } @@ -2896,6 +3095,17 @@ fn fork_requires_python_full() -> Result<()> { ); }); + // Assert the idempotence of `uv lock` + context + .lock() + .env_remove("UV_EXCLUDE_NEWER") + .arg("--index-url") + .arg("https://astral-sh.github.io/packse/0.3.31/simple-html/") + .assert() + .success(); + let lock2 = fs_err::read_to_string(context.temp_dir.join("uv.lock"))?; + assert_eq!(lock2, lock); + Ok(()) } @@ -2982,6 +3192,17 @@ fn fork_requires_python_patch_overlap() -> Result<()> { ); }); + // Assert the idempotence of `uv lock` + context + .lock() + .env_remove("UV_EXCLUDE_NEWER") + .arg("--index-url") + .arg("https://astral-sh.github.io/packse/0.3.31/simple-html/") + .assert() + .success(); + let lock2 = fs_err::read_to_string(context.temp_dir.join("uv.lock"))?; + assert_eq!(lock2, lock); + Ok(()) } @@ -3051,5 +3272,16 @@ fn fork_requires_python() -> Result<()> { ); }); + // Assert the idempotence of `uv lock` + context + .lock() + .env_remove("UV_EXCLUDE_NEWER") + .arg("--index-url") + .arg("https://astral-sh.github.io/packse/0.3.31/simple-html/") + .assert() + .success(); + let lock2 = fs_err::read_to_string(context.temp_dir.join("uv.lock"))?; + assert_eq!(lock2, lock); + Ok(()) } diff --git a/scripts/scenarios/templates/lock.mustache b/scripts/scenarios/templates/lock.mustache index b5fa7a5c4..e8f0f6c60 100644 --- a/scripts/scenarios/templates/lock.mustache +++ b/scripts/scenarios/templates/lock.mustache @@ -7,6 +7,7 @@ #![allow(clippy::needless_raw_string_hashes)] use anyhow::Result; +use assert_cmd::assert::OutputAssertExt; use assert_fs::prelude::*; use insta::assert_snapshot; @@ -71,6 +72,17 @@ fn {{module_name}}() -> Result<()> { "### ); }); + + // Assert the idempotence of `uv lock` + context + .lock() + .env_remove("UV_EXCLUDE_NEWER") + .arg("--index-url") + .arg("https://astral-sh.github.io/packse/0.3.31/simple-html/") + .assert() + .success(); + let lock2 = fs_err::read_to_string(context.temp_dir.join("uv.lock"))?; + assert_eq!(lock2, lock); {{/expected.satisfiable}} Ok(())