summaryrefslogtreecommitdiffstats
path: root/src/tools/cargo/tests/testsuite/lockfile_compat.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/cargo/tests/testsuite/lockfile_compat.rs')
-rw-r--r--src/tools/cargo/tests/testsuite/lockfile_compat.rs890
1 files changed, 890 insertions, 0 deletions
diff --git a/src/tools/cargo/tests/testsuite/lockfile_compat.rs b/src/tools/cargo/tests/testsuite/lockfile_compat.rs
new file mode 100644
index 000000000..aad8723c3
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/lockfile_compat.rs
@@ -0,0 +1,890 @@
+//! Tests for supporting older versions of the Cargo.lock file format.
+
+use cargo_test_support::compare::assert_match_exact;
+use cargo_test_support::git;
+use cargo_test_support::registry::Package;
+use cargo_test_support::{basic_lib_manifest, basic_manifest, project};
+
+#[cargo_test]
+fn oldest_lockfile_still_works() {
+ let cargo_commands = vec!["build", "update"];
+ for cargo_command in cargo_commands {
+ oldest_lockfile_still_works_with_command(cargo_command);
+ }
+}
+
+fn oldest_lockfile_still_works_with_command(cargo_command: &str) {
+ Package::new("bar", "0.1.0").publish();
+
+ let expected_lockfile = r#"# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "bar"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "[..]"
+
+[[package]]
+name = "foo"
+version = "0.0.1"
+dependencies = [
+ "bar",
+]
+"#;
+
+ let old_lockfile = r#"
+[root]
+name = "foo"
+version = "0.0.1"
+dependencies = [
+ "bar 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "bar"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+"#;
+
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ bar = "0.1.0"
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .file("Cargo.lock", old_lockfile)
+ .build();
+
+ p.cargo(cargo_command).run();
+
+ let lock = p.read_lockfile();
+ assert_match_exact(expected_lockfile, &lock);
+}
+
+#[cargo_test]
+fn frozen_flag_preserves_old_lockfile() {
+ let cksum = Package::new("bar", "0.1.0").publish();
+
+ let old_lockfile = format!(
+ r#"[root]
+name = "foo"
+version = "0.0.1"
+dependencies = [
+ "bar 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "bar"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[metadata]
+"checksum bar 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "{}"
+"#,
+ cksum,
+ );
+
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ bar = "0.1.0"
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .file("Cargo.lock", &old_lockfile)
+ .build();
+
+ p.cargo("check --locked").run();
+
+ let lock = p.read_lockfile();
+ assert_match_exact(&old_lockfile, &lock);
+}
+
+#[cargo_test]
+fn totally_wild_checksums_works() {
+ Package::new("bar", "0.1.0").publish();
+
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ bar = "0.1.0"
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .file(
+ "Cargo.lock",
+ r#"
+[[package]]
+name = "foo"
+version = "0.0.1"
+dependencies = [
+ "bar 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "bar"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[metadata]
+"checksum baz 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "checksum"
+"checksum bar 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "checksum"
+"#,
+ );
+
+ let p = p.build();
+
+ p.cargo("check").run();
+
+ let lock = p.read_lockfile();
+ assert_match_exact(
+ r#"# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "bar"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "[..]"
+
+[[package]]
+name = "foo"
+version = "0.0.1"
+dependencies = [
+ "bar",
+]
+"#,
+ &lock,
+ );
+}
+
+#[cargo_test]
+fn wrong_checksum_is_an_error() {
+ Package::new("bar", "0.1.0").publish();
+
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ bar = "0.1.0"
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .file(
+ "Cargo.lock",
+ r#"
+[[package]]
+name = "foo"
+version = "0.0.1"
+dependencies = [
+ "bar 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "bar"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[metadata]
+"checksum bar 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "checksum"
+"#,
+ );
+
+ let p = p.build();
+
+ p.cargo("check")
+ .with_status(101)
+ .with_stderr(
+ "\
+[UPDATING] `[..]` index
+error: checksum for `bar v0.1.0` changed between lock files
+
+this could be indicative of a few possible errors:
+
+ * the lock file is corrupt
+ * a replacement source in use (e.g., a mirror) returned a different checksum
+ * the source itself may be corrupt in one way or another
+
+unable to verify that `bar v0.1.0` is the same as when the lockfile was generated
+
+",
+ )
+ .run();
+}
+
+// If the checksum is unlisted in the lock file (e.g., <none>) yet we can
+// calculate it (e.g., it's a registry dep), then we should in theory just fill
+// it in.
+#[cargo_test]
+fn unlisted_checksum_is_bad_if_we_calculate() {
+ Package::new("bar", "0.1.0").publish();
+
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ bar = "0.1.0"
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .file(
+ "Cargo.lock",
+ r#"
+[[package]]
+name = "foo"
+version = "0.0.1"
+dependencies = [
+ "bar 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "bar"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[metadata]
+"checksum bar 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "<none>"
+"#,
+ );
+ let p = p.build();
+
+ p.cargo("fetch")
+ .with_status(101)
+ .with_stderr(
+ "\
+[UPDATING] `[..]` index
+error: checksum for `bar v0.1.0` was not previously calculated, but a checksum \
+could now be calculated
+
+this could be indicative of a few possible situations:
+
+ * the source `[..]` did not previously support checksums,
+ but was replaced with one that does
+ * newer Cargo implementations know how to checksum this source, but this
+ older implementation does not
+ * the lock file is corrupt
+
+",
+ )
+ .run();
+}
+
+// If the checksum is listed in the lock file yet we cannot calculate it (e.g.,
+// Git dependencies as of today), then make sure we choke.
+#[cargo_test]
+fn listed_checksum_bad_if_we_cannot_compute() {
+ let git = git::new("bar", |p| {
+ p.file("Cargo.toml", &basic_manifest("bar", "0.1.0"))
+ .file("src/lib.rs", "")
+ });
+
+ let p = project()
+ .file(
+ "Cargo.toml",
+ &format!(
+ r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ bar = {{ git = '{}' }}
+ "#,
+ git.url()
+ ),
+ )
+ .file("src/lib.rs", "")
+ .file(
+ "Cargo.lock",
+ &format!(
+ r#"
+[[package]]
+name = "foo"
+version = "0.0.1"
+dependencies = [
+ "bar 0.1.0 (git+{0})"
+]
+
+[[package]]
+name = "bar"
+version = "0.1.0"
+source = "git+{0}"
+
+[metadata]
+"checksum bar 0.1.0 (git+{0})" = "checksum"
+"#,
+ git.url()
+ ),
+ );
+
+ let p = p.build();
+
+ p.cargo("fetch")
+ .with_status(101)
+ .with_stderr(
+ "\
+[UPDATING] git repository `[..]`
+error: checksum for `bar v0.1.0 ([..])` could not be calculated, but a \
+checksum is listed in the existing lock file[..]
+
+this could be indicative of a few possible situations:
+
+ * the source `[..]` supports checksums,
+ but was replaced with one that doesn't
+ * the lock file is corrupt
+
+unable to verify that `bar v0.1.0 ([..])` is the same as when the lockfile was generated
+
+",
+ )
+ .run();
+}
+
+#[cargo_test]
+fn current_lockfile_format() {
+ Package::new("bar", "0.1.0").publish();
+
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ bar = "0.1.0"
+ "#,
+ )
+ .file("src/lib.rs", "");
+ let p = p.build();
+
+ p.cargo("check").run();
+
+ let actual = p.read_lockfile();
+
+ let expected = "\
+# This file is automatically @generated by Cargo.\n# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = \"bar\"
+version = \"0.1.0\"
+source = \"registry+https://github.com/rust-lang/crates.io-index\"
+checksum = \"[..]\"
+
+[[package]]
+name = \"foo\"
+version = \"0.0.1\"
+dependencies = [
+ \"bar\",
+]
+";
+ assert_match_exact(expected, &actual);
+}
+
+#[cargo_test]
+fn lockfile_without_root() {
+ Package::new("bar", "0.1.0").publish();
+
+ let lockfile = r#"
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "bar"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "foo"
+version = "0.0.1"
+dependencies = [
+ "bar",
+]
+"#;
+
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ bar = "0.1.0"
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .file("Cargo.lock", lockfile);
+
+ let p = p.build();
+
+ p.cargo("check").run();
+
+ let lock = p.read_lockfile();
+ assert_match_exact(
+ r#"# [..]
+# [..]
+version = 3
+
+[[package]]
+name = "bar"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "[..]"
+
+[[package]]
+name = "foo"
+version = "0.0.1"
+dependencies = [
+ "bar",
+]
+"#,
+ &lock,
+ );
+}
+
+#[cargo_test]
+fn locked_correct_error() {
+ Package::new("bar", "0.1.0").publish();
+
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ bar = "0.1.0"
+ "#,
+ )
+ .file("src/lib.rs", "");
+ let p = p.build();
+
+ p.cargo("check --locked")
+ .with_status(101)
+ .with_stderr(
+ "\
+[UPDATING] `[..]` index
+error: the lock file [CWD]/Cargo.lock needs to be updated but --locked was passed to prevent this
+If you want to try to generate the lock file without accessing the network, \
+remove the --locked flag and use --offline instead.
+",
+ )
+ .run();
+}
+
+#[cargo_test]
+fn v2_format_preserved() {
+ let cksum = Package::new("bar", "0.1.0").publish();
+
+ let lockfile = format!(
+ r#"# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "bar"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "{}"
+
+[[package]]
+name = "foo"
+version = "0.0.1"
+dependencies = [
+ "bar",
+]
+"#,
+ cksum
+ );
+
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ bar = "0.1.0"
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .file("Cargo.lock", &lockfile)
+ .build();
+
+ p.cargo("fetch").run();
+
+ let lock = p.read_lockfile();
+ assert_match_exact(&lockfile, &lock);
+}
+
+#[cargo_test]
+fn v2_path_and_crates_io() {
+ let cksum010 = Package::new("a", "0.1.0").publish();
+ let cksum020 = Package::new("a", "0.2.0").publish();
+
+ let lockfile = format!(
+ r#"# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "a"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "{}"
+
+[[package]]
+name = "a"
+version = "0.2.0"
+
+[[package]]
+name = "a"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "{}"
+
+[[package]]
+name = "foo"
+version = "0.0.1"
+dependencies = [
+ "a 0.1.0",
+ "a 0.2.0",
+ "a 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+"#,
+ cksum010, cksum020,
+ );
+
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ a = { path = 'a' }
+ b = { version = "0.1", package = 'a' }
+ c = { version = "0.2", package = 'a' }
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .file(
+ "a/Cargo.toml",
+ r#"
+ [package]
+ name = "a"
+ version = "0.2.0"
+ "#,
+ )
+ .file("a/src/lib.rs", "")
+ .file("Cargo.lock", &lockfile)
+ .build();
+
+ p.cargo("fetch").run();
+ p.cargo("fetch").run();
+
+ let lock = p.read_lockfile();
+ assert_match_exact(&lockfile, &lock);
+}
+
+#[cargo_test]
+fn v3_and_git() {
+ let (git_project, repo) = git::new_repo("dep1", |project| {
+ project
+ .file("Cargo.toml", &basic_lib_manifest("dep1"))
+ .file("src/lib.rs", "")
+ });
+ let head_id = repo.head().unwrap().target().unwrap();
+
+ let lockfile = format!(
+ r#"# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "dep1"
+version = "0.5.0"
+source = "git+{}?branch=master#{}"
+
+[[package]]
+name = "foo"
+version = "0.0.1"
+dependencies = [
+ "dep1",
+]
+"#,
+ git_project.url(),
+ head_id,
+ );
+
+ let p = project()
+ .file(
+ "Cargo.toml",
+ &format!(
+ r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ dep1 = {{ git = '{}', branch = 'master' }}
+ "#,
+ git_project.url(),
+ ),
+ )
+ .file("src/lib.rs", "")
+ .file("Cargo.lock", "version = 3")
+ .build();
+
+ p.cargo("fetch").run();
+
+ let lock = p.read_lockfile();
+ assert_match_exact(&lockfile, &lock);
+}
+
+#[cargo_test]
+fn lock_from_the_future() {
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .file("Cargo.lock", "version = 10000000")
+ .build();
+
+ p.cargo("fetch")
+ .with_stderr(
+ "\
+error: failed to parse lock file at: [..]
+
+Caused by:
+ lock file version `10000000` was found, but this version of Cargo does not \
+ understand this lock file, perhaps Cargo needs to be updated?
+",
+ )
+ .with_status(101)
+ .run();
+}
+
+#[cargo_test]
+fn preserve_old_format_if_no_update_needed() {
+ let cksum = Package::new("bar", "0.1.0").publish();
+ let lockfile = format!(
+ r#"# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "bar"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "foo"
+version = "0.0.1"
+dependencies = [
+ "bar 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[metadata]
+"checksum bar 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "{}"
+"#,
+ cksum
+ );
+
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ bar = "0.1.0"
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .file("Cargo.lock", &lockfile)
+ .build();
+
+ p.cargo("check --locked").run();
+}
+
+#[cargo_test]
+fn same_name_version_different_sources() {
+ let cksum = Package::new("foo", "0.1.0").publish();
+ let (git_project, repo) = git::new_repo("dep1", |project| {
+ project
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ "#,
+ )
+ .file("src/lib.rs", "")
+ });
+ let head_id = repo.head().unwrap().target().unwrap();
+
+ // Lockfile was generated with Rust 1.51
+ let lockfile = format!(
+ r#"# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "foo"
+version = "0.1.0"
+dependencies = [
+ "foo 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "foo 0.1.0 (git+{url})",
+]
+
+[[package]]
+name = "foo"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "{cksum}"
+
+[[package]]
+name = "foo"
+version = "0.1.0"
+source = "git+{url}#{sha}"
+"#,
+ sha = head_id,
+ url = git_project.url(),
+ cksum = cksum
+ );
+
+ let p = project()
+ .file(
+ "Cargo.toml",
+ &format!(
+ r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+
+ [dependencies]
+ foo = "0.1.0"
+ foo2 = {{ git = '{}', package = 'foo' }}
+ "#,
+ git_project.url(),
+ ),
+ )
+ .file("src/lib.rs", "")
+ .file("Cargo.lock", &lockfile)
+ .build();
+
+ p.cargo("check").run();
+
+ assert_eq!(p.read_file("Cargo.lock"), lockfile);
+}
+
+#[cargo_test]
+fn bad_data_in_lockfile_error_meg() {
+ Package::new("bar", "0.0.1").publish();
+
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "test"
+ version = "0.0.0"
+
+ [dependencies]
+ bar = "*"
+ "#,
+ )
+ .file("src/main.rs", "fn main() {}")
+ .file(
+ "Cargo.lock",
+ r#"# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "bar"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e1b9346248cf3391ead604c4407258d327c28e37209f6d56127598165165dda"
+
+[[package]]
+name = "test"
+version = "0.0.0"
+dependencies = [
+ "bar",
+]"#,
+ )
+ .build();
+ p.cargo("check")
+ .with_status(101)
+ .with_stderr(
+ "\
+[..]
+[ERROR] failed to select a version for the requirement `bar = \"*\"` (locked to 0.1.0)
+candidate versions found which didn't match: 0.0.1
+location searched: `dummy-registry` index (which is replacing registry `crates-io`)
+required by package `test v0.0.0 ([..])`
+perhaps a crate was updated and forgotten to be re-vendored?
+",
+ )
+ .run();
+}