diff options
Diffstat (limited to 'tests/testsuite/directory.rs')
-rw-r--r-- | tests/testsuite/directory.rs | 774 |
1 files changed, 774 insertions, 0 deletions
diff --git a/tests/testsuite/directory.rs b/tests/testsuite/directory.rs new file mode 100644 index 0000000..0e28de0 --- /dev/null +++ b/tests/testsuite/directory.rs @@ -0,0 +1,774 @@ +//! Tests for directory sources. + +use std::collections::HashMap; +use std::fs; +use std::str; + +use serde::Serialize; + +use cargo_test_support::cargo_process; +use cargo_test_support::git; +use cargo_test_support::paths; +use cargo_test_support::registry::{cksum, Package}; +use cargo_test_support::{basic_manifest, project, t, ProjectBuilder}; + +fn setup() { + let root = paths::root(); + t!(fs::create_dir(&root.join(".cargo"))); + t!(fs::write( + root.join(".cargo/config"), + r#" + [source.crates-io] + replace-with = 'my-awesome-local-registry' + + [source.my-awesome-local-registry] + directory = 'index' + "# + )); +} + +struct VendorPackage { + p: Option<ProjectBuilder>, + cksum: Checksum, +} + +#[derive(Serialize)] +struct Checksum { + package: Option<String>, + files: HashMap<String, String>, +} + +impl VendorPackage { + fn new(name: &str) -> VendorPackage { + VendorPackage { + p: Some(project().at(&format!("index/{}", name))), + cksum: Checksum { + package: Some(String::new()), + files: HashMap::new(), + }, + } + } + + fn file(&mut self, name: &str, contents: &str) -> &mut VendorPackage { + self.p = Some(self.p.take().unwrap().file(name, contents)); + self.cksum + .files + .insert(name.to_string(), cksum(contents.as_bytes())); + self + } + + fn disable_checksum(&mut self) -> &mut VendorPackage { + self.cksum.package = None; + self + } + + fn no_manifest(mut self) -> Self { + self.p = self.p.map(|pb| pb.no_manifest()); + self + } + + fn build(&mut self) { + let p = self.p.take().unwrap(); + let json = serde_json::to_string(&self.cksum).unwrap(); + let p = p.file(".cargo-checksum.json", &json); + let _ = p.build(); + } +} + +#[cargo_test] +fn simple() { + setup(); + + VendorPackage::new("bar") + .file("Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("src/lib.rs", "pub fn bar() {}") + .build(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + authors = [] + + [dependencies] + bar = "0.1.0" + "#, + ) + .file( + "src/lib.rs", + "extern crate bar; pub fn foo() { bar::bar(); }", + ) + .build(); + + p.cargo("check") + .with_stderr( + "\ +[CHECKING] bar v0.1.0 +[CHECKING] foo v0.1.0 ([CWD]) +[FINISHED] [..] +", + ) + .run(); +} + +#[cargo_test] +fn simple_install() { + setup(); + + VendorPackage::new("foo") + .file("src/lib.rs", "pub fn foo() {}") + .build(); + + VendorPackage::new("bar") + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + authors = [] + + [dependencies] + foo = "0.0.1" + "#, + ) + .file( + "src/main.rs", + "extern crate foo; pub fn main() { foo::foo(); }", + ) + .build(); + + cargo_process("install bar") + .with_stderr( + "\ +[INSTALLING] bar v0.1.0 +[COMPILING] foo v0.0.1 +[COMPILING] bar v0.1.0 +[FINISHED] release [optimized] target(s) in [..]s +[INSTALLING] [..]bar[..] +[INSTALLED] package `bar v0.1.0` (executable `bar[EXE]`) +[WARNING] be sure to add `[..]` to your PATH to be able to run the installed binaries +", + ) + .run(); +} + +#[cargo_test] +fn simple_install_fail() { + setup(); + + VendorPackage::new("foo") + .file("src/lib.rs", "pub fn foo() {}") + .build(); + + VendorPackage::new("bar") + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + authors = [] + + [dependencies] + foo = "0.1.0" + baz = "9.8.7" + "#, + ) + .file( + "src/main.rs", + "extern crate foo; pub fn main() { foo::foo(); }", + ) + .build(); + + cargo_process("install bar") + .with_status(101) + .with_stderr( + " Installing bar v0.1.0 +error: failed to compile `bar v0.1.0`, intermediate artifacts can be found at `[..]` + +Caused by: + no matching package found + searched package name: `baz` + perhaps you meant: bar or foo + location searched: registry `crates-io` + required by package `bar v0.1.0` +", + ) + .run(); +} + +#[cargo_test] +fn install_without_feature_dep() { + setup(); + + VendorPackage::new("foo") + .file("src/lib.rs", "pub fn foo() {}") + .build(); + + VendorPackage::new("bar") + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + authors = [] + + [dependencies] + foo = "0.0.1" + baz = { version = "9.8.7", optional = true } + + [features] + wantbaz = ["baz"] + "#, + ) + .file( + "src/main.rs", + "extern crate foo; pub fn main() { foo::foo(); }", + ) + .build(); + + cargo_process("install bar") + .with_stderr( + "\ +[INSTALLING] bar v0.1.0 +[COMPILING] foo v0.0.1 +[COMPILING] bar v0.1.0 +[FINISHED] release [optimized] target(s) in [..]s +[INSTALLING] [..]bar[..] +[INSTALLED] package `bar v0.1.0` (executable `bar[EXE]`) +[WARNING] be sure to add `[..]` to your PATH to be able to run the installed binaries +", + ) + .run(); +} + +#[cargo_test] +fn not_there() { + setup(); + + let _ = project().at("index").build(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + authors = [] + + [dependencies] + bar = "0.1.0" + "#, + ) + .file( + "src/lib.rs", + "extern crate bar; pub fn foo() { bar::bar(); }", + ) + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr( + "\ +error: no matching package named `bar` found +location searched: [..] +required by package `foo v0.1.0 ([..])` +", + ) + .run(); +} + +#[cargo_test] +fn multiple() { + setup(); + + VendorPackage::new("bar-0.1.0") + .file("Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("src/lib.rs", "pub fn bar() {}") + .file(".cargo-checksum", "") + .build(); + + VendorPackage::new("bar-0.2.0") + .file("Cargo.toml", &basic_manifest("bar", "0.2.0")) + .file("src/lib.rs", "pub fn bar() {}") + .file(".cargo-checksum", "") + .build(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + authors = [] + + [dependencies] + bar = "0.1.0" + "#, + ) + .file( + "src/lib.rs", + "extern crate bar; pub fn foo() { bar::bar(); }", + ) + .build(); + + p.cargo("check") + .with_stderr( + "\ +[CHECKING] bar v0.1.0 +[CHECKING] foo v0.1.0 ([CWD]) +[FINISHED] [..] +", + ) + .run(); +} + +#[cargo_test] +fn crates_io_then_directory() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + authors = [] + + [dependencies] + bar = "0.1.0" + "#, + ) + .file( + "src/lib.rs", + "extern crate bar; pub fn foo() { bar::bar(); }", + ) + .build(); + + let cksum = Package::new("bar", "0.1.0") + .file("src/lib.rs", "pub fn bar() -> u32 { 0 }") + .publish(); + + p.cargo("check") + .with_stderr( + "\ +[UPDATING] `[..]` index +[DOWNLOADING] crates ... +[DOWNLOADED] bar v0.1.0 ([..]) +[CHECKING] bar v0.1.0 +[CHECKING] foo v0.1.0 ([CWD]) +[FINISHED] [..] +", + ) + .run(); + + setup(); + + let mut v = VendorPackage::new("bar"); + v.file("Cargo.toml", &basic_manifest("bar", "0.1.0")); + v.file("src/lib.rs", "pub fn bar() -> u32 { 1 }"); + v.cksum.package = Some(cksum); + v.build(); + + p.cargo("check") + .with_stderr( + "\ +[CHECKING] bar v0.1.0 +[CHECKING] foo v0.1.0 ([CWD]) +[FINISHED] [..] +", + ) + .run(); +} + +#[cargo_test] +fn crates_io_then_bad_checksum() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + authors = [] + + [dependencies] + bar = "0.1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + + Package::new("bar", "0.1.0").publish(); + + p.cargo("check").run(); + setup(); + + VendorPackage::new("bar") + .file("Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("src/lib.rs", "") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr( + "\ +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(); +} + +#[cargo_test] +fn bad_file_checksum() { + setup(); + + VendorPackage::new("bar") + .file("Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("src/lib.rs", "") + .build(); + + t!(fs::write( + paths::root().join("index/bar/src/lib.rs"), + "fn bar() -> u32 { 0 }" + )); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + authors = [] + + [dependencies] + bar = "0.1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr( + "\ +error: the listed checksum of `[..]lib.rs` has changed: +expected: [..] +actual: [..] + +directory sources are not intended to be edited, if modifications are \ +required then it is recommended that `[patch]` is used with a forked copy of \ +the source +", + ) + .run(); +} + +#[cargo_test] +fn only_dot_files_ok() { + setup(); + + VendorPackage::new("bar") + .file("Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("src/lib.rs", "") + .build(); + VendorPackage::new("foo") + .no_manifest() + .file(".bar", "") + .build(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + authors = [] + + [dependencies] + bar = "0.1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check").run(); +} + +#[cargo_test] +fn random_files_ok() { + setup(); + + VendorPackage::new("bar") + .file("Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("src/lib.rs", "") + .build(); + VendorPackage::new("foo") + .no_manifest() + .file("bar", "") + .file("../test", "") + .build(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + authors = [] + + [dependencies] + bar = "0.1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check").run(); +} + +#[cargo_test] +fn git_lock_file_doesnt_change() { + let git = git::new("git", |p| { + p.file("Cargo.toml", &basic_manifest("git", "0.5.0")) + .file("src/lib.rs", "") + }); + + VendorPackage::new("git") + .file("Cargo.toml", &basic_manifest("git", "0.5.0")) + .file("src/lib.rs", "") + .disable_checksum() + .build(); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.0.1" + authors = [] + + [dependencies] + git = {{ git = '{0}' }} + "#, + git.url() + ), + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check").run(); + + let lock1 = p.read_lockfile(); + + let root = paths::root(); + t!(fs::create_dir(&root.join(".cargo"))); + t!(fs::write( + root.join(".cargo/config"), + format!( + r#" + [source.my-git-repo] + git = '{}' + replace-with = 'my-awesome-local-registry' + + [source.my-awesome-local-registry] + directory = 'index' + "#, + git.url() + ) + )); + + p.cargo("check") + .with_stderr( + "\ +[CHECKING] [..] +[CHECKING] [..] +[FINISHED] [..] +", + ) + .run(); + + let lock2 = p.read_lockfile(); + assert_eq!(lock1, lock2, "lock files changed"); +} + +#[cargo_test] +fn git_override_requires_lockfile() { + VendorPackage::new("git") + .file("Cargo.toml", &basic_manifest("git", "0.5.0")) + .file("src/lib.rs", "") + .disable_checksum() + .build(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + authors = [] + + [dependencies] + git = { git = 'https://example.com/' } + "#, + ) + .file("src/lib.rs", "") + .build(); + + let root = paths::root(); + t!(fs::create_dir(&root.join(".cargo"))); + t!(fs::write( + root.join(".cargo/config"), + r#" + [source.my-git-repo] + git = 'https://example.com/' + replace-with = 'my-awesome-local-registry' + + [source.my-awesome-local-registry] + directory = 'index' + "# + )); + + p.cargo("check") + .with_status(101) + .with_stderr( + "\ +[ERROR] failed to get `git` as a dependency of package `foo v0.0.1 ([..])` + +Caused by: + failed to load source for dependency `git` + +Caused by: + Unable to update [..] + +Caused by: + the source my-git-repo requires a lock file to be present first before it can be + used against vendored source code + + remove the source replacement configuration, generate a lock file, and then + restore the source replacement configuration to continue the build +", + ) + .run(); +} + +#[cargo_test] +fn workspace_different_locations() { + let p = project() + .no_manifest() + .file( + "foo/Cargo.toml", + r#" + [package] + name = 'foo' + version = '0.1.0' + + [dependencies] + baz = "*" + "#, + ) + .file("foo/src/lib.rs", "") + .file("foo/vendor/baz/Cargo.toml", &basic_manifest("baz", "0.1.0")) + .file("foo/vendor/baz/src/lib.rs", "") + .file("foo/vendor/baz/.cargo-checksum.json", "{\"files\":{}}") + .file( + "bar/Cargo.toml", + r#" + [package] + name = 'bar' + version = '0.1.0' + + [dependencies] + baz = "*" + "#, + ) + .file("bar/src/lib.rs", "") + .file( + ".cargo/config", + r#" + [build] + target-dir = './target' + + [source.crates-io] + replace-with = 'my-awesome-local-registry' + + [source.my-awesome-local-registry] + directory = 'foo/vendor' + "#, + ) + .build(); + + p.cargo("check").cwd("foo").run(); + p.cargo("check") + .cwd("bar") + .with_stderr( + "\ +[CHECKING] bar [..] +[FINISHED] [..] +", + ) + .run(); +} + +#[cargo_test] +fn version_missing() { + setup(); + + VendorPackage::new("foo") + .file("src/lib.rs", "pub fn foo() {}") + .build(); + + VendorPackage::new("bar") + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + authors = [] + + [dependencies] + foo = "2" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + cargo_process("install bar") + .with_stderr( + "\ +[INSTALLING] bar v0.1.0 +error: failed to compile [..] + +Caused by: + failed to select a version for the requirement `foo = \"^2\"` + candidate versions found which didn't match: 0.0.1 + location searched: directory source `[..] (which is replacing registry `[..]`) + required by package `bar v0.1.0` + perhaps a crate was updated and forgotten to be re-vendored? +", + ) + .with_status(101) + .run(); +} |