use super::*;
const E2E_RELATIVE_DIR: &str = "e2e/rust";
const REGISTRY_DEPENDENCY: &str = "sample-json";
const STALE_PIN: &str = "1.25.0";
const FRESH_PIN: &str = "1.26.0";
const REQUIREMENT: &str = "1.26";
fn write_root_manifest(root: &Path, dependencies: &str) {
std::fs::write(
root.join("Cargo.toml"),
format!("[package]\nname = \"sample-core\"\nversion = \"0.1.0\"\nedition = \"2024\"\n\n{dependencies}"),
)
.expect("write root Cargo.toml");
}
fn write_generated_e2e_manifest(root: &Path) -> PathBuf {
let dir = root.join(E2E_RELATIVE_DIR);
std::fs::create_dir_all(&dir).expect("create e2e dir");
let manifest = dir.join("Cargo.toml");
std::fs::write(
&manifest,
"[workspace]\n\n[package]\nname = \"sample-core-e2e-rust\"\nversion = \"0.1.0\"\nedition = \"2024\"\n\n\
[dependencies]\nsample_core = { package = \"sample-core\", path = \"../..\" }\n",
)
.expect("write generated e2e Cargo.toml");
manifest
}
fn write_lock(root: &Path, pin: &str) {
std::fs::write(
root.join(E2E_RELATIVE_DIR).join("Cargo.lock"),
format!(
"version = 4\n\n\
[[package]]\nname = \"sample-core-e2e-rust\"\nversion = \"0.1.0\"\n\n\
[[package]]\nname = \"sample-core\"\nversion = \"0.1.0\"\n\n\
[[package]]\nname = \"{REGISTRY_DEPENDENCY}\"\nversion = \"{pin}\"\n"
),
)
.expect("write Cargo.lock");
}
fn e2e_dir(root: &Path) -> PathBuf {
root.join(E2E_RELATIVE_DIR)
}
#[test]
fn stale_lock_findings_reports_a_requirement_no_locked_version_satisfies() {
let temp = tempfile::tempdir().expect("tempdir");
let root = temp.path();
write_root_manifest(
root,
&format!("[dependencies]\n{REGISTRY_DEPENDENCY} = \"{REQUIREMENT}\"\n"),
);
write_generated_e2e_manifest(root);
write_lock(root, STALE_PIN);
let findings = stale_lock_findings(&e2e_dir(root));
assert_eq!(findings.len(), 1, "expected exactly one finding, got: {findings:?}");
let finding = &findings[0];
assert_eq!(finding.dependency, REGISTRY_DEPENDENCY);
assert_eq!(finding.requirement, REQUIREMENT);
assert_eq!(finding.locked_versions, vec![STALE_PIN.to_string()]);
assert_eq!(finding.lock, e2e_dir(root).join("Cargo.lock"));
assert_eq!(
finding.declared_in,
root.join("Cargo.toml"),
"the requirement is declared in the path dependency, not in the manifest alef generated"
);
}
#[test]
fn stale_lock_findings_accepts_a_lock_that_satisfies_every_requirement() {
let temp = tempfile::tempdir().expect("tempdir");
let root = temp.path();
write_root_manifest(
root,
&format!("[dependencies]\n{REGISTRY_DEPENDENCY} = \"{REQUIREMENT}\"\n"),
);
write_generated_e2e_manifest(root);
write_lock(root, FRESH_PIN);
let findings = stale_lock_findings(&e2e_dir(root));
assert!(
findings.is_empty(),
"a lock that resolves must be reported clean: {findings:?}"
);
}
#[test]
fn stale_lock_findings_ignores_a_dependency_absent_from_the_lock() {
let temp = tempfile::tempdir().expect("tempdir");
let root = temp.path();
write_root_manifest(root, "[dependencies]\nsample-absent = \"2\"\n");
write_generated_e2e_manifest(root);
write_lock(root, STALE_PIN);
let findings = stale_lock_findings(&e2e_dir(root));
assert!(
findings.is_empty(),
"a package missing from the lock is not evidence of staleness: {findings:?}"
);
}
#[test]
fn stale_lock_findings_resolves_a_workspace_inherited_requirement() {
let temp = tempfile::tempdir().expect("tempdir");
let root = temp.path();
write_root_manifest(
root,
&format!(
"[workspace]\nmembers = []\n\n[workspace.dependencies]\n{REGISTRY_DEPENDENCY} = \"{REQUIREMENT}\"\n\n\
[dependencies]\n{REGISTRY_DEPENDENCY} = {{ workspace = true }}\n"
),
);
write_generated_e2e_manifest(root);
write_lock(root, STALE_PIN);
let findings = stale_lock_findings(&e2e_dir(root));
assert_eq!(
findings.len(),
1,
"expected the inherited requirement, got: {findings:?}"
);
assert_eq!(findings[0].dependency, REGISTRY_DEPENDENCY);
assert_eq!(findings[0].requirement, REQUIREMENT);
}
#[test]
fn stale_lock_findings_ignores_a_git_dependency() {
let temp = tempfile::tempdir().expect("tempdir");
let root = temp.path();
write_root_manifest(
root,
&format!(
"[dependencies]\n{REGISTRY_DEPENDENCY} = {{ git = \"https://example.invalid/sample.git\", version = \
\"{REQUIREMENT}\" }}\n"
),
);
write_generated_e2e_manifest(root);
write_lock(root, STALE_PIN);
let findings = stale_lock_findings(&e2e_dir(root));
assert!(
findings.is_empty(),
"a git dependency carries no registry pin: {findings:?}"
);
}
#[test]
fn stale_lock_findings_skips_a_directory_with_no_committed_lock() {
let temp = tempfile::tempdir().expect("tempdir");
let root = temp.path();
write_root_manifest(
root,
&format!("[dependencies]\n{REGISTRY_DEPENDENCY} = \"{REQUIREMENT}\"\n"),
);
write_generated_e2e_manifest(root);
let findings = stale_lock_findings(&e2e_dir(root));
assert!(
findings.is_empty(),
"a directory with no lock has nothing to check: {findings:?}"
);
}
#[test]
fn check_generated_lock_freshness_names_the_dependency_and_the_remedy() {
let temp = tempfile::tempdir().expect("tempdir");
let root = temp.path();
write_root_manifest(
root,
&format!("[dependencies]\n{REGISTRY_DEPENDENCY} = \"{REQUIREMENT}\"\n"),
);
let manifest = write_generated_e2e_manifest(root);
write_lock(root, STALE_PIN);
let generated: HashSet<PathBuf> = [manifest, root.join(E2E_RELATIVE_DIR).join("tests/basic_test.rs")]
.into_iter()
.collect();
let error = check_generated_lock_freshness(&generated).expect("a stale lock must fail the run");
let message = format!("{error:#}");
assert!(
message.contains(REGISTRY_DEPENDENCY),
"message must name the dependency: {message}"
);
assert!(
message.contains(STALE_PIN),
"message must name the stale pin: {message}"
);
assert!(
message.contains(REQUIREMENT),
"message must name the requirement: {message}"
);
assert!(
message.contains("cargo update"),
"message must name the remedy: {message}"
);
assert!(
message.contains(&e2e_dir(root).join("Cargo.lock").display().to_string()),
"message must name the lock: {message}"
);
}
#[test]
fn check_generated_lock_freshness_passes_a_resolvable_lock() {
let temp = tempfile::tempdir().expect("tempdir");
let root = temp.path();
write_root_manifest(
root,
&format!("[dependencies]\n{REGISTRY_DEPENDENCY} = \"{REQUIREMENT}\"\n"),
);
let manifest = write_generated_e2e_manifest(root);
write_lock(root, FRESH_PIN);
let generated: HashSet<PathBuf> = [manifest].into_iter().collect();
assert!(
check_generated_lock_freshness(&generated).is_none(),
"a resolvable lock must not fail the run"
);
}
#[test]
fn check_generated_lock_freshness_ignores_non_manifest_paths() {
let temp = tempfile::tempdir().expect("tempdir");
let root = temp.path();
write_root_manifest(
root,
&format!("[dependencies]\n{REGISTRY_DEPENDENCY} = \"{REQUIREMENT}\"\n"),
);
write_generated_e2e_manifest(root);
write_lock(root, STALE_PIN);
let generated: HashSet<PathBuf> = [root.join(E2E_RELATIVE_DIR).join("tests/basic_test.rs")]
.into_iter()
.collect();
assert!(check_generated_lock_freshness(&generated).is_none());
}
mod pending_publish {
use super::*;
const CANONICAL: &str = "3.12.0";
const PUBLISHED: &str = "3.11.6";
const LOCAL_CRATE: &str = "sample-core";
const GENERATED_RELATIVE_DIR: &str = "test_apps/rust";
fn write_root_crate(root: &Path, version: &str) {
std::fs::write(
root.join("Cargo.toml"),
format!("[package]\nname = \"{LOCAL_CRATE}\"\nversion = \"{version}\"\nedition = \"2024\"\n"),
)
.expect("write root Cargo.toml");
}
fn write_test_app_manifest(root: &Path, required_version: &str) -> PathBuf {
let dir = root.join(GENERATED_RELATIVE_DIR);
std::fs::create_dir_all(&dir).expect("create test_apps dir");
let manifest = dir.join("Cargo.toml");
std::fs::write(
&manifest,
format!(
"[workspace]\n\n[package]\nname = \"{LOCAL_CRATE}-e2e-rust\"\nversion = \"0.0.0\"\nedition = \
\"2024\"\n\n[dependencies]\n{LOCAL_CRATE} = {{ version = \"{required_version}\" }}\n"
),
)
.expect("write test-app Cargo.toml");
manifest
}
fn write_test_app_lock(root: &Path, locked_version: &str) {
std::fs::write(
root.join(GENERATED_RELATIVE_DIR).join("Cargo.lock"),
format!(
"version = 3\n\n[[package]]\nname = \"{LOCAL_CRATE}\"\nversion = \"{locked_version}\"\nsource = \
\"registry+https://github.com/rust-lang/crates.io-index\"\n"
),
)
.expect("write test-app Cargo.lock");
}
#[test]
fn plain_check_still_fails_on_a_pending_publish_disagreement() {
let temp = tempfile::tempdir().expect("tempdir");
let root = temp.path();
write_root_crate(root, CANONICAL);
let manifest = write_test_app_manifest(root, CANONICAL);
write_test_app_lock(root, PUBLISHED);
let generated: HashSet<PathBuf> = [manifest].into_iter().collect();
assert!(
check_generated_lock_freshness(&generated).is_some(),
"control: the plain check has no pending-publish exemption and must still fail here"
);
}
#[test]
fn tolerating_variant_warns_instead_of_failing_on_a_pending_publish_disagreement() {
let temp = tempfile::tempdir().expect("tempdir");
let root = temp.path();
write_root_crate(root, CANONICAL);
let manifest = write_test_app_manifest(root, CANONICAL);
write_test_app_lock(root, PUBLISHED);
let generated: HashSet<PathBuf> = [manifest].into_iter().collect();
let result = check_generated_lock_freshness_tolerating_pending_publish(&generated, root, Some(CANONICAL));
assert!(
result.is_none(),
"a disagreement fully explained by this crate's own not-yet-published version must not fail the \
run: {result:?}"
);
}
#[test]
fn tolerating_variant_without_canonical_behaves_like_the_plain_check() {
let temp = tempfile::tempdir().expect("tempdir");
let root = temp.path();
write_root_crate(root, CANONICAL);
let manifest = write_test_app_manifest(root, CANONICAL);
write_test_app_lock(root, PUBLISHED);
let generated: HashSet<PathBuf> = [manifest].into_iter().collect();
assert!(
check_generated_lock_freshness_tolerating_pending_publish(&generated, root, None).is_some(),
"no canonical version means no exemption is possible; this must still fail"
);
}
#[test]
fn tolerating_variant_still_fails_on_a_disagreement_not_explained_by_pending_publish() {
let temp = tempfile::tempdir().expect("tempdir");
let root = temp.path();
write_root_manifest(
root,
&format!("[dependencies]\n{REGISTRY_DEPENDENCY} = \"{REQUIREMENT}\"\n"),
);
let manifest = write_generated_e2e_manifest(root);
write_lock(root, STALE_PIN);
let generated: HashSet<PathBuf> = [manifest].into_iter().collect();
assert!(
check_generated_lock_freshness_tolerating_pending_publish(&generated, root, Some(CANONICAL)).is_some(),
"a third-party lock drift unrelated to this crate's own version must still fail the run"
);
}
}
mod node {
use super::*;
const NODE_DIR_RELATIVE: &str = "e2e/typescript";
const NODE_DEPENDENCY: &str = "sample-pkg";
const NODE_STALE_SPEC: &str = "1.3.0";
const NODE_FRESH_SPEC: &str = "1.2.3";
fn node_dir(root: &Path) -> PathBuf {
root.join(NODE_DIR_RELATIVE)
}
fn write_package_json(root: &Path, specifier: &str) -> PathBuf {
let dir = node_dir(root);
std::fs::create_dir_all(&dir).expect("create node dir");
let manifest = dir.join("package.json");
std::fs::write(
&manifest,
format!(
"{{\n \"name\": \"sample-pkg-e2e-typescript\",\n \"version\": \"0.1.0\",\n \"private\": \
true,\n \"devDependencies\": {{\n \"{NODE_DEPENDENCY}\": \"{specifier}\"\n }}\n}}\n"
),
)
.expect("write package.json");
manifest
}
fn write_pnpm_lock_v9(root: &Path, locked_specifier: &str) {
std::fs::write(
node_dir(root).join("pnpm-lock.yaml"),
format!(
"lockfileVersion: '9.0'\n\nimporters:\n .:\n devDependencies:\n \
{NODE_DEPENDENCY}:\n specifier: {locked_specifier}\n version: \
{locked_specifier}\n"
),
)
.expect("write pnpm-lock.yaml");
}
fn write_pnpm_lock_v6(root: &Path, locked_specifier: &str) {
std::fs::write(
node_dir(root).join("pnpm-lock.yaml"),
format!(
"lockfileVersion: '6.0'\n\ndevDependencies:\n {NODE_DEPENDENCY}:\n specifier: \
{locked_specifier}\n version: {locked_specifier}\n"
),
)
.expect("write pnpm-lock.yaml");
}
#[test]
fn stale_node_lock_findings_reports_a_specifier_mismatch() {
let temp = tempfile::tempdir().expect("tempdir");
let root = temp.path();
write_package_json(root, NODE_STALE_SPEC);
write_pnpm_lock_v9(root, NODE_FRESH_SPEC);
let findings = stale_node_lock_findings(&node_dir(root));
assert_eq!(findings.len(), 1, "expected exactly one finding, got: {findings:?}");
let finding = &findings[0];
assert_eq!(finding.dependency, NODE_DEPENDENCY);
assert_eq!(finding.bucket, "devDependencies");
assert_eq!(finding.requirement, NODE_STALE_SPEC);
assert_eq!(finding.locked_requirement, NODE_FRESH_SPEC);
assert_eq!(finding.lock, node_dir(root).join("pnpm-lock.yaml"));
assert_eq!(finding.declared_in, node_dir(root).join("package.json"));
}
#[test]
fn stale_node_lock_findings_accepts_a_lock_that_matches() {
let temp = tempfile::tempdir().expect("tempdir");
let root = temp.path();
write_package_json(root, NODE_FRESH_SPEC);
write_pnpm_lock_v9(root, NODE_FRESH_SPEC);
let findings = stale_node_lock_findings(&node_dir(root));
assert!(
findings.is_empty(),
"a lock matching package.json must be reported clean: {findings:?}"
);
}
#[test]
fn stale_node_lock_findings_reports_a_mismatch_in_the_flat_lockfile_v6_shape() {
let temp = tempfile::tempdir().expect("tempdir");
let root = temp.path();
write_package_json(root, NODE_STALE_SPEC);
write_pnpm_lock_v6(root, NODE_FRESH_SPEC);
let findings = stale_node_lock_findings(&node_dir(root));
assert_eq!(
findings.len(),
1,
"expected the flat lockfileVersion 6 shape to be read too, got: {findings:?}"
);
assert_eq!(findings[0].locked_requirement, NODE_FRESH_SPEC);
}
#[test]
fn stale_node_lock_findings_ignores_a_dependency_absent_from_the_lock() {
let temp = tempfile::tempdir().expect("tempdir");
let root = temp.path();
write_package_json(root, NODE_STALE_SPEC);
let dir = node_dir(root);
std::fs::write(
dir.join("pnpm-lock.yaml"),
"lockfileVersion: '9.0'\n\nimporters:\n .:\n devDependencies:\n other-pkg:\n \
specifier: 2.0.0\n version: 2.0.0\n",
)
.expect("write pnpm-lock.yaml");
let findings = stale_node_lock_findings(&dir);
assert!(
findings.is_empty(),
"a package missing from the lock's bucket is not evidence of drift: {findings:?}"
);
}
#[test]
fn stale_node_lock_findings_ignores_a_workspace_specifier() {
let temp = tempfile::tempdir().expect("tempdir");
let root = temp.path();
write_package_json(root, "workspace:*");
write_pnpm_lock_v9(root, "workspace:^1.0.0");
let findings = stale_node_lock_findings(&node_dir(root));
assert!(
findings.is_empty(),
"workspace: specifiers are not directly comparable: {findings:?}"
);
}
#[test]
fn stale_node_lock_findings_ignores_a_file_specifier() {
let temp = tempfile::tempdir().expect("tempdir");
let root = temp.path();
write_package_json(root, "file:../../..");
write_pnpm_lock_v9(root, "file:../../../dist");
let findings = stale_node_lock_findings(&node_dir(root));
assert!(
findings.is_empty(),
"file: specifiers are not directly comparable: {findings:?}"
);
}
#[test]
fn check_generated_node_lock_freshness_names_the_dependency_and_the_remedy() {
let temp = tempfile::tempdir().expect("tempdir");
let root = temp.path();
let manifest = write_package_json(root, NODE_STALE_SPEC);
write_pnpm_lock_v9(root, NODE_FRESH_SPEC);
let generated: HashSet<PathBuf> = [manifest].into_iter().collect();
let error = check_generated_node_lock_freshness(&generated, root).expect("a stale lock must fail the run");
let message = format!("{error:#}");
assert!(
message.contains(NODE_DEPENDENCY),
"message must name the dependency: {message}"
);
assert!(
message.contains(NODE_STALE_SPEC),
"message must name the package.json specifier: {message}"
);
assert!(
message.contains(NODE_FRESH_SPEC),
"message must name the locked specifier: {message}"
);
assert!(
message.contains("pnpm install"),
"message must name the remedy: {message}"
);
assert!(
message.contains(&node_dir(root).join("pnpm-lock.yaml").display().to_string()),
"message must name the lock: {message}"
);
}
#[test]
fn check_generated_node_lock_freshness_passes_a_matching_lock() {
let temp = tempfile::tempdir().expect("tempdir");
let root = temp.path();
let manifest = write_package_json(root, NODE_FRESH_SPEC);
write_pnpm_lock_v9(root, NODE_FRESH_SPEC);
let generated: HashSet<PathBuf> = [manifest].into_iter().collect();
assert!(
check_generated_node_lock_freshness(&generated, root).is_none(),
"a matching lock must not fail the run"
);
}
#[test]
fn check_generated_node_lock_freshness_ignores_non_manifest_paths() {
let temp = tempfile::tempdir().expect("tempdir");
let root = temp.path();
write_package_json(root, NODE_STALE_SPEC);
write_pnpm_lock_v9(root, NODE_FRESH_SPEC);
let generated: HashSet<PathBuf> = [node_dir(root).join("src/index.ts")].into_iter().collect();
assert!(check_generated_node_lock_freshness(&generated, root).is_none());
}
mod pending_publish {
use super::*;
use crate::core::config::ResolvedCrateConfig;
use crate::core::config::e2e::{E2eConfig, PackageRef, RegistryConfig};
fn resolved_cfg_with_node_registry_package(pkg_name: &str, pkg_version: &str) -> ResolvedCrateConfig {
let e2e = E2eConfig {
registry: RegistryConfig {
packages: [(
"node".to_string(),
PackageRef {
name: Some(pkg_name.to_string()),
version: Some(pkg_version.to_string()),
..PackageRef::default()
},
)]
.into_iter()
.collect(),
..RegistryConfig::default()
},
..E2eConfig::default()
};
ResolvedCrateConfig {
e2e: Some(e2e),
..ResolvedCrateConfig::default()
}
}
#[test]
fn plain_check_still_fails_on_a_pending_publish_disagreement() {
let temp = tempfile::tempdir().expect("tempdir");
let root = temp.path();
let manifest = write_package_json(root, NODE_STALE_SPEC);
write_pnpm_lock_v9(root, NODE_FRESH_SPEC);
let generated: HashSet<PathBuf> = [manifest].into_iter().collect();
assert!(
check_generated_node_lock_freshness(&generated, root).is_some(),
"control: the plain check has no pending-publish exemption and must still fail here"
);
}
#[test]
fn tolerating_variant_warns_instead_of_failing_when_the_requirement_matches_the_configured_registry_package() {
let temp = tempfile::tempdir().expect("tempdir");
let root = temp.path();
let manifest = write_package_json(root, NODE_STALE_SPEC);
write_pnpm_lock_v9(root, NODE_FRESH_SPEC);
let generated: HashSet<PathBuf> = [manifest].into_iter().collect();
let resolved_cfg = resolved_cfg_with_node_registry_package(NODE_DEPENDENCY, NODE_STALE_SPEC);
let result =
check_generated_node_lock_freshness_tolerating_pending_publish(&generated, root, Some(&resolved_cfg));
assert!(
result.is_none(),
"a disagreement fully explained by this crate's own configured registry \
self-dependency must not fail the run: {result:?}"
);
}
#[test]
fn tolerating_variant_without_resolved_cfg_behaves_like_the_plain_check() {
let temp = tempfile::tempdir().expect("tempdir");
let root = temp.path();
let manifest = write_package_json(root, NODE_STALE_SPEC);
write_pnpm_lock_v9(root, NODE_FRESH_SPEC);
let generated: HashSet<PathBuf> = [manifest].into_iter().collect();
assert!(
check_generated_node_lock_freshness_tolerating_pending_publish(&generated, root, None).is_some(),
"no resolved config means no exemption is possible; this must still fail"
);
}
#[test]
fn tolerating_variant_still_fails_on_a_disagreement_not_explained_by_pending_publish() {
let temp = tempfile::tempdir().expect("tempdir");
let root = temp.path();
let manifest = write_package_json(root, NODE_STALE_SPEC);
write_pnpm_lock_v9(root, NODE_FRESH_SPEC);
let generated: HashSet<PathBuf> = [manifest].into_iter().collect();
let resolved_cfg = resolved_cfg_with_node_registry_package("unrelated-package", "9.9.9");
assert!(
check_generated_node_lock_freshness_tolerating_pending_publish(&generated, root, Some(&resolved_cfg),)
.is_some(),
"a third-party lock drift unrelated to this crate's own registry self-dependency \
must still fail the run"
);
}
}
}
#[path = "lock_freshness_registered_manifest_tests.rs"]
mod registered_unmarkable_manifest_gap;
mod uv {
use super::*;
const UV_DIR_RELATIVE: &str = "e2e/python";
const UV_DEPENDENCY: &str = "sample-pkg";
const UV_STALE_SPEC: &str = ">=1.1.1";
const UV_FRESH_SPEC: &str = ">=1.2.0";
fn uv_dir(root: &Path) -> PathBuf {
root.join(UV_DIR_RELATIVE)
}
fn write_pyproject(root: &Path, specifier: &str) -> PathBuf {
let dir = uv_dir(root);
std::fs::create_dir_all(&dir).expect("create uv dir");
let manifest = dir.join("pyproject.toml");
std::fs::write(
&manifest,
format!(
"[project]\nname = \"sample-pkg-e2e\"\nversion = \"0.0.0\"\ndependencies = \
[\"{UV_DEPENDENCY}{specifier}\"]\n"
),
)
.expect("write pyproject.toml");
manifest
}
fn write_uv_lock_project_shape(root: &Path, locked_specifier: &str) {
std::fs::write(
uv_dir(root).join("uv.lock"),
format!(
"version = 1\nrequires-python = \">=3.10\"\n\n\
[[package]]\nname = \"sample-pkg-e2e\"\nversion = \"0.0.0\"\nsource = {{ virtual = \".\" }}\n\
dependencies = [\n {{ name = \"{UV_DEPENDENCY}\" }},\n]\n\n\
[package.metadata]\nrequires-dist = [{{ name = \"{UV_DEPENDENCY}\", specifier = \
\"{locked_specifier}\" }}]\n"
),
)
.expect("write uv.lock");
}
fn write_uv_lock_manifest_shape(root: &Path, locked_specifier: &str) {
std::fs::write(
uv_dir(root).join("uv.lock"),
format!(
"version = 1\nrequires-python = \">=3.10\"\n\n\
[manifest]\nrequirements = [{{ name = \"{UV_DEPENDENCY}\", specifier = \
\"{locked_specifier}\" }}]\n"
),
)
.expect("write uv.lock");
}
#[test]
fn stale_uv_lock_findings_reports_a_specifier_mismatch() {
let temp = tempfile::tempdir().expect("tempdir");
let root = temp.path();
write_pyproject(root, UV_STALE_SPEC);
write_uv_lock_project_shape(root, UV_FRESH_SPEC);
let findings = stale_uv_lock_findings(&uv_dir(root));
assert_eq!(findings.len(), 1, "expected exactly one finding, got: {findings:?}");
let finding = &findings[0];
assert_eq!(finding.dependency, UV_DEPENDENCY);
assert_eq!(finding.requirement, UV_STALE_SPEC);
assert_eq!(finding.locked_requirement, UV_FRESH_SPEC);
assert_eq!(finding.lock, uv_dir(root).join("uv.lock"));
assert_eq!(finding.declared_in, uv_dir(root).join("pyproject.toml"));
}
#[test]
fn stale_uv_lock_findings_accepts_a_lock_that_matches() {
let temp = tempfile::tempdir().expect("tempdir");
let root = temp.path();
write_pyproject(root, UV_FRESH_SPEC);
write_uv_lock_project_shape(root, UV_FRESH_SPEC);
let findings = stale_uv_lock_findings(&uv_dir(root));
assert!(
findings.is_empty(),
"a lock matching pyproject.toml must be reported clean: {findings:?}"
);
}
#[test]
fn stale_uv_lock_findings_ignores_a_dependency_absent_from_the_lock() {
let temp = tempfile::tempdir().expect("tempdir");
let root = temp.path();
write_pyproject(root, UV_STALE_SPEC);
std::fs::write(
uv_dir(root).join("uv.lock"),
"version = 1\nrequires-python = \">=3.10\"\n\n\
[[package]]\nname = \"sample-pkg-e2e\"\nversion = \"0.0.0\"\nsource = { virtual = \".\" }\n\n\
[package.metadata]\nrequires-dist = [{ name = \"other-pkg\", specifier = \">=2.0\" }]\n",
)
.expect("write uv.lock");
let findings = stale_uv_lock_findings(&uv_dir(root));
assert!(
findings.is_empty(),
"a package missing from the lock's recorded copy is not evidence of drift: {findings:?}"
);
}
#[test]
fn stale_uv_lock_findings_reports_a_mismatch_in_the_manifest_requirements_fallback_shape() {
let temp = tempfile::tempdir().expect("tempdir");
let root = temp.path();
write_pyproject(root, UV_STALE_SPEC);
write_uv_lock_manifest_shape(root, UV_FRESH_SPEC);
let findings = stale_uv_lock_findings(&uv_dir(root));
assert_eq!(
findings.len(),
1,
"expected the manifest.requirements fallback shape to be read too, got: {findings:?}"
);
assert_eq!(findings[0].locked_requirement, UV_FRESH_SPEC);
}
#[test]
fn stale_uv_lock_findings_ignores_a_marker_conditional_dependency() {
let temp = tempfile::tempdir().expect("tempdir");
let root = temp.path();
let dir = uv_dir(root);
std::fs::create_dir_all(&dir).expect("create uv dir");
std::fs::write(
dir.join("pyproject.toml"),
format!(
"[project]\nname = \"sample-pkg-e2e\"\nversion = \"0.0.0\"\ndependencies = \
[\"{UV_DEPENDENCY}{UV_STALE_SPEC}; python_version < '3.11'\"]\n"
),
)
.expect("write pyproject.toml");
write_uv_lock_project_shape(root, UV_FRESH_SPEC);
let findings = stale_uv_lock_findings(&uv_dir(root));
assert!(
findings.is_empty(),
"a marker-conditional requirement is not directly comparable: {findings:?}"
);
}
#[test]
fn stale_uv_lock_findings_ignores_a_source_overridden_dependency() {
let temp = tempfile::tempdir().expect("tempdir");
let root = temp.path();
let dir = uv_dir(root);
std::fs::create_dir_all(&dir).expect("create uv dir");
std::fs::write(
dir.join("pyproject.toml"),
format!(
"[project]\nname = \"sample-pkg-e2e\"\nversion = \"0.0.0\"\ndependencies = \
[\"{UV_DEPENDENCY}\"]\n\n[tool.uv]\nsources.{UV_DEPENDENCY} = {{ path = \"../..\" }}\n"
),
)
.expect("write pyproject.toml");
write_uv_lock_project_shape(root, UV_FRESH_SPEC);
let findings = stale_uv_lock_findings(&uv_dir(root));
assert!(
findings.is_empty(),
"a [tool.uv.sources]-overridden dependency is not directly comparable: {findings:?}"
);
}
#[test]
fn check_generated_uv_lock_freshness_names_the_dependency_and_the_remedy() {
let temp = tempfile::tempdir().expect("tempdir");
let root = temp.path();
let manifest = write_pyproject(root, UV_STALE_SPEC);
write_uv_lock_project_shape(root, UV_FRESH_SPEC);
let generated: HashSet<PathBuf> = [manifest].into_iter().collect();
let error = check_generated_uv_lock_freshness(&generated).expect("a stale lock must fail the run");
let message = format!("{error:#}");
assert!(
message.contains(UV_DEPENDENCY),
"message must name the dependency: {message}"
);
assert!(
message.contains(UV_STALE_SPEC),
"message must name the pyproject.toml specifier: {message}"
);
assert!(
message.contains(UV_FRESH_SPEC),
"message must name the locked specifier: {message}"
);
assert!(message.contains("uv lock"), "message must name the remedy: {message}");
assert!(
message.contains(&uv_dir(root).join("uv.lock").display().to_string()),
"message must name the lock: {message}"
);
}
#[test]
fn check_generated_uv_lock_freshness_passes_a_matching_lock() {
let temp = tempfile::tempdir().expect("tempdir");
let root = temp.path();
let manifest = write_pyproject(root, UV_FRESH_SPEC);
write_uv_lock_project_shape(root, UV_FRESH_SPEC);
let generated: HashSet<PathBuf> = [manifest].into_iter().collect();
assert!(
check_generated_uv_lock_freshness(&generated).is_none(),
"a matching lock must not fail the run"
);
}
#[test]
fn check_generated_uv_lock_freshness_ignores_non_manifest_paths() {
let temp = tempfile::tempdir().expect("tempdir");
let root = temp.path();
write_pyproject(root, UV_STALE_SPEC);
write_uv_lock_project_shape(root, UV_FRESH_SPEC);
let generated: HashSet<PathBuf> = [uv_dir(root).join("tests/test_basic.py")].into_iter().collect();
assert!(check_generated_uv_lock_freshness(&generated).is_none());
}
mod pending_publish {
use super::*;
use crate::core::config::ResolvedCrateConfig;
use crate::core::config::e2e::{E2eConfig, PackageRef, RegistryConfig};
fn resolved_cfg_with_python_registry_package(pkg_name: &str, pkg_version: &str) -> ResolvedCrateConfig {
let e2e = E2eConfig {
registry: RegistryConfig {
packages: [(
"python".to_string(),
PackageRef {
name: Some(pkg_name.to_string()),
version: Some(pkg_version.to_string()),
..PackageRef::default()
},
)]
.into_iter()
.collect(),
..RegistryConfig::default()
},
..E2eConfig::default()
};
ResolvedCrateConfig {
e2e: Some(e2e),
..ResolvedCrateConfig::default()
}
}
#[test]
fn plain_check_still_fails_on_a_pending_publish_disagreement() {
let temp = tempfile::tempdir().expect("tempdir");
let root = temp.path();
let manifest = write_pyproject(root, UV_STALE_SPEC);
write_uv_lock_project_shape(root, UV_FRESH_SPEC);
let generated: HashSet<PathBuf> = [manifest].into_iter().collect();
assert!(
check_generated_uv_lock_freshness(&generated).is_some(),
"control: the plain check has no pending-publish exemption and must still fail here"
);
}
#[test]
fn tolerating_variant_warns_instead_of_failing_when_the_requirement_matches_the_configured_registry_package() {
let temp = tempfile::tempdir().expect("tempdir");
let root = temp.path();
let manifest = write_pyproject(root, UV_STALE_SPEC);
write_uv_lock_project_shape(root, UV_FRESH_SPEC);
let generated: HashSet<PathBuf> = [manifest].into_iter().collect();
let resolved_cfg = resolved_cfg_with_python_registry_package(UV_DEPENDENCY, UV_STALE_SPEC);
let result = check_generated_uv_lock_freshness_tolerating_pending_publish(&generated, Some(&resolved_cfg));
assert!(
result.is_none(),
"a disagreement fully explained by this crate's own configured registry \
self-dependency must not fail the run: {result:?}"
);
}
#[test]
fn tolerating_variant_without_resolved_cfg_behaves_like_the_plain_check() {
let temp = tempfile::tempdir().expect("tempdir");
let root = temp.path();
let manifest = write_pyproject(root, UV_STALE_SPEC);
write_uv_lock_project_shape(root, UV_FRESH_SPEC);
let generated: HashSet<PathBuf> = [manifest].into_iter().collect();
assert!(
check_generated_uv_lock_freshness_tolerating_pending_publish(&generated, None).is_some(),
"no resolved config means no exemption is possible; this must still fail"
);
}
#[test]
fn tolerating_variant_still_fails_on_a_disagreement_not_explained_by_pending_publish() {
let temp = tempfile::tempdir().expect("tempdir");
let root = temp.path();
let manifest = write_pyproject(root, UV_STALE_SPEC);
write_uv_lock_project_shape(root, UV_FRESH_SPEC);
let generated: HashSet<PathBuf> = [manifest].into_iter().collect();
let resolved_cfg = resolved_cfg_with_python_registry_package("unrelated-package", ">=9.9.9");
assert!(
check_generated_uv_lock_freshness_tolerating_pending_publish(&generated, Some(&resolved_cfg)).is_some(),
"a third-party lock drift unrelated to this crate's own registry self-dependency \
must still fail the run"
);
}
}
}