[dev-dependencies]
bufstream = "0.1"
-cargotest = { path = "tests/cargotest", version = "0.1" }
+cargotest = { path = "tests/testsuite/cargotest", version = "0.1" }
filetime = "0.1"
hamcrest = "=0.1.1"
name = "cargo"
test = false
doc = false
+
+[[test]]
+name = "testsuite"
+path = "tests/testsuite/lib.rs"
\ No newline at end of file
+++ /dev/null
-extern crate cargotest;
-extern crate hamcrest;
-
-use cargotest::ChannelChanger;
-use cargotest::support::registry::{self, Package, alt_api_path};
-use cargotest::support::{paths, project, execs};
-use hamcrest::assert_that;
-use std::fs::File;
-use std::io::Write;
-
-#[test]
-fn is_feature_gated() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies.bar]
- version = "0.0.1"
- registry = "alternative"
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- Package::new("bar", "0.0.1").alternative(true).publish();
-
- assert_that(p.cargo("build").masquerade_as_nightly_cargo(),
- execs().with_status(101)
- .with_stderr_contains(" feature `alternative-registries` is required"));
-}
-
-#[test]
-fn depend_on_alt_registry() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- cargo-features = ["alternative-registries"]
-
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies.bar]
- version = "0.0.1"
- registry = "alternative"
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- Package::new("bar", "0.0.1").alternative(true).publish();
-
- assert_that(p.cargo("build").masquerade_as_nightly_cargo(),
- execs().with_status(0).with_stderr(&format!("\
-[UPDATING] registry `{reg}`
-[DOWNLOADING] bar v0.0.1 (registry `file://[..]`)
-[COMPILING] bar v0.0.1 (registry `file://[..]`)
-[COMPILING] foo v0.0.1 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] secs
-",
- dir = p.url(),
- reg = registry::alt_registry())));
-
- assert_that(p.cargo("clean").masquerade_as_nightly_cargo(), execs().with_status(0));
-
- // Don't download a second time
- assert_that(p.cargo("build").masquerade_as_nightly_cargo(),
- execs().with_status(0).with_stderr(&format!("\
-[COMPILING] bar v0.0.1 (registry `file://[..]`)
-[COMPILING] foo v0.0.1 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] secs
-",
- dir = p.url())));
-}
-
-#[test]
-fn depend_on_alt_registry_depends_on_same_registry_no_index() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- cargo-features = ["alternative-registries"]
-
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies.bar]
- version = "0.0.1"
- registry = "alternative"
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- Package::new("baz", "0.0.1").alternative(true).publish();
- Package::new("bar", "0.0.1").dep("baz", "0.0.1").alternative(true).publish();
-
- assert_that(p.cargo("build").masquerade_as_nightly_cargo(),
- execs().with_status(0).with_stderr(&format!("\
-[UPDATING] registry `{reg}`
-[DOWNLOADING] [..] v0.0.1 (registry `file://[..]`)
-[DOWNLOADING] [..] v0.0.1 (registry `file://[..]`)
-[COMPILING] baz v0.0.1 (registry `file://[..]`)
-[COMPILING] bar v0.0.1 (registry `file://[..]`)
-[COMPILING] foo v0.0.1 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] secs
-",
- dir = p.url(),
- reg = registry::alt_registry())));
-}
-
-#[test]
-fn depend_on_alt_registry_depends_on_same_registry() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- cargo-features = ["alternative-registries"]
-
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies.bar]
- version = "0.0.1"
- registry = "alternative"
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- Package::new("baz", "0.0.1").alternative(true).publish();
- Package::new("bar", "0.0.1").registry_dep("baz", "0.0.1", registry::alt_registry().as_str()).alternative(true).publish();
-
- assert_that(p.cargo("build").masquerade_as_nightly_cargo(),
- execs().with_status(0).with_stderr(&format!("\
-[UPDATING] registry `{reg}`
-[DOWNLOADING] [..] v0.0.1 (registry `file://[..]`)
-[DOWNLOADING] [..] v0.0.1 (registry `file://[..]`)
-[COMPILING] baz v0.0.1 (registry `file://[..]`)
-[COMPILING] bar v0.0.1 (registry `file://[..]`)
-[COMPILING] foo v0.0.1 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] secs
-",
- dir = p.url(),
- reg = registry::alt_registry())));
-}
-
-#[test]
-fn depend_on_alt_registry_depends_on_crates_io() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- cargo-features = ["alternative-registries"]
-
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies.bar]
- version = "0.0.1"
- registry = "alternative"
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- Package::new("baz", "0.0.1").publish();
- Package::new("bar", "0.0.1").registry_dep("baz", "0.0.1", registry::registry().as_str()).alternative(true).publish();
-
- assert_that(p.cargo("build").masquerade_as_nightly_cargo(),
- execs().with_status(0).with_stderr(&format!("\
-[UPDATING] registry `{alt_reg}`
-[UPDATING] registry `{reg}`
-[DOWNLOADING] [..] v0.0.1 (registry `file://[..]`)
-[DOWNLOADING] [..] v0.0.1 (registry `file://[..]`)
-[COMPILING] baz v0.0.1 (registry `file://[..]`)
-[COMPILING] bar v0.0.1 (registry `file://[..]`)
-[COMPILING] foo v0.0.1 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] secs
-",
- dir = p.url(),
- alt_reg = registry::alt_registry(),
- reg = registry::registry())));
-}
-
-#[test]
-fn registry_and_path_dep_works() {
- registry::init();
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- cargo-features = ["alternative-registries"]
-
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies.bar]
- path = "bar"
- registry = "alternative"
- "#)
- .file("src/main.rs", "fn main() {}")
- .file("bar/Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.0.1"
- authors = []
- "#)
- .file("bar/src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build").masquerade_as_nightly_cargo(),
- execs().with_status(0)
- .with_stderr(&format!("\
-[COMPILING] bar v0.0.1 ({dir}/bar)
-[COMPILING] foo v0.0.1 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] secs
-",
- dir = p.url())));
-}
-
-#[test]
-fn registry_incompatible_with_git() {
- registry::init();
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- cargo-features = ["alternative-registries"]
-
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies.bar]
- git = ""
- registry = "alternative"
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("build").masquerade_as_nightly_cargo(),
- execs().with_status(101)
- .with_stderr_contains(" dependency (bar) specification is ambiguous. Only one of `git` or `registry` is allowed."));
-}
-
-#[test]
-fn cannot_publish_to_crates_io_with_registry_dependency() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- cargo-features = ["alternative-registries"]
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- [dependencies.bar]
- version = "0.0.1"
- registry = "alternative"
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- Package::new("bar", "0.0.1").alternative(true).publish();
-
- assert_that(p.cargo("publish").masquerade_as_nightly_cargo()
- .arg("--index").arg(registry::registry().to_string()),
- execs().with_status(101));
-}
-
-#[test]
-fn publish_with_registry_dependency() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- cargo-features = ["alternative-registries"]
-
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies.bar]
- version = "0.0.1"
- registry = "alternative"
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- Package::new("bar", "0.0.1").alternative(true).publish();
-
- // Login so that we have the token available
- assert_that(p.cargo("login").masquerade_as_nightly_cargo()
- .arg("--registry").arg("alternative").arg("TOKEN").arg("-Zunstable-options"),
- execs().with_status(0));
-
- assert_that(p.cargo("publish").masquerade_as_nightly_cargo()
- .arg("--registry").arg("alternative").arg("-Zunstable-options"),
- execs().with_status(0));
-}
-
-#[test]
-fn alt_registry_and_crates_io_deps() {
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- cargo-features = ["alternative-registries"]
-
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- crates_io_dep = "0.0.1"
-
- [dependencies.alt_reg_dep]
- version = "0.1.0"
- registry = "alternative"
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- Package::new("crates_io_dep", "0.0.1").publish();
- Package::new("alt_reg_dep", "0.1.0").alternative(true).publish();
-
- assert_that(p.cargo("build").masquerade_as_nightly_cargo(),
- execs().with_status(0)
- .with_stderr_contains(format!("\
-[UPDATING] registry `{}`", registry::alt_registry()))
- .with_stderr_contains(&format!("\
-[UPDATING] registry `{}`", registry::registry()))
- .with_stderr_contains("\
-[DOWNLOADING] crates_io_dep v0.0.1 (registry `file://[..]`)")
- .with_stderr_contains("\
-[DOWNLOADING] alt_reg_dep v0.1.0 (registry `file://[..]`)")
- .with_stderr_contains("\
-[COMPILING] alt_reg_dep v0.1.0 (registry `file://[..]`)")
- .with_stderr_contains("\
-[COMPILING] crates_io_dep v0.0.1")
- .with_stderr_contains(&format!("\
-[COMPILING] foo v0.0.1 ({})", p.url()))
- .with_stderr_contains("\
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] secs"))
-
-}
-
-#[test]
-fn block_publish_due_to_no_token() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- // Setup the registry by publishing a package
- Package::new("bar", "0.0.1").alternative(true).publish();
-
- // Now perform the actual publish
- assert_that(p.cargo("publish").masquerade_as_nightly_cargo()
- .arg("--registry").arg("alternative").arg("-Zunstable-options"),
- execs().with_status(101)
- .with_stderr_contains("error: no upload token found, please run `cargo login`"));
-}
-
-#[test]
-fn publish_to_alt_registry() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- cargo-features = ["alternative-registries"]
-
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- // Setup the registry by publishing a package
- Package::new("bar", "0.0.1").alternative(true).publish();
-
- // Login so that we have the token available
- assert_that(p.cargo("login").masquerade_as_nightly_cargo()
- .arg("--registry").arg("alternative").arg("TOKEN").arg("-Zunstable-options"),
- execs().with_status(0));
-
- // Now perform the actual publish
- assert_that(p.cargo("publish").masquerade_as_nightly_cargo()
- .arg("--registry").arg("alternative").arg("-Zunstable-options"),
- execs().with_status(0));
-
- // Ensure that the crate is uploaded
- assert!(alt_api_path().join("api/v1/crates/new").exists());
-}
-
-#[test]
-fn publish_with_crates_io_dep() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- cargo-features = ["alternative-registries"]
-
- [project]
- name = "foo"
- version = "0.0.1"
- authors = ["me"]
- license = "MIT"
- description = "foo"
-
- [dependencies.bar]
- version = "0.0.1"
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- Package::new("bar", "0.0.1").publish();
-
- // Login so that we have the token available
- assert_that(p.cargo("login").masquerade_as_nightly_cargo()
- .arg("--registry").arg("alternative").arg("TOKEN").arg("-Zunstable-options"),
- execs().with_status(0));
-
- assert_that(p.cargo("publish").masquerade_as_nightly_cargo()
- .arg("--registry").arg("alternative").arg("-Zunstable-options"),
- execs().with_status(0));
-}
-
-#[test]
-fn credentials_in_url_forbidden() {
- registry::init();
-
- let config = paths::home().join(".cargo/config");
-
- File::create(config)
- .unwrap()
- .write_all(br#"
- [registries.alternative]
- index = "ssh://git:secret@foobar.com"
- "#)
- .unwrap();
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- cargo-features = ["alternative-registries"]
-
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("publish").masquerade_as_nightly_cargo()
- .arg("--registry").arg("alternative").arg("-Zunstable-options"),
- execs().with_status(101)
- .with_stderr_contains("error: Registry URLs may not contain credentials"));
-}
+++ /dev/null
-extern crate cargotest;
-extern crate hamcrest;
-
-use cargotest::support::{project, execs};
-use cargotest::support::registry::Package;
-use hamcrest::assert_that;
-
-#[test]
-fn bad1() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.0"
- authors = []
- "#)
- .file("src/lib.rs", "")
- .file(".cargo/config", r#"
- [target]
- nonexistent-target = "foo"
- "#)
- .build();
- assert_that(p.cargo("build").arg("-v")
- .arg("--target=nonexistent-target"),
- execs().with_status(101).with_stderr("\
-[ERROR] expected table for configuration key `target.nonexistent-target`, \
-but found string in [..]config
-"));
-}
-
-#[test]
-fn bad2() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.0"
- authors = []
- "#)
- .file("src/lib.rs", "")
- .file(".cargo/config", r#"
- [http]
- proxy = 3.0
- "#)
- .build();
- assert_that(p.cargo("publish").arg("-v"),
- execs().with_status(101).with_stderr("\
-[ERROR] Couldn't load Cargo configuration
-
-Caused by:
- failed to load TOML configuration from `[..]config`
-
-Caused by:
- failed to parse key `http`
-
-Caused by:
- failed to parse key `proxy`
-
-Caused by:
- found TOML configuration value of unknown type `float`
-"));
-}
-
-#[test]
-fn bad3() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.0"
- authors = []
- "#)
- .file("src/lib.rs", "")
- .file(".cargo/config", r#"
- [http]
- proxy = true
- "#)
- .build();
- Package::new("foo", "1.0.0").publish();
-
- assert_that(p.cargo("publish").arg("-v"),
- execs().with_status(101).with_stderr("\
-error: failed to update registry [..]
-
-Caused by:
- invalid configuration for key `http.proxy`
-expected a string, but found a boolean for `http.proxy` in [..]config
-"));
-}
-
-#[test]
-fn bad4() {
- let p = project("foo")
- .file(".cargo/config", r#"
- [cargo-new]
- name = false
- "#)
- .build();
- assert_that(p.cargo("new").arg("-v").arg("foo"),
- execs().with_status(101).with_stderr("\
-[ERROR] Failed to create project `foo` at `[..]`
-
-Caused by:
- invalid configuration for key `cargo-new.name`
-expected a string, but found a boolean for `cargo-new.name` in [..]config
-"));
-}
-
-#[test]
-fn bad5() {
- let p = project("foo")
- .file(".cargo/config", r#"
- foo = ""
- "#)
- .file("foo/.cargo/config", r#"
- foo = 2
- "#)
- .build();
- assert_that(p.cargo("new")
- .arg("-v").arg("foo").cwd(&p.root().join("foo")),
- execs().with_status(101).with_stderr("\
-[ERROR] Failed to create project `foo` at `[..]`
-
-Caused by:
- Couldn't load Cargo configuration
-
-Caused by:
- failed to merge configuration at `[..]`
-
-Caused by:
- failed to merge key `foo` between files:
- file 1: [..]foo[..]foo[..]config
- file 2: [..]foo[..]config
-
-Caused by:
- expected integer, but found string
-"));
-}
-
-#[test]
-fn bad_cargo_config_jobs() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.0"
- authors = []
- "#)
- .file("src/lib.rs", "")
- .file(".cargo/config", r#"
- [build]
- jobs = -1
- "#)
- .build();
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(101).with_stderr("\
-[ERROR] build.jobs must be positive, but found -1 in [..]
-"));
-}
-
-#[test]
-fn default_cargo_config_jobs() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.0"
- authors = []
- "#)
- .file("src/lib.rs", "")
- .file(".cargo/config", r#"
- [build]
- jobs = 1
- "#)
- .build();
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(0));
-}
-
-#[test]
-fn good_cargo_config_jobs() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.0"
- authors = []
- "#)
- .file("src/lib.rs", "")
- .file(".cargo/config", r#"
- [build]
- jobs = 4
- "#)
- .build();
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(0));
-}
-
-#[test]
-fn invalid_global_config() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.0"
- authors = []
-
- [dependencies]
- foo = "0.1.0"
- "#)
- .file(".cargo/config", "4")
- .file("src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(101).with_stderr("\
-[ERROR] Couldn't load Cargo configuration
-
-Caused by:
- could not parse TOML configuration in `[..]`
-
-Caused by:
- could not parse input as TOML
-
-Caused by:
- expected an equals, found eof at line 1
-"));
-}
-
-#[test]
-fn bad_cargo_lock() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.0"
- authors = []
- "#)
- .file("Cargo.lock", "[[package]]\nfoo = 92")
- .file("src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(101).with_stderr("\
-[ERROR] failed to parse lock file at: [..]Cargo.lock
-
-Caused by:
- missing field `name` for key `package`
-"));
-}
-
-#[test]
-fn duplicate_packages_in_cargo_lock() {
- Package::new("foo", "0.1.0").publish();
-
- let p = project("bar")
- .file("Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- foo = "0.1.0"
- "#)
- .file("src/lib.rs", "")
- .file("Cargo.lock", r#"
- [[package]]
- name = "bar"
- version = "0.0.1"
- dependencies = [
- "foo 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
- ]
-
- [[package]]
- name = "foo"
- version = "0.1.0"
- source = "registry+https://github.com/rust-lang/crates.io-index"
-
- [[package]]
- name = "foo"
- version = "0.1.0"
- source = "registry+https://github.com/rust-lang/crates.io-index"
- "#)
- .build();
-
- assert_that(p.cargo("build").arg("--verbose"),
- execs().with_status(101).with_stderr("\
-[ERROR] failed to parse lock file at: [..]
-
-Caused by:
- package `foo` is specified twice in the lockfile
-"));
-}
-
-#[test]
-fn bad_source_in_cargo_lock() {
- Package::new("foo", "0.1.0").publish();
-
- let p = project("bar")
- .file("Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- foo = "0.1.0"
- "#)
- .file("src/lib.rs", "")
- .file("Cargo.lock", r#"
- [[package]]
- name = "bar"
- version = "0.0.1"
- dependencies = [
- "foo 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
- ]
-
- [[package]]
- name = "foo"
- version = "0.1.0"
- source = "You shall not parse"
- "#)
- .build();
-
- assert_that(p.cargo("build").arg("--verbose"),
- execs().with_status(101).with_stderr("\
-[ERROR] failed to parse lock file at: [..]
-
-Caused by:
- invalid source `You shall not parse` for key `package.source`
-"));
-}
-
-#[test]
-fn bad_dependency_in_lockfile() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .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)",
- ]
- "#)
- .build();
-
- assert_that(p.cargo("build").arg("--verbose"),
- execs().with_status(101).with_stderr("\
-[ERROR] failed to parse lock file at: [..]
-
-Caused by:
- package `bar 0.1.0 ([..])` is specified as a dependency, but is missing from the package list
-"));
-
-}
-
-#[test]
-fn bad_git_dependency() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.0"
- authors = []
-
- [dependencies]
- foo = { git = "file:.." }
- "#)
- .file("src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(101).with_stderr("\
-[UPDATING] git repository `file:///`
-[ERROR] failed to load source for a dependency on `foo`
-
-Caused by:
- Unable to update file:///
-
-Caused by:
- failed to clone into: [..]
-
-Caused by:
- [..]'file:///' is not a valid local file URI[..]
-"));
-}
-
-#[test]
-fn bad_crate_type() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.0"
- authors = []
-
- [lib]
- crate-type = ["bad_type", "rlib"]
- "#)
- .file("src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(101).with_stderr_contains("\
-error: failed to run `rustc` to learn about target-specific information
-"));
-}
-
-#[test]
-fn malformed_override() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.0"
- authors = []
-
- [target.x86_64-apple-darwin.freetype]
- native = {
- foo: "bar"
- }
- "#)
- .file("src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(101).with_stderr("\
-[ERROR] failed to parse manifest at `[..]`
-
-Caused by:
- could not parse input as TOML
-
-Caused by:
- expected a table key, found a newline at line 8
-"));
-}
-
-#[test]
-fn duplicate_binary_names() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "qqq"
- version = "0.1.0"
- authors = ["A <a@a.a>"]
-
- [[bin]]
- name = "e"
- path = "a.rs"
-
- [[bin]]
- name = "e"
- path = "b.rs"
- "#)
- .file("a.rs", r#"fn main() -> () {}"#)
- .file("b.rs", r#"fn main() -> () {}"#)
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(101).with_stderr("\
-[ERROR] failed to parse manifest at `[..]`
-
-Caused by:
- found duplicate binary name e, but all binary targets must have a unique name
-"));
-}
-
-#[test]
-fn duplicate_example_names() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "qqq"
- version = "0.1.0"
- authors = ["A <a@a.a>"]
-
- [[example]]
- name = "ex"
- path = "examples/ex.rs"
-
- [[example]]
- name = "ex"
- path = "examples/ex2.rs"
- "#)
- .file("examples/ex.rs", r#"fn main () -> () {}"#)
- .file("examples/ex2.rs", r#"fn main () -> () {}"#)
- .build();
-
- assert_that(p.cargo("build").arg("--example").arg("ex"),
- execs().with_status(101).with_stderr("\
-[ERROR] failed to parse manifest at `[..]`
-
-Caused by:
- found duplicate example name ex, but all example targets must have a unique name
-"));
-}
-
-#[test]
-fn duplicate_bench_names() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "qqq"
- version = "0.1.0"
- authors = ["A <a@a.a>"]
-
- [[bench]]
- name = "ex"
- path = "benches/ex.rs"
-
- [[bench]]
- name = "ex"
- path = "benches/ex2.rs"
- "#)
- .file("benches/ex.rs", r#"fn main () {}"#)
- .file("benches/ex2.rs", r#"fn main () {}"#)
- .build();
-
- assert_that(p.cargo("bench"),
- execs().with_status(101).with_stderr("\
-[ERROR] failed to parse manifest at `[..]`
-
-Caused by:
- found duplicate bench name ex, but all bench targets must have a unique name
-"));
-}
-
-#[test]
-fn duplicate_deps() {
- let p = project("foo")
- .file("shim-bar/Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
- "#)
- .file("shim-bar/src/lib.rs", r#"
- pub fn a() {}
- "#)
- .file("linux-bar/Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
- "#)
- .file("linux-bar/src/lib.rs", r#"
- pub fn a() {}
- "#)
- .file("Cargo.toml", r#"
- [package]
- name = "qqq"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- bar = { path = "shim-bar" }
-
- [target.x86_64-unknown-linux-gnu.dependencies]
- bar = { path = "linux-bar" }
- "#)
- .file("src/main.rs", r#"fn main () {}"#)
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(101).with_stderr("\
-[ERROR] failed to parse manifest at `[..]`
-
-Caused by:
- Dependency 'bar' has different source paths depending on the build target. Each dependency must \
-have a single canonical source path irrespective of build target.
-"));
-}
-
-#[test]
-fn duplicate_deps_diff_sources() {
- let p = project("foo")
- .file("shim-bar/Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
- "#)
- .file("shim-bar/src/lib.rs", r#"
- pub fn a() {}
- "#)
- .file("linux-bar/Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
- "#)
- .file("linux-bar/src/lib.rs", r#"
- pub fn a() {}
- "#)
- .file("Cargo.toml", r#"
- [package]
- name = "qqq"
- version = "0.0.1"
- authors = []
-
- [target.i686-unknown-linux-gnu.dependencies]
- bar = { path = "shim-bar" }
-
- [target.x86_64-unknown-linux-gnu.dependencies]
- bar = { path = "linux-bar" }
- "#)
- .file("src/main.rs", r#"fn main () {}"#)
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(101).with_stderr("\
-[ERROR] failed to parse manifest at `[..]`
-
-Caused by:
- Dependency 'bar' has different source paths depending on the build target. Each dependency must \
-have a single canonical source path irrespective of build target.
-"));
-}
-
-#[test]
-fn unused_keys() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
-
- [target.foo]
- bar = "3"
- "#)
- .file("src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr("\
-warning: unused manifest key: target.foo.bar
-[COMPILING] foo v0.1.0 (file:///[..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
-
- name = "foo"
- version = "0.5.0"
- authors = ["wycats@example.com"]
- bulid = "foo"
- "#)
- .file("src/lib.rs", r#"
- pub fn foo() {}
- "#)
- .build();
- assert_that(p.cargo("build"),
- execs().with_status(0)
- .with_stderr("\
-warning: unused manifest key: project.bulid
-[COMPILING] foo [..]
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-
- let p = project("bar")
- .file("Cargo.toml", r#"
- [project]
-
- name = "foo"
- version = "0.5.0"
- authors = ["wycats@example.com"]
-
- [lib]
- build = "foo"
- "#)
- .file("src/lib.rs", r#"
- pub fn foo() {}
- "#)
- .build();
- assert_that(p.cargo("build"),
- execs().with_status(0)
- .with_stderr("\
-warning: unused manifest key: lib.build
-[COMPILING] foo [..]
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-}
-
-
-#[test]
-fn empty_dependencies() {
- let p = project("empty_deps")
- .file("Cargo.toml", r#"
- [package]
- name = "empty_deps"
- version = "0.0.0"
- authors = []
-
- [dependencies]
- foo = {}
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- Package::new("foo", "0.0.1").publish();
-
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr_contains("\
-warning: dependency (foo) specified without providing a local path, Git repository, or version \
-to use. This will be considered an error in future versions
-"));
-}
-
-#[test]
-fn invalid_toml_historically_allowed_is_warned() {
- let p = project("empty_deps")
- .file("Cargo.toml", r#"
- [package]
- name = "empty_deps"
- version = "0.0.0"
- authors = []
- "#)
- .file(".cargo/config", r#"
- [foo] bar = 2
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr("\
-warning: TOML file found which contains invalid syntax and will soon not parse
-at `[..]config`.
-
-The TOML spec requires newlines after table definitions (e.g. `[a] b = 1` is
-invalid), but this file has a table header which does not have a newline after
-it. A newline needs to be added and this warning will soon become a hard error
-in the future.
-[COMPILING] empty_deps v0.0.0 ([..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-}
-
-#[test]
-fn ambiguous_git_reference() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.0"
- authors = []
-
- [dependencies.bar]
- git = "https://127.0.0.1"
- branch = "master"
- tag = "some-tag"
- "#)
- .file("src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build").arg("-v"),
- execs().with_stderr_contains("\
-[WARNING] dependency (bar) specification is ambiguous. \
-Only one of `branch`, `tag` or `rev` is allowed. \
-This will be considered an error in future versions
-"));
-}
-
-#[test]
-fn bad_source_config1() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.0"
- authors = []
- "#)
- .file("src/lib.rs", "")
- .file(".cargo/config", r#"
- [source.foo]
- "#)
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(101).with_stderr("\
-error: no source URL specified for `source.foo`, need [..]
-"));
-}
-
-#[test]
-fn bad_source_config2() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.0"
- authors = []
-
- [dependencies]
- bar = "*"
- "#)
- .file("src/lib.rs", "")
- .file(".cargo/config", r#"
- [source.crates-io]
- registry = 'http://example.com'
- replace-with = 'bar'
- "#)
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(101).with_stderr("\
-error: failed to load source for a dependency on `bar`
-
-Caused by:
- Unable to update registry `https://[..]`
-
-Caused by:
- could not find a configured source with the name `bar` \
- when attempting to lookup `crates-io` (configuration in [..])
-"));
-}
-
-#[test]
-fn bad_source_config3() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.0"
- authors = []
-
- [dependencies]
- bar = "*"
- "#)
- .file("src/lib.rs", "")
- .file(".cargo/config", r#"
- [source.crates-io]
- registry = 'http://example.com'
- replace-with = 'crates-io'
- "#)
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(101).with_stderr("\
-error: failed to load source for a dependency on `bar`
-
-Caused by:
- Unable to update registry `https://[..]`
-
-Caused by:
- detected a cycle of `replace-with` sources, [..]
-"));
-}
-
-#[test]
-fn bad_source_config4() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.0"
- authors = []
-
- [dependencies]
- bar = "*"
- "#)
- .file("src/lib.rs", "")
- .file(".cargo/config", r#"
- [source.crates-io]
- registry = 'http://example.com'
- replace-with = 'bar'
-
- [source.bar]
- registry = 'http://example.com'
- replace-with = 'crates-io'
- "#)
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(101).with_stderr("\
-error: failed to load source for a dependency on `bar`
-
-Caused by:
- Unable to update registry `https://[..]`
-
-Caused by:
- detected a cycle of `replace-with` sources, the source `crates-io` is \
- eventually replaced with itself (configuration in [..])
-"));
-}
-
-#[test]
-fn bad_source_config5() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.0"
- authors = []
-
- [dependencies]
- bar = "*"
- "#)
- .file("src/lib.rs", "")
- .file(".cargo/config", r#"
- [source.crates-io]
- registry = 'http://example.com'
- replace-with = 'bar'
-
- [source.bar]
- registry = 'not a url'
- "#)
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(101).with_stderr("\
-error: configuration key `source.bar.registry` specified an invalid URL (in [..])
-
-Caused by:
- invalid url `not a url`: [..]
-"));
-}
-
-#[test]
-fn both_git_and_path_specified() {
- let foo = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.0"
- authors = []
-
- [dependencies.bar]
- git = "https://127.0.0.1"
- path = "bar"
- "#)
- .file("src/lib.rs", "")
- .build();
-
- assert_that(foo.cargo("build").arg("-v"),
- execs().with_stderr_contains("\
-[WARNING] dependency (bar) specification is ambiguous. \
-Only one of `git` or `path` is allowed. \
-This will be considered an error in future versions
-"));
-}
-
-#[test]
-fn bad_source_config6() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.0"
- authors = []
-
- [dependencies]
- bar = "*"
- "#)
- .file("src/lib.rs", "")
- .file(".cargo/config", r#"
- [source.crates-io]
- registry = 'http://example.com'
- replace-with = ['not', 'a', 'string']
- "#)
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(101).with_stderr("\
-error: expected a string, but found a array for `source.crates-io.replace-with` in [..]
-"));
-}
-
-#[test]
-fn ignored_git_revision() {
- let foo = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.0"
- authors = []
-
- [dependencies.bar]
- path = "bar"
- branch = "spam"
- "#)
- .file("src/lib.rs", "")
- .build();
-
- assert_that(foo.cargo("build").arg("-v"),
- execs().with_stderr_contains("\
-[WARNING] key `branch` is ignored for dependency (bar). \
-This will be considered an error in future versions"));
-}
-
-#[test]
-fn bad_source_config7() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.0"
- authors = []
-
- [dependencies]
- bar = "*"
- "#)
- .file("src/lib.rs", "")
- .file(".cargo/config", r#"
- [source.foo]
- registry = 'http://example.com'
- local-registry = 'file:///another/file'
- "#)
- .build();
-
- Package::new("bar", "0.1.0").publish();
-
- assert_that(p.cargo("build"),
- execs().with_status(101).with_stderr("\
-error: more than one source URL specified for `source.foo`
-"));
-}
-
-#[test]
-fn bad_dependency() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.0"
- authors = []
-
- [dependencies]
- bar = 3
- "#)
- .file("src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(101).with_stderr("\
-error: failed to parse manifest at `[..]`
-
-Caused by:
- invalid type: integer `3`, expected a version string like [..]
-"));
-}
-
-#[test]
-fn bad_debuginfo() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.0"
- authors = []
-
- [profile.dev]
- debug = 'a'
- "#)
- .file("src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(101).with_stderr("\
-error: failed to parse manifest at `[..]`
-
-Caused by:
- invalid type: string \"a\", expected a boolean or an integer for [..]
-"));
-}
-
-#[test]
-fn bad_opt_level() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.0"
- authors = []
- build = 3
- "#)
- .file("src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(101).with_stderr("\
-error: failed to parse manifest at `[..]`
-
-Caused by:
- invalid type: integer `3`, expected a boolean or a string for key [..]
-"));
-}
+++ /dev/null
-extern crate hamcrest;
-extern crate cargotest;
-
-use cargotest::support::{project, execs, main_file, basic_bin_manifest};
-use hamcrest::{assert_that};
-
-fn assert_not_a_cargo_toml(command: &str, manifest_path_argument: &str) {
- let p = project("foo")
- .file("Cargo.toml", &basic_bin_manifest("foo"))
- .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
- .build();
-
- assert_that(p.cargo(command)
- .arg("--manifest-path").arg(manifest_path_argument)
- .cwd(p.root().parent().unwrap()),
- execs().with_status(101)
- .with_stderr("[ERROR] the manifest-path must be a path \
- to a Cargo.toml file"));
-}
-
-
-fn assert_cargo_toml_doesnt_exist(command: &str, manifest_path_argument: &str) {
- let p = project("foo").build();
- let expected_path = manifest_path_argument
- .split('/').collect::<Vec<_>>().join("[..]");
-
- assert_that(p.cargo(command)
- .arg("--manifest-path").arg(manifest_path_argument)
- .cwd(p.root().parent().unwrap()),
- execs().with_status(101)
- .with_stderr(
- format!("[ERROR] manifest path `{}` does not exist",
- expected_path)
- ));
-}
-
-#[test]
-fn bench_dir_containing_cargo_toml() {
- assert_not_a_cargo_toml("bench", "foo");
-}
-
-#[test]
-fn bench_dir_plus_file() {
- assert_not_a_cargo_toml("bench", "foo/bar");
-}
-
-#[test]
-fn bench_dir_plus_path() {
- assert_not_a_cargo_toml("bench", "foo/bar/baz");
-}
-
-#[test]
-fn bench_dir_to_nonexistent_cargo_toml() {
- assert_cargo_toml_doesnt_exist("bench", "foo/bar/baz/Cargo.toml");
-}
-
-#[test]
-fn build_dir_containing_cargo_toml() {
- assert_not_a_cargo_toml("build", "foo");
-}
-
-#[test]
-fn build_dir_plus_file() {
- assert_not_a_cargo_toml("bench", "foo/bar");
-}
-
-#[test]
-fn build_dir_plus_path() {
- assert_not_a_cargo_toml("bench", "foo/bar/baz");
-}
-
-#[test]
-fn build_dir_to_nonexistent_cargo_toml() {
- assert_cargo_toml_doesnt_exist("build", "foo/bar/baz/Cargo.toml");
-}
-
-#[test]
-fn clean_dir_containing_cargo_toml() {
- assert_not_a_cargo_toml("clean", "foo");
-}
-
-#[test]
-fn clean_dir_plus_file() {
- assert_not_a_cargo_toml("clean", "foo/bar");
-}
-
-#[test]
-fn clean_dir_plus_path() {
- assert_not_a_cargo_toml("clean", "foo/bar/baz");
-}
-
-#[test]
-fn clean_dir_to_nonexistent_cargo_toml() {
- assert_cargo_toml_doesnt_exist("clean", "foo/bar/baz/Cargo.toml");
-}
-
-#[test]
-fn doc_dir_containing_cargo_toml() {
- assert_not_a_cargo_toml("doc", "foo");
-}
-
-#[test]
-fn doc_dir_plus_file() {
- assert_not_a_cargo_toml("doc", "foo/bar");
-}
-
-#[test]
-fn doc_dir_plus_path() {
- assert_not_a_cargo_toml("doc", "foo/bar/baz");
-}
-
-#[test]
-fn doc_dir_to_nonexistent_cargo_toml() {
- assert_cargo_toml_doesnt_exist("doc", "foo/bar/baz/Cargo.toml");
-}
-
-#[test]
-fn fetch_dir_containing_cargo_toml() {
- assert_not_a_cargo_toml("fetch", "foo");
-}
-
-#[test]
-fn fetch_dir_plus_file() {
- assert_not_a_cargo_toml("fetch", "foo/bar");
-}
-
-#[test]
-fn fetch_dir_plus_path() {
- assert_not_a_cargo_toml("fetch", "foo/bar/baz");
-}
-
-#[test]
-fn fetch_dir_to_nonexistent_cargo_toml() {
- assert_cargo_toml_doesnt_exist("fetch", "foo/bar/baz/Cargo.toml");
-}
-
-#[test]
-fn generate_lockfile_dir_containing_cargo_toml() {
- assert_not_a_cargo_toml("generate-lockfile", "foo");
-}
-
-#[test]
-fn generate_lockfile_dir_plus_file() {
- assert_not_a_cargo_toml("generate-lockfile", "foo/bar");
-}
-
-#[test]
-fn generate_lockfile_dir_plus_path() {
- assert_not_a_cargo_toml("generate-lockfile", "foo/bar/baz");
-}
-
-#[test]
-fn generate_lockfile_dir_to_nonexistent_cargo_toml() {
- assert_cargo_toml_doesnt_exist("generate-lockfile", "foo/bar/baz/Cargo.toml");
-}
-
-#[test]
-fn package_dir_containing_cargo_toml() {
- assert_not_a_cargo_toml("package", "foo");
-}
-
-#[test]
-fn package_dir_plus_file() {
- assert_not_a_cargo_toml("package", "foo/bar");
-}
-
-#[test]
-fn package_dir_plus_path() {
- assert_not_a_cargo_toml("package", "foo/bar/baz");
-}
-
-#[test]
-fn package_dir_to_nonexistent_cargo_toml() {
- assert_cargo_toml_doesnt_exist("package", "foo/bar/baz/Cargo.toml");
-}
-
-#[test]
-fn pkgid_dir_containing_cargo_toml() {
- assert_not_a_cargo_toml("pkgid", "foo");
-}
-
-#[test]
-fn pkgid_dir_plus_file() {
- assert_not_a_cargo_toml("pkgid", "foo/bar");
-}
-
-#[test]
-fn pkgid_dir_plus_path() {
- assert_not_a_cargo_toml("pkgid", "foo/bar/baz");
-}
-
-#[test]
-fn pkgid_dir_to_nonexistent_cargo_toml() {
- assert_cargo_toml_doesnt_exist("pkgid", "foo/bar/baz/Cargo.toml");
-}
-
-#[test]
-fn publish_dir_containing_cargo_toml() {
- assert_not_a_cargo_toml("publish", "foo");
-}
-
-#[test]
-fn publish_dir_plus_file() {
- assert_not_a_cargo_toml("publish", "foo/bar");
-}
-
-#[test]
-fn publish_dir_plus_path() {
- assert_not_a_cargo_toml("publish", "foo/bar/baz");
-}
-
-#[test]
-fn publish_dir_to_nonexistent_cargo_toml() {
- assert_cargo_toml_doesnt_exist("publish", "foo/bar/baz/Cargo.toml");
-}
-
-#[test]
-fn read_manifest_dir_containing_cargo_toml() {
- assert_not_a_cargo_toml("read-manifest", "foo");
-}
-
-#[test]
-fn read_manifest_dir_plus_file() {
- assert_not_a_cargo_toml("read-manifest", "foo/bar");
-}
-
-#[test]
-fn read_manifest_dir_plus_path() {
- assert_not_a_cargo_toml("read-manifest", "foo/bar/baz");
-}
-
-#[test]
-fn read_manifest_dir_to_nonexistent_cargo_toml() {
- assert_cargo_toml_doesnt_exist("read-manifest", "foo/bar/baz/Cargo.toml");
-}
-
-#[test]
-fn run_dir_containing_cargo_toml() {
- assert_not_a_cargo_toml("run", "foo");
-}
-
-#[test]
-fn run_dir_plus_file() {
- assert_not_a_cargo_toml("run", "foo/bar");
-}
-
-#[test]
-fn run_dir_plus_path() {
- assert_not_a_cargo_toml("run", "foo/bar/baz");
-}
-
-#[test]
-fn run_dir_to_nonexistent_cargo_toml() {
- assert_cargo_toml_doesnt_exist("run", "foo/bar/baz/Cargo.toml");
-}
-
-#[test]
-fn rustc_dir_containing_cargo_toml() {
- assert_not_a_cargo_toml("rustc", "foo");
-}
-
-#[test]
-fn rustc_dir_plus_file() {
- assert_not_a_cargo_toml("rustc", "foo/bar");
-}
-
-#[test]
-fn rustc_dir_plus_path() {
- assert_not_a_cargo_toml("rustc", "foo/bar/baz");
-}
-
-#[test]
-fn rustc_dir_to_nonexistent_cargo_toml() {
- assert_cargo_toml_doesnt_exist("rustc", "foo/bar/baz/Cargo.toml");
-}
-
-#[test]
-fn test_dir_containing_cargo_toml() {
- assert_not_a_cargo_toml("test", "foo");
-}
-
-#[test]
-fn test_dir_plus_file() {
- assert_not_a_cargo_toml("test", "foo/bar");
-}
-
-#[test]
-fn test_dir_plus_path() {
- assert_not_a_cargo_toml("test", "foo/bar/baz");
-}
-
-#[test]
-fn test_dir_to_nonexistent_cargo_toml() {
- assert_cargo_toml_doesnt_exist("test", "foo/bar/baz/Cargo.toml");
-}
-
-#[test]
-fn update_dir_containing_cargo_toml() {
- assert_not_a_cargo_toml("update", "foo");
-}
-
-#[test]
-fn update_dir_plus_file() {
- assert_not_a_cargo_toml("update", "foo/bar");
-}
-
-#[test]
-fn update_dir_plus_path() {
- assert_not_a_cargo_toml("update", "foo/bar/baz");
-}
-
-#[test]
-fn update_dir_to_nonexistent_cargo_toml() {
- assert_cargo_toml_doesnt_exist("update", "foo/bar/baz/Cargo.toml");
-}
-
-#[test]
-fn verify_project_dir_containing_cargo_toml() {
- let p = project("foo")
- .file("Cargo.toml", &basic_bin_manifest("foo"))
- .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
- .build();
-
- assert_that(p.cargo("verify-project")
- .arg("--manifest-path").arg("foo")
- .cwd(p.root().parent().unwrap()),
- execs().with_status(1)
- .with_stdout("\
-{\"invalid\":\"the manifest-path must be a path to a Cargo.toml file\"}\
- "));
-}
-
-#[test]
-fn verify_project_dir_plus_file() {
- let p = project("foo")
- .file("Cargo.toml", &basic_bin_manifest("foo"))
- .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
- .build();
-
- assert_that(p.cargo("verify-project")
- .arg("--manifest-path").arg("foo/bar")
- .cwd(p.root().parent().unwrap()),
- execs().with_status(1)
- .with_stdout("\
-{\"invalid\":\"the manifest-path must be a path to a Cargo.toml file\"}\
- "));
-}
-
-#[test]
-fn verify_project_dir_plus_path() {
- let p = project("foo")
- .file("Cargo.toml", &basic_bin_manifest("foo"))
- .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
- .build();
-
- assert_that(p.cargo("verify-project")
- .arg("--manifest-path").arg("foo/bar/baz")
- .cwd(p.root().parent().unwrap()),
- execs().with_status(1)
- .with_stdout("\
-{\"invalid\":\"the manifest-path must be a path to a Cargo.toml file\"}\
- "));
-}
-
-#[test]
-fn verify_project_dir_to_nonexistent_cargo_toml() {
- let p = project("foo").build();
- assert_that(p.cargo("verify-project")
- .arg("--manifest-path").arg("foo/bar/baz/Cargo.toml")
- .cwd(p.root().parent().unwrap()),
- execs().with_status(1)
- .with_stdout("\
-{\"invalid\":\"manifest path `foo[..]bar[..]baz[..]Cargo.toml` does not exist\"}\
- "));
-}
+++ /dev/null
-extern crate cargotest;
-extern crate cargo;
-extern crate hamcrest;
-
-use std::str;
-
-use cargo::util::process;
-use cargotest::is_nightly;
-use cargotest::support::paths::CargoPathExt;
-use cargotest::support::{project, execs, basic_bin_manifest, basic_lib_manifest};
-use hamcrest::{assert_that, existing_file};
-
-#[test]
-fn cargo_bench_simple() {
- if !is_nightly() { return }
-
- let p = project("foo")
- .file("Cargo.toml", &basic_bin_manifest("foo"))
- .file("src/main.rs", r#"
- #![feature(test)]
- #[cfg(test)]
- extern crate test;
-
- fn hello() -> &'static str {
- "hello"
- }
-
- pub fn main() {
- println!("{}", hello())
- }
-
- #[bench]
- fn bench_hello(_b: &mut test::Bencher) {
- assert_eq!(hello(), "hello")
- }"#)
- .build();
-
- assert_that(p.cargo("build"), execs());
- assert_that(&p.bin("foo"), existing_file());
-
- assert_that(process(&p.bin("foo")),
- execs().with_stdout("hello\n"));
-
- assert_that(p.cargo("bench"),
- execs().with_stderr(&format!("\
-[COMPILING] foo v0.5.0 ({})
-[FINISHED] release [optimized] target(s) in [..]
-[RUNNING] target[/]release[/]deps[/]foo-[..][EXE]", p.url()))
- .with_stdout_contains("test bench_hello ... bench: [..]"));
-}
-
-#[test]
-fn bench_bench_implicit() {
- if !is_nightly() { return }
-
- let p = project("foo")
- .file("Cargo.toml" , r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/main.rs", r#"
- #![cfg_attr(test, feature(test))]
- #[cfg(test)]
- extern crate test;
- #[bench] fn run1(_ben: &mut test::Bencher) { }
- fn main() { println!("Hello main!"); }"#)
- .file("tests/other.rs", r#"
- #![feature(test)]
- extern crate test;
- #[bench] fn run3(_ben: &mut test::Bencher) { }"#)
- .file("benches/mybench.rs", r#"
- #![feature(test)]
- extern crate test;
- #[bench] fn run2(_ben: &mut test::Bencher) { }"#)
- .build();
-
- assert_that(p.cargo("bench").arg("--benches"),
- execs().with_status(0)
- .with_stderr(format!("\
-[COMPILING] foo v0.0.1 ({dir})
-[FINISHED] release [optimized] target(s) in [..]
-[RUNNING] target[/]release[/]deps[/]foo-[..][EXE]
-[RUNNING] target[/]release[/]deps[/]mybench-[..][EXE]
-", dir = p.url()))
- .with_stdout_contains("test run2 ... bench: [..]"));
-}
-
-#[test]
-fn bench_bin_implicit() {
- if !is_nightly() { return }
-
- let p = project("foo")
- .file("Cargo.toml" , r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/main.rs", r#"
- #![feature(test)]
- #[cfg(test)]
- extern crate test;
- #[bench] fn run1(_ben: &mut test::Bencher) { }
- fn main() { println!("Hello main!"); }"#)
- .file("tests/other.rs", r#"
- #![feature(test)]
- extern crate test;
- #[bench] fn run3(_ben: &mut test::Bencher) { }"#)
- .file("benches/mybench.rs", r#"
- #![feature(test)]
- extern crate test;
- #[bench] fn run2(_ben: &mut test::Bencher) { }"#)
- .build();
-
- assert_that(p.cargo("bench").arg("--bins"),
- execs().with_status(0)
- .with_stderr(format!("\
-[COMPILING] foo v0.0.1 ({dir})
-[FINISHED] release [optimized] target(s) in [..]
-[RUNNING] target[/]release[/]deps[/]foo-[..][EXE]
-", dir = p.url()))
- .with_stdout_contains("test run1 ... bench: [..]"));
-}
-
-#[test]
-fn bench_tarname() {
- if !is_nightly() { return }
-
- let p = project("foo")
- .file("Cargo.toml" , r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("benches/bin1.rs", r#"
- #![feature(test)]
- extern crate test;
- #[bench] fn run1(_ben: &mut test::Bencher) { }"#)
- .file("benches/bin2.rs", r#"
- #![feature(test)]
- extern crate test;
- #[bench] fn run2(_ben: &mut test::Bencher) { }"#)
- .build();
-
- assert_that(p.cargo("bench").arg("--bench").arg("bin2"),
- execs().with_status(0)
- .with_stderr(format!("\
-[COMPILING] foo v0.0.1 ({dir})
-[FINISHED] release [optimized] target(s) in [..]
-[RUNNING] target[/]release[/]deps[/]bin2-[..][EXE]
-", dir = p.url()))
- .with_stdout_contains("test run2 ... bench: [..]"));
-}
-
-#[test]
-fn bench_multiple_targets() {
- if !is_nightly() { return }
-
- let p = project("foo")
- .file("Cargo.toml" , r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("benches/bin1.rs", r#"
- #![feature(test)]
- extern crate test;
- #[bench] fn run1(_ben: &mut test::Bencher) { }"#)
- .file("benches/bin2.rs", r#"
- #![feature(test)]
- extern crate test;
- #[bench] fn run2(_ben: &mut test::Bencher) { }"#)
- .file("benches/bin3.rs", r#"
- #![feature(test)]
- extern crate test;
- #[bench] fn run3(_ben: &mut test::Bencher) { }"#)
- .build();
-
- assert_that(p.cargo("bench")
- .arg("--bench").arg("bin1")
- .arg("--bench").arg("bin2"),
- execs()
- .with_status(0)
- .with_stdout_contains("test run1 ... bench: [..]")
- .with_stdout_contains("test run2 ... bench: [..]")
- .with_stdout_does_not_contain("run3"));
-}
-
-#[test]
-fn cargo_bench_verbose() {
- if !is_nightly() { return }
-
- let p = project("foo")
- .file("Cargo.toml", &basic_bin_manifest("foo"))
- .file("src/main.rs", r#"
- #![feature(test)]
- #[cfg(test)]
- extern crate test;
- fn main() {}
- #[bench] fn bench_hello(_b: &mut test::Bencher) {}
- "#)
- .build();
-
- assert_that(p.cargo("bench").arg("-v").arg("hello"),
- execs().with_stderr(&format!("\
-[COMPILING] foo v0.5.0 ({url})
-[RUNNING] `rustc [..] src[/]main.rs [..]`
-[FINISHED] release [optimized] target(s) in [..]
-[RUNNING] `[..]target[/]release[/]deps[/]foo-[..][EXE] hello --bench`", url = p.url()))
- .with_stdout_contains("test bench_hello ... bench: [..]"));
-}
-
-#[test]
-fn many_similar_names() {
- if !is_nightly() { return }
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/lib.rs", "
- #![feature(test)]
- #[cfg(test)]
- extern crate test;
- pub fn foo() {}
- #[bench] fn lib_bench(_b: &mut test::Bencher) {}
- ")
- .file("src/main.rs", "
- #![feature(test)]
- #[cfg(test)]
- extern crate foo;
- #[cfg(test)]
- extern crate test;
- fn main() {}
- #[bench] fn bin_bench(_b: &mut test::Bencher) { foo::foo() }
- ")
- .file("benches/foo.rs", r#"
- #![feature(test)]
- extern crate foo;
- extern crate test;
- #[bench] fn bench_bench(_b: &mut test::Bencher) { foo::foo() }
- "#)
- .build();
-
- let output = p.cargo("bench").exec_with_output().unwrap();
- let output = str::from_utf8(&output.stdout).unwrap();
- assert!(output.contains("test bin_bench"), "bin_bench missing\n{}", output);
- assert!(output.contains("test lib_bench"), "lib_bench missing\n{}", output);
- assert!(output.contains("test bench_bench"), "bench_bench missing\n{}", output);
-}
-
-#[test]
-fn cargo_bench_failing_test() {
- if !is_nightly() { return }
-
- let p = project("foo")
- .file("Cargo.toml", &basic_bin_manifest("foo"))
- .file("src/main.rs", r#"
- #![feature(test)]
- #[cfg(test)]
- extern crate test;
- fn hello() -> &'static str {
- "hello"
- }
-
- pub fn main() {
- println!("{}", hello())
- }
-
- #[bench]
- fn bench_hello(_b: &mut test::Bencher) {
- assert_eq!(hello(), "nope")
- }"#)
- .build();
-
- assert_that(p.cargo("build"), execs());
- assert_that(&p.bin("foo"), existing_file());
-
- assert_that(process(&p.bin("foo")),
- execs().with_stdout("hello\n"));
-
- // Force libtest into serial execution so that the test header will be printed.
- assert_that(p.cargo("bench").arg("--").arg("--test-threads=1"),
- execs().with_stdout_contains("test bench_hello ...[..]")
- .with_stderr_contains(format!("\
-[COMPILING] foo v0.5.0 ({})[..]
-[FINISHED] release [optimized] target(s) in [..]
-[RUNNING] target[/]release[/]deps[/]foo-[..][EXE]", p.url()))
- .with_either_contains("[..]thread '[..]' panicked at 'assertion failed: `(left == right)`[..]")
- .with_either_contains("[..]left: `\"hello\"`[..]")
- .with_either_contains("[..]right: `\"nope\"`[..]")
- .with_either_contains("[..]src[/]main.rs:15[..]")
- .with_status(101));
-}
-
-#[test]
-fn bench_with_lib_dep() {
- if !is_nightly() { return }
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [[bin]]
- name = "baz"
- path = "src/main.rs"
- "#)
- .file("src/lib.rs", r#"
- #![cfg_attr(test, feature(test))]
- #[cfg(test)]
- extern crate test;
- ///
- /// ```rust
- /// extern crate foo;
- /// fn main() {
- /// println!("{}", foo::foo());
- /// }
- /// ```
- ///
- pub fn foo(){}
- #[bench] fn lib_bench(_b: &mut test::Bencher) {}
- "#)
- .file("src/main.rs", "
- #![feature(test)]
- #[allow(unused_extern_crates)]
- extern crate foo;
- #[cfg(test)]
- extern crate test;
-
- fn main() {}
-
- #[bench]
- fn bin_bench(_b: &mut test::Bencher) {}
- ")
- .build();
-
- assert_that(p.cargo("bench"),
- execs().with_stderr(&format!("\
-[COMPILING] foo v0.0.1 ({})
-[FINISHED] release [optimized] target(s) in [..]
-[RUNNING] target[/]release[/]deps[/]foo-[..][EXE]
-[RUNNING] target[/]release[/]deps[/]baz-[..][EXE]", p.url()))
- .with_stdout_contains("test lib_bench ... bench: [..]")
- .with_stdout_contains("test bin_bench ... bench: [..]"));
-}
-
-#[test]
-fn bench_with_deep_lib_dep() {
- if !is_nightly() { return }
-
- let p = project("bar")
- .file("Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
-
- [dependencies.foo]
- path = "../foo"
- "#)
- .file("src/lib.rs", "
- #![cfg_attr(test, feature(test))]
- #[cfg(test)]
- extern crate foo;
- #[cfg(test)]
- extern crate test;
- #[bench]
- fn bar_bench(_b: &mut test::Bencher) {
- foo::foo();
- }
- ")
- .build();
- let _p2 = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/lib.rs", "
- #![cfg_attr(test, feature(test))]
- #[cfg(test)]
- extern crate test;
-
- pub fn foo() {}
-
- #[bench]
- fn foo_bench(_b: &mut test::Bencher) {}
- ")
- .build();
-
- assert_that(p.cargo("bench"),
- execs().with_status(0)
- .with_stderr(&format!("\
-[COMPILING] foo v0.0.1 ([..])
-[COMPILING] bar v0.0.1 ({dir})
-[FINISHED] release [optimized] target(s) in [..]
-[RUNNING] target[/]release[/]deps[/]bar-[..][EXE]", dir = p.url()))
- .with_stdout_contains("test bar_bench ... bench: [..]"));
-}
-
-#[test]
-fn external_bench_explicit() {
- if !is_nightly() { return }
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [[bench]]
- name = "bench"
- path = "src/bench.rs"
- "#)
- .file("src/lib.rs", r#"
- #![cfg_attr(test, feature(test))]
- #[cfg(test)]
- extern crate test;
- pub fn get_hello() -> &'static str { "Hello" }
-
- #[bench]
- fn internal_bench(_b: &mut test::Bencher) {}
- "#)
- .file("src/bench.rs", r#"
- #![feature(test)]
- #[allow(unused_extern_crates)]
- extern crate foo;
- extern crate test;
-
- #[bench]
- fn external_bench(_b: &mut test::Bencher) {}
- "#)
- .build();
-
- assert_that(p.cargo("bench"),
- execs().with_stderr(&format!("\
-[COMPILING] foo v0.0.1 ({})
-[FINISHED] release [optimized] target(s) in [..]
-[RUNNING] target[/]release[/]deps[/]foo-[..][EXE]
-[RUNNING] target[/]release[/]deps[/]bench-[..][EXE]", p.url()))
- .with_stdout_contains("test internal_bench ... bench: [..]")
- .with_stdout_contains("test external_bench ... bench: [..]"));
-}
-
-#[test]
-fn external_bench_implicit() {
- if !is_nightly() { return }
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/lib.rs", r#"
- #![cfg_attr(test, feature(test))]
- #[cfg(test)]
- extern crate test;
-
- pub fn get_hello() -> &'static str { "Hello" }
-
- #[bench]
- fn internal_bench(_b: &mut test::Bencher) {}
- "#)
- .file("benches/external.rs", r#"
- #![feature(test)]
- #[allow(unused_extern_crates)]
- extern crate foo;
- extern crate test;
-
- #[bench]
- fn external_bench(_b: &mut test::Bencher) {}
- "#)
- .build();
-
- assert_that(p.cargo("bench"),
- execs().with_stderr(&format!("\
-[COMPILING] foo v0.0.1 ({})
-[FINISHED] release [optimized] target(s) in [..]
-[RUNNING] target[/]release[/]deps[/]foo-[..][EXE]
-[RUNNING] target[/]release[/]deps[/]external-[..][EXE]", p.url()))
- .with_stdout_contains("test internal_bench ... bench: [..]")
- .with_stdout_contains("test external_bench ... bench: [..]"));
-}
-
-#[test]
-fn dont_run_examples() {
- if !is_nightly() { return }
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/lib.rs", r"")
- .file("examples/dont-run-me-i-will-fail.rs", r#"
- fn main() { panic!("Examples should not be run by 'cargo test'"); }
- "#)
- .build();
- assert_that(p.cargo("bench"),
- execs().with_status(0));
-}
-
-#[test]
-fn pass_through_command_line() {
- if !is_nightly() { return }
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/lib.rs", "
- #![feature(test)]
- #[cfg(test)]
- extern crate test;
-
- #[bench] fn foo(_b: &mut test::Bencher) {}
- #[bench] fn bar(_b: &mut test::Bencher) {}
- ")
- .build();
-
- assert_that(p.cargo("bench").arg("bar"),
- execs().with_status(0)
- .with_stderr(&format!("\
-[COMPILING] foo v0.0.1 ({dir})
-[FINISHED] release [optimized] target(s) in [..]
-[RUNNING] target[/]release[/]deps[/]foo-[..][EXE]", dir = p.url()))
- .with_stdout_contains("test bar ... bench: [..]"));
-
- assert_that(p.cargo("bench").arg("foo"),
- execs().with_status(0)
- .with_stderr("[FINISHED] release [optimized] target(s) in [..]
-[RUNNING] target[/]release[/]deps[/]foo-[..][EXE]")
- .with_stdout_contains("test foo ... bench: [..]"));
-}
-
-// Regression test for running cargo-bench twice with
-// tests in an rlib
-#[test]
-fn cargo_bench_twice() {
- if !is_nightly() { return }
-
- let p = project("test_twice")
- .file("Cargo.toml", &basic_lib_manifest("test_twice"))
- .file("src/test_twice.rs", r#"
- #![crate_type = "rlib"]
- #![feature(test)]
- #[cfg(test)]
- extern crate test;
-
- #[bench]
- fn dummy_bench(b: &mut test::Bencher) { }
- "#)
- .build();
-
- p.cargo("build");
-
- for _ in 0..2 {
- assert_that(p.cargo("bench"),
- execs().with_status(0));
- }
-}
-
-#[test]
-fn lib_bin_same_name() {
- if !is_nightly() { return }
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [lib]
- name = "foo"
- [[bin]]
- name = "foo"
- "#)
- .file("src/lib.rs", "
- #![cfg_attr(test, feature(test))]
- #[cfg(test)]
- extern crate test;
- #[bench] fn lib_bench(_b: &mut test::Bencher) {}
- ")
- .file("src/main.rs", "
- #![cfg_attr(test, feature(test))]
- #[allow(unused_extern_crates)]
- extern crate foo;
- #[cfg(test)]
- extern crate test;
-
- #[bench]
- fn bin_bench(_b: &mut test::Bencher) {}
- ")
- .build();
-
- assert_that(p.cargo("bench"),
- execs().with_stderr(&format!("\
-[COMPILING] foo v0.0.1 ({})
-[FINISHED] release [optimized] target(s) in [..]
-[RUNNING] target[/]release[/]deps[/]foo-[..][EXE]
-[RUNNING] target[/]release[/]deps[/]foo-[..][EXE]", p.url()))
- .with_stdout_contains_n("test [..] ... bench: [..]", 2));
-}
-
-#[test]
-fn lib_with_standard_name() {
- if !is_nightly() { return }
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "syntax"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/lib.rs", "
- #![cfg_attr(test, feature(test))]
- #[cfg(test)]
- extern crate test;
-
- /// ```
- /// syntax::foo();
- /// ```
- pub fn foo() {}
-
- #[bench]
- fn foo_bench(_b: &mut test::Bencher) {}
- ")
- .file("benches/bench.rs", "
- #![feature(test)]
- extern crate syntax;
- extern crate test;
-
- #[bench]
- fn bench(_b: &mut test::Bencher) { syntax::foo() }
- ")
- .build();
-
- assert_that(p.cargo("bench"),
- execs().with_status(0)
- .with_stderr(&format!("\
-[COMPILING] syntax v0.0.1 ({dir})
-[FINISHED] release [optimized] target(s) in [..]
-[RUNNING] target[/]release[/]deps[/]syntax-[..][EXE]
-[RUNNING] target[/]release[/]deps[/]bench-[..][EXE]", dir = p.url()))
- .with_stdout_contains("test foo_bench ... bench: [..]")
- .with_stdout_contains("test bench ... bench: [..]"));
-}
-
-#[test]
-fn lib_with_standard_name2() {
- if !is_nightly() { return }
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "syntax"
- version = "0.0.1"
- authors = []
-
- [lib]
- name = "syntax"
- bench = false
- doctest = false
- "#)
- .file("src/lib.rs", "
- pub fn foo() {}
- ")
- .file("src/main.rs", "
- #![feature(test)]
- #[cfg(test)]
- extern crate syntax;
- #[cfg(test)]
- extern crate test;
-
- fn main() {}
-
- #[bench]
- fn bench(_b: &mut test::Bencher) { syntax::foo() }
- ")
- .build();
-
- assert_that(p.cargo("bench"),
- execs().with_status(0)
- .with_stderr(&format!("\
-[COMPILING] syntax v0.0.1 ({dir})
-[FINISHED] release [optimized] target(s) in [..]
-[RUNNING] target[/]release[/]deps[/]syntax-[..][EXE]", dir = p.url()))
- .with_stdout_contains("test bench ... bench: [..]"));
-}
-
-#[test]
-fn bench_dylib() {
- if !is_nightly() { return }
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [lib]
- name = "foo"
- crate_type = ["dylib"]
-
- [dependencies.bar]
- path = "bar"
- "#)
- .file("src/lib.rs", r#"
- #![cfg_attr(test, feature(test))]
- extern crate bar as the_bar;
- #[cfg(test)]
- extern crate test;
-
- pub fn bar() { the_bar::baz(); }
-
- #[bench]
- fn foo(_b: &mut test::Bencher) {}
- "#)
- .file("benches/bench.rs", r#"
- #![feature(test)]
- extern crate foo as the_foo;
- extern crate test;
-
- #[bench]
- fn foo(_b: &mut test::Bencher) { the_foo::bar(); }
- "#)
- .file("bar/Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
-
- [lib]
- name = "bar"
- crate_type = ["dylib"]
- "#)
- .file("bar/src/lib.rs", "
- pub fn baz() {}
- ")
- .build();
-
- assert_that(p.cargo("bench").arg("-v"),
- execs().with_status(0)
- .with_stderr(&format!("\
-[COMPILING] bar v0.0.1 ({dir}/bar)
-[RUNNING] [..] -C opt-level=3 [..]
-[COMPILING] foo v0.0.1 ({dir})
-[RUNNING] [..] -C opt-level=3 [..]
-[RUNNING] [..] -C opt-level=3 [..]
-[RUNNING] [..] -C opt-level=3 [..]
-[FINISHED] release [optimized] target(s) in [..]
-[RUNNING] `[..]target[/]release[/]deps[/]foo-[..][EXE] --bench`
-[RUNNING] `[..]target[/]release[/]deps[/]bench-[..][EXE] --bench`", dir = p.url()))
- .with_stdout_contains_n("test foo ... bench: [..]", 2));
-
- p.root().move_into_the_past();
- assert_that(p.cargo("bench").arg("-v"),
- execs().with_status(0)
- .with_stderr(&format!("\
-[FRESH] bar v0.0.1 ({dir}/bar)
-[FRESH] foo v0.0.1 ({dir})
-[FINISHED] release [optimized] target(s) in [..]
-[RUNNING] `[..]target[/]release[/]deps[/]foo-[..][EXE] --bench`
-[RUNNING] `[..]target[/]release[/]deps[/]bench-[..][EXE] --bench`", dir = p.url()))
- .with_stdout_contains_n("test foo ... bench: [..]", 2));
-}
-
-#[test]
-fn bench_twice_with_build_cmd() {
- if !is_nightly() { return }
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- build = "build.rs"
- "#)
- .file("build.rs", "fn main() {}")
- .file("src/lib.rs", "
- #![feature(test)]
- #[cfg(test)]
- extern crate test;
- #[bench]
- fn foo(_b: &mut test::Bencher) {}
- ")
- .build();
-
- assert_that(p.cargo("bench"),
- execs().with_status(0)
- .with_stderr(&format!("\
-[COMPILING] foo v0.0.1 ({dir})
-[FINISHED] release [optimized] target(s) in [..]
-[RUNNING] target[/]release[/]deps[/]foo-[..][EXE]", dir = p.url()))
- .with_stdout_contains("test foo ... bench: [..]"));
-
- assert_that(p.cargo("bench"),
- execs().with_status(0)
- .with_stderr("[FINISHED] release [optimized] target(s) in [..]
-[RUNNING] target[/]release[/]deps[/]foo-[..][EXE]")
- .with_stdout_contains("test foo ... bench: [..]"));
-}
-
-#[test]
-fn bench_with_examples() {
- if !is_nightly() { return }
-
- let p = project("testbench")
- .file("Cargo.toml", r#"
- [package]
- name = "testbench"
- version = "6.6.6"
- authors = []
-
- [[example]]
- name = "teste1"
-
- [[bench]]
- name = "testb1"
- "#)
- .file("src/lib.rs", r#"
- #![cfg_attr(test, feature(test))]
- #[cfg(test)]
- extern crate test;
- #[cfg(test)]
- use test::Bencher;
-
- pub fn f1() {
- println!("f1");
- }
-
- pub fn f2() {}
-
- #[bench]
- fn bench_bench1(_b: &mut Bencher) {
- f2();
- }
- "#)
- .file("benches/testb1.rs", "
- #![feature(test)]
- extern crate testbench;
- extern crate test;
-
- use test::Bencher;
-
- #[bench]
- fn bench_bench2(_b: &mut Bencher) {
- testbench::f2();
- }
- ")
- .file("examples/teste1.rs", r#"
- extern crate testbench;
-
- fn main() {
- println!("example1");
- testbench::f1();
- }
- "#)
- .build();
-
- assert_that(p.cargo("bench").arg("-v"),
- execs().with_status(0)
- .with_stderr(&format!("\
-[COMPILING] testbench v6.6.6 ({url})
-[RUNNING] `rustc [..]`
-[RUNNING] `rustc [..]`
-[RUNNING] `rustc [..]`
-[FINISHED] release [optimized] target(s) in [..]
-[RUNNING] `{dir}[/]target[/]release[/]deps[/]testbench-[..][EXE] --bench`
-[RUNNING] `{dir}[/]target[/]release[/]deps[/]testb1-[..][EXE] --bench`",
- dir = p.root().display(), url = p.url()))
- .with_stdout_contains("test bench_bench1 ... bench: [..]")
- .with_stdout_contains("test bench_bench2 ... bench: [..]"));
-}
-
-#[test]
-fn test_a_bench() {
- if !is_nightly() { return }
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- authors = []
- version = "0.1.0"
-
- [lib]
- name = "foo"
- test = false
- doctest = false
-
- [[bench]]
- name = "b"
- test = true
- "#)
- .file("src/lib.rs", "")
- .file("benches/b.rs", r#"
- #[test]
- fn foo() {}
- "#)
- .build();
-
- assert_that(p.cargo("test"),
- execs().with_status(0)
- .with_stderr("\
-[COMPILING] foo v0.1.0 ([..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] target[/]debug[/]deps[/]b-[..][EXE]")
- .with_stdout_contains("test foo ... ok"));
-}
-
-#[test]
-fn test_bench_no_run() {
- if !is_nightly() { return }
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- authors = []
- version = "0.1.0"
- "#)
- .file("src/lib.rs", "")
- .file("benches/bbaz.rs", r#"
- #![feature(test)]
-
- extern crate test;
-
- use test::Bencher;
-
- #[bench]
- fn bench_baz(_: &mut Bencher) {}
- "#)
- .build();
-
- assert_that(p.cargo("bench").arg("--no-run"),
- execs().with_status(0)
- .with_stderr("\
-[COMPILING] foo v0.1.0 ([..])
-[FINISHED] release [optimized] target(s) in [..]
-"));
-}
-
-#[test]
-fn test_bench_no_fail_fast() {
- if !is_nightly() { return }
-
- let p = project("foo")
- .file("Cargo.toml", &basic_bin_manifest("foo"))
- .file("src/foo.rs", r#"
- #![feature(test)]
- #[cfg(test)]
- extern crate test;
- fn hello() -> &'static str {
- "hello"
- }
-
- pub fn main() {
- println!("{}", hello())
- }
-
- #[bench]
- fn bench_hello(_b: &mut test::Bencher) {
- assert_eq!(hello(), "hello")
- }
-
- #[bench]
- fn bench_nope(_b: &mut test::Bencher) {
- assert_eq!("nope", hello())
- }"#)
- .build();
-
- assert_that(p.cargo("bench").arg("--no-fail-fast").arg("--").arg("--test-threads=1"),
- execs().with_status(101)
- .with_stderr_contains("\
-[RUNNING] target[/]release[/]deps[/]foo-[..][EXE]")
- .with_stdout_contains("running 2 tests")
- .with_stderr_contains("\
-[RUNNING] target[/]release[/]deps[/]foo-[..][EXE]")
- .with_stdout_contains("test bench_hello [..]")
- .with_stdout_contains("test bench_nope [..]"));
-}
-
-#[test]
-fn test_bench_multiple_packages() {
- if !is_nightly() { return }
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- authors = []
- version = "0.1.0"
-
- [dependencies.bar]
- path = "../bar"
-
- [dependencies.baz]
- path = "../baz"
- "#)
- .file("src/lib.rs", "")
- .build();
-
- let _bar = project("bar")
- .file("Cargo.toml", r#"
- [project]
- name = "bar"
- authors = []
- version = "0.1.0"
-
- [[bench]]
- name = "bbar"
- test = true
- "#)
- .file("src/lib.rs", "")
- .file("benches/bbar.rs", r#"
- #![feature(test)]
- extern crate test;
-
- use test::Bencher;
-
- #[bench]
- fn bench_bar(_b: &mut Bencher) {}
- "#)
- .build();
-
- let _baz = project("baz")
- .file("Cargo.toml", r#"
- [project]
- name = "baz"
- authors = []
- version = "0.1.0"
-
- [[bench]]
- name = "bbaz"
- test = true
- "#)
- .file("src/lib.rs", "")
- .file("benches/bbaz.rs", r#"
- #![feature(test)]
- extern crate test;
-
- use test::Bencher;
-
- #[bench]
- fn bench_baz(_b: &mut Bencher) {}
- "#)
- .build();
-
-
- assert_that(p.cargo("bench").arg("-p").arg("bar").arg("-p").arg("baz"),
- execs().with_status(0)
- .with_stderr_contains("\
-[RUNNING] target[/]release[/]deps[/]bbaz-[..][EXE]")
- .with_stdout_contains("test bench_baz ... bench: [..]")
- .with_stderr_contains("\
-[RUNNING] target[/]release[/]deps[/]bbar-[..][EXE]")
- .with_stdout_contains("test bench_bar ... bench: [..]"));
-}
-
-#[test]
-fn bench_all_workspace() {
- if !is_nightly() { return }
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.1.0"
-
- [dependencies]
- bar = { path = "bar" }
-
- [workspace]
- "#)
- .file("src/main.rs", r#"
- fn main() {}
- "#)
- .file("benches/foo.rs", r#"
- #![feature(test)]
- extern crate test;
-
- use test::Bencher;
-
- #[bench]
- fn bench_foo(_: &mut Bencher) -> () { () }
- "#)
- .file("bar/Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.1.0"
- "#)
- .file("bar/src/lib.rs", r#"
- pub fn bar() {}
- "#)
- .file("bar/benches/bar.rs", r#"
- #![feature(test)]
- extern crate test;
-
- use test::Bencher;
-
- #[bench]
- fn bench_bar(_: &mut Bencher) -> () { () }
- "#)
- .build();
-
- assert_that(p.cargo("bench")
- .arg("--all"),
- execs().with_status(0)
- .with_stderr_contains("\
-[RUNNING] target[/]release[/]deps[/]bar-[..][EXE]")
- .with_stdout_contains("test bench_bar ... bench: [..]")
- .with_stderr_contains("\
-[RUNNING] target[/]release[/]deps[/]foo-[..][EXE]")
- .with_stdout_contains("test bench_foo ... bench: [..]"));
-}
-
-#[test]
-fn bench_all_exclude() {
- if !is_nightly() { return }
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.1.0"
-
- [workspace]
- members = ["bar", "baz"]
- "#)
- .file("src/main.rs", r#"
- fn main() {}
- "#)
- .file("bar/Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.1.0"
- "#)
- .file("bar/src/lib.rs", r#"
- #![feature(test)]
- #[cfg(test)]
- extern crate test;
-
- #[bench]
- pub fn bar(b: &mut test::Bencher) {
- b.iter(|| {});
- }
- "#)
- .file("baz/Cargo.toml", r#"
- [project]
- name = "baz"
- version = "0.1.0"
- "#)
- .file("baz/src/lib.rs", r#"
- #[test]
- pub fn baz() {
- break_the_build();
- }
- "#)
- .build();
-
- assert_that(p.cargo("bench")
- .arg("--all")
- .arg("--exclude")
- .arg("baz"),
- execs().with_status(0)
- .with_stdout_contains("\
-running 1 test
-test bar ... bench: [..] ns/iter (+/- [..])"));
-}
-
-#[test]
-fn bench_all_virtual_manifest() {
- if !is_nightly() { return }
-
- let p = project("workspace")
- .file("Cargo.toml", r#"
- [workspace]
- members = ["foo", "bar"]
- "#)
- .file("foo/Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.1.0"
- "#)
- .file("foo/src/lib.rs", r#"
- pub fn foo() {}
- "#)
- .file("foo/benches/foo.rs", r#"
- #![feature(test)]
- extern crate test;
-
- use test::Bencher;
-
- #[bench]
- fn bench_foo(_: &mut Bencher) -> () { () }
- "#)
- .file("bar/Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.1.0"
- "#)
- .file("bar/src/lib.rs", r#"
- pub fn bar() {}
- "#)
- .file("bar/benches/bar.rs", r#"
- #![feature(test)]
- extern crate test;
-
- use test::Bencher;
-
- #[bench]
- fn bench_bar(_: &mut Bencher) -> () { () }
- "#)
- .build();
-
- // The order in which foo and bar are built is not guaranteed
- assert_that(p.cargo("bench")
- .arg("--all"),
- execs().with_status(0)
- .with_stderr_contains("\
-[RUNNING] target[/]release[/]deps[/]bar-[..][EXE]")
- .with_stdout_contains("test bench_bar ... bench: [..]")
- .with_stderr_contains("\
-[RUNNING] target[/]release[/]deps[/]foo-[..][EXE]")
- .with_stdout_contains("test bench_foo ... bench: [..]"));
-}
-
-// https://github.com/rust-lang/cargo/issues/4287
-#[test]
-fn legacy_bench_name() {
- if !is_nightly() { return }
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.1.0"
-
- [[bench]]
- name = "bench"
- "#)
- .file("src/lib.rs", r#"
- pub fn foo() {}
- "#)
- .file("src/bench.rs", r#"
- #![feature(test)]
- extern crate test;
-
- use test::Bencher;
-
- #[bench]
- fn bench_foo(_: &mut Bencher) -> () { () }
- "#)
- .build();
-
- assert_that(p.cargo("bench"), execs().with_status(0).with_stderr_contains("\
-[WARNING] path `[..]src[/]bench.rs` was erroneously implicitly accepted for benchmark `bench`,
-please set bench.path in Cargo.toml"));
-}
-
-#[test]
-fn bench_virtual_manifest_all_implied() {
- if !is_nightly() { return }
-
- let p = project("workspace")
- .file("Cargo.toml", r#"
- [workspace]
- members = ["foo", "bar"]
- "#)
- .file("foo/Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.1.0"
- "#)
- .file("foo/src/lib.rs", r#"
- pub fn foo() {}
- "#)
- .file("foo/benches/foo.rs", r#"
- #![feature(test)]
- extern crate test;
- use test::Bencher;
- #[bench]
- fn bench_foo(_: &mut Bencher) -> () { () }
- "#)
- .file("bar/Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.1.0"
- "#)
- .file("bar/src/lib.rs", r#"
- pub fn bar() {}
- "#)
- .file("bar/benches/bar.rs", r#"
- #![feature(test)]
- extern crate test;
- use test::Bencher;
- #[bench]
- fn bench_bar(_: &mut Bencher) -> () { () }
- "#)
- .build();
-
- // The order in which foo and bar are built is not guaranteed
-
- assert_that(p.cargo("bench"),
- execs().with_status(0)
- .with_stderr_contains("\
-[RUNNING] target[/]release[/]deps[/]bar-[..][EXE]")
- .with_stdout_contains("test bench_bar ... bench: [..]")
- .with_stderr_contains("\
-[RUNNING] target[/]release[/]deps[/]foo-[..][EXE]")
- .with_stdout_contains("test bench_foo ... bench: [..]"));
-}
+++ /dev/null
-extern crate bufstream;
-extern crate git2;
-extern crate cargotest;
-extern crate hamcrest;
-
-use std::collections::HashSet;
-use std::io::prelude::*;
-use std::net::TcpListener;
-use std::thread;
-
-use bufstream::BufStream;
-use cargotest::support::paths;
-use cargotest::support::{project, execs};
-use hamcrest::assert_that;
-
-// Test that HTTP auth is offered from `credential.helper`
-#[test]
-fn http_auth_offered() {
- let server = TcpListener::bind("127.0.0.1:0").unwrap();
- let addr = server.local_addr().unwrap();
-
- fn headers(rdr: &mut BufRead) -> HashSet<String> {
- let valid = ["GET", "Authorization", "Accept", "User-Agent"];
- rdr.lines().map(|s| s.unwrap())
- .take_while(|s| s.len() > 2)
- .map(|s| s.trim().to_string())
- .filter(|s| {
- valid.iter().any(|prefix| s.starts_with(*prefix))
- })
- .collect()
- }
-
- let t = thread::spawn(move|| {
- let mut conn = BufStream::new(server.accept().unwrap().0);
- let req = headers(&mut conn);
- let user_agent = if cfg!(windows) {
- "User-Agent: git/1.0 (libgit2 0.26.0)"
- } else {
- "User-Agent: git/2.0 (libgit2 0.26.0)"
- };
- conn.write_all(b"\
- HTTP/1.1 401 Unauthorized\r\n\
- WWW-Authenticate: Basic realm=\"wheee\"\r\n
- \r\n\
- ").unwrap();
- assert_eq!(req, vec![
- "GET /foo/bar/info/refs?service=git-upload-pack HTTP/1.1",
- "Accept: */*",
- user_agent,
- ].into_iter().map(|s| s.to_string()).collect());
- drop(conn);
-
- let mut conn = BufStream::new(server.accept().unwrap().0);
- let req = headers(&mut conn);
- conn.write_all(b"\
- HTTP/1.1 401 Unauthorized\r\n\
- WWW-Authenticate: Basic realm=\"wheee\"\r\n
- \r\n\
- ").unwrap();
- assert_eq!(req, vec![
- "GET /foo/bar/info/refs?service=git-upload-pack HTTP/1.1",
- "Authorization: Basic Zm9vOmJhcg==",
- "Accept: */*",
- user_agent,
- ].into_iter().map(|s| s.to_string()).collect());
- });
-
- let script = project("script")
- .file("Cargo.toml", r#"
- [project]
- name = "script"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/main.rs", r#"
- fn main() {
- println!("username=foo");
- println!("password=bar");
- }
- "#)
- .build();
-
- assert_that(script.cargo("build").arg("-v"),
- execs().with_status(0));
- let script = script.bin("script");
-
- let config = paths::home().join(".gitconfig");
- let mut config = git2::Config::open(&config).unwrap();
- config.set_str("credential.helper",
- &script.display().to_string()).unwrap();
-
- let p = project("foo")
- .file("Cargo.toml", &format!(r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies.bar]
- git = "http://127.0.0.1:{}/foo/bar"
- "#, addr.port()))
- .file("src/main.rs", "")
- .file(".cargo/config","\
- [net]
- retry = 0
- ")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(101).with_stderr(&format!("\
-[UPDATING] git repository `http://{addr}/foo/bar`
-[ERROR] failed to load source for a dependency on `bar`
-
-Caused by:
- Unable to update http://{addr}/foo/bar
-
-Caused by:
- failed to clone into: [..]
-
-Caused by:
- failed to authenticate when downloading repository
-attempted to find username/password via `credential.helper`, but [..]
-
-To learn more, run the command again with --verbose.
-",
- addr = addr)));
-
- t.join().ok().unwrap();
-}
-
-// Boy, sure would be nice to have a TLS implementation in rust!
-#[test]
-fn https_something_happens() {
- let server = TcpListener::bind("127.0.0.1:0").unwrap();
- let addr = server.local_addr().unwrap();
- let t = thread::spawn(move|| {
- let mut conn = server.accept().unwrap().0;
- drop(conn.write(b"1234"));
- drop(conn.shutdown(std::net::Shutdown::Write));
- drop(conn.read(&mut [0; 16]));
- });
-
- let p = project("foo")
- .file("Cargo.toml", &format!(r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies.bar]
- git = "https://127.0.0.1:{}/foo/bar"
- "#, addr.port()))
- .file("src/main.rs", "")
- .file(".cargo/config","\
- [net]
- retry = 0
- ")
- .build();
-
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(101).with_stderr_contains(&format!("\
-[UPDATING] git repository `https://{addr}/foo/bar`
-", addr = addr))
- .with_stderr_contains(&format!("\
-Caused by:
- {errmsg}
-",
- errmsg = if cfg!(windows) {
- "[..]failed to send request: [..]"
- } else if cfg!(target_os = "macos") {
- // OSX is difficult to tests as some builds may use
- // Security.framework and others may use OpenSSL. In that case let's
- // just not verify the error message here.
- "[..]"
- } else {
- "[..]SSL error: [..]"
- })));
-
- t.join().ok().unwrap();
-}
-
-// Boy, sure would be nice to have an SSH implementation in rust!
-#[test]
-fn ssh_something_happens() {
- let server = TcpListener::bind("127.0.0.1:0").unwrap();
- let addr = server.local_addr().unwrap();
- let t = thread::spawn(move|| {
- drop(server.accept().unwrap());
- });
-
- let p = project("foo")
- .file("Cargo.toml", &format!(r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies.bar]
- git = "ssh://127.0.0.1:{}/foo/bar"
- "#, addr.port()))
- .file("src/main.rs", "")
- .build();
-
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(101).with_stderr_contains(&format!("\
-[UPDATING] git repository `ssh://{addr}/foo/bar`
-", addr = addr))
- .with_stderr_contains("\
-Caused by:
- [..]failed to start SSH session: Failed getting banner[..]
-"));
- t.join().ok().unwrap();
-}
+++ /dev/null
-extern crate cargotest;
-extern crate hamcrest;
-
-use cargotest::support::{basic_bin_manifest, execs, project, Project};
-use hamcrest::{assert_that};
-
-fn verbose_output_for_lib(p: &Project) -> String {
- format!("\
-[COMPILING] {name} v{version} ({url})
-[RUNNING] `rustc --crate-name {name} src[/]lib.rs --crate-type lib \
- --emit=dep-info,link -C debuginfo=2 \
- -C metadata=[..] \
- --out-dir [..] \
- -L dependency={dir}[/]target[/]debug[/]deps`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-",
- dir = p.root().display(), url = p.url(),
- name = "foo", version = "0.0.1")
-}
-
-#[test]
-fn build_lib_only() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
-
- name = "foo"
- version = "0.0.1"
- authors = ["wycats@example.com"]
- "#)
- .file("src/main.rs", r#"
- fn main() {}
- "#)
- .file("src/lib.rs", r#" "#)
- .build();
-
- assert_that(p.cargo("build").arg("--lib").arg("-v"),
- execs()
- .with_status(0)
- .with_stderr(verbose_output_for_lib(&p)));
-}
-
-
-#[test]
-fn build_with_no_lib() {
- let p = project("foo")
- .file("Cargo.toml", &basic_bin_manifest("foo"))
- .file("src/main.rs", r#"
- fn main() {}
- "#)
- .build();
-
- assert_that(p.cargo("build").arg("--lib"),
- execs().with_status(101)
- .with_stderr("[ERROR] no library targets found"));
-}
-
-#[test]
-fn build_with_relative_cargo_home_path() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
-
- name = "foo"
- version = "0.0.1"
- authors = ["wycats@example.com"]
-
- [dependencies]
-
- "test-dependency" = { path = "src/test_dependency" }
- "#)
- .file("src/main.rs", r#"
- fn main() {}
- "#)
- .file("src/test_dependency/src/lib.rs", r#" "#)
- .file("src/test_dependency/Cargo.toml", r#"
- [package]
-
- name = "test-dependency"
- version = "0.0.1"
- authors = ["wycats@example.com"]
- "#)
- .build();
-
- assert_that(p.cargo("build").env("CARGO_HOME", "./cargo_home/"),
- execs()
- .with_status(0));
-}
+++ /dev/null
-extern crate cargotest;
-extern crate hamcrest;
-
-use std::fs::File;
-
-use cargotest::sleep_ms;
-use cargotest::support::{project, execs};
-use hamcrest::assert_that;
-
-#[test]
-fn rerun_if_env_changes() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.5.0"
- authors = []
- "#)
- .file("src/main.rs", r#"
- fn main() {}
- "#)
- .file("build.rs", r#"
- fn main() {
- println!("cargo:rerun-if-env-changed=FOO");
- }
- "#)
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0)
- .with_stderr("\
-[COMPILING] foo v0.5.0 ([..])
-[FINISHED] [..]
-"));
- assert_that(p.cargo("build").env("FOO", "bar"),
- execs().with_status(0)
- .with_stderr("\
-[COMPILING] foo v0.5.0 ([..])
-[FINISHED] [..]
-"));
- assert_that(p.cargo("build").env("FOO", "baz"),
- execs().with_status(0)
- .with_stderr("\
-[COMPILING] foo v0.5.0 ([..])
-[FINISHED] [..]
-"));
- assert_that(p.cargo("build").env("FOO", "baz"),
- execs().with_status(0)
- .with_stderr("\
-[FINISHED] [..]
-"));
- assert_that(p.cargo("build"),
- execs().with_status(0)
- .with_stderr("\
-[COMPILING] foo v0.5.0 ([..])
-[FINISHED] [..]
-"));
-}
-
-#[test]
-fn rerun_if_env_or_file_changes() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.5.0"
- authors = []
- "#)
- .file("src/main.rs", r#"
- fn main() {}
- "#)
- .file("build.rs", r#"
- fn main() {
- println!("cargo:rerun-if-env-changed=FOO");
- println!("cargo:rerun-if-changed=foo");
- }
- "#)
- .file("foo", "")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0)
- .with_stderr("\
-[COMPILING] foo v0.5.0 ([..])
-[FINISHED] [..]
-"));
- assert_that(p.cargo("build").env("FOO", "bar"),
- execs().with_status(0)
- .with_stderr("\
-[COMPILING] foo v0.5.0 ([..])
-[FINISHED] [..]
-"));
- assert_that(p.cargo("build").env("FOO", "bar"),
- execs().with_status(0)
- .with_stderr("\
-[FINISHED] [..]
-"));
- sleep_ms(1000);
- File::create(p.root().join("foo")).unwrap();
- assert_that(p.cargo("build").env("FOO", "bar"),
- execs().with_status(0)
- .with_stderr("\
-[COMPILING] foo v0.5.0 ([..])
-[FINISHED] [..]
-"));
-}
+++ /dev/null
-extern crate cargotest;
-extern crate hamcrest;
-
-use std::env;
-use std::fs::{self, File};
-use std::io::prelude::*;
-use std::path::PathBuf;
-
-use cargotest::{rustc_host, sleep_ms};
-use cargotest::support::{project, execs};
-use cargotest::support::paths::CargoPathExt;
-use cargotest::support::registry::Package;
-use hamcrest::{assert_that, existing_file, existing_dir};
-
-#[test]
-fn custom_build_script_failed() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
-
- name = "foo"
- version = "0.5.0"
- authors = ["wycats@example.com"]
- build = "build.rs"
- "#)
- .file("src/main.rs", r#"
- fn main() {}
- "#)
- .file("build.rs", r#"
- fn main() {
- std::process::exit(101);
- }
- "#)
- .build();
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(101)
- .with_stderr(&format!("\
-[COMPILING] foo v0.5.0 ({url})
-[RUNNING] `rustc --crate-name build_script_build build.rs --crate-type bin [..]`
-[RUNNING] `[..][/]build-script-build`
-[ERROR] failed to run custom build command for `foo v0.5.0 ({url})`
-process didn't exit successfully: `[..][/]build-script-build` (exit code: 101)",
-url = p.url())));
-}
-
-#[test]
-fn custom_build_env_vars() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
-
- name = "foo"
- version = "0.5.0"
- authors = ["wycats@example.com"]
-
- [features]
- bar_feat = ["bar/foo"]
-
- [dependencies.bar]
- path = "bar"
- "#)
- .file("src/main.rs", r#"
- fn main() {}
- "#)
- .file("bar/Cargo.toml", r#"
- [project]
-
- name = "bar"
- version = "0.5.0"
- authors = ["wycats@example.com"]
- build = "build.rs"
-
- [features]
- foo = []
- "#)
- .file("bar/src/lib.rs", r#"
- pub fn hello() {}
- "#);
-
- let file_content = format!(r#"
- use std::env;
- use std::io::prelude::*;
- use std::path::Path;
- use std::fs;
-
- fn main() {{
- let _target = env::var("TARGET").unwrap();
- let _ncpus = env::var("NUM_JOBS").unwrap();
- let _dir = env::var("CARGO_MANIFEST_DIR").unwrap();
-
- let opt = env::var("OPT_LEVEL").unwrap();
- assert_eq!(opt, "0");
-
- let opt = env::var("PROFILE").unwrap();
- assert_eq!(opt, "debug");
-
- let debug = env::var("DEBUG").unwrap();
- assert_eq!(debug, "true");
-
- let out = env::var("OUT_DIR").unwrap();
- assert!(out.starts_with(r"{0}"));
- assert!(fs::metadata(&out).map(|m| m.is_dir()).unwrap_or(false));
-
- let _host = env::var("HOST").unwrap();
-
- let _feat = env::var("CARGO_FEATURE_FOO").unwrap();
-
- let _cargo = env::var("CARGO").unwrap();
-
- let rustc = env::var("RUSTC").unwrap();
- assert_eq!(rustc, "rustc");
-
- let rustdoc = env::var("RUSTDOC").unwrap();
- assert_eq!(rustdoc, "rustdoc");
- }}
- "#,
- p.root().join("target").join("debug").join("build").display());
-
- let p = p.file("bar/build.rs", &file_content).build();
-
- assert_that(p.cargo("build").arg("--features").arg("bar_feat"),
- execs().with_status(0));
-}
-
-#[test]
-fn custom_build_script_wrong_rustc_flags() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
-
- name = "foo"
- version = "0.5.0"
- authors = ["wycats@example.com"]
- build = "build.rs"
- "#)
- .file("src/main.rs", r#"
- fn main() {}
- "#)
- .file("build.rs", r#"
- fn main() {
- println!("cargo:rustc-flags=-aaa -bbb");
- }
- "#)
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(101)
- .with_stderr_contains(&format!("\
-[ERROR] Only `-l` and `-L` flags are allowed in build script of `foo v0.5.0 ({})`: \
-`-aaa -bbb`",
-p.url())));
-}
-
-/*
-#[test]
-fn custom_build_script_rustc_flags() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
-
- name = "bar"
- version = "0.5.0"
- authors = ["wycats@example.com"]
-
- [dependencies.foo]
- path = "foo"
- "#)
- .file("src/main.rs", r#"
- fn main() {}
- "#)
- .file("foo/Cargo.toml", r#"
- [project]
-
- name = "foo"
- version = "0.5.0"
- authors = ["wycats@example.com"]
- build = "build.rs"
- "#)
- .file("foo/src/lib.rs", r#"
- "#)
- .file("foo/build.rs", r#"
- fn main() {
- println!("cargo:rustc-flags=-l nonexistinglib -L /dummy/path1 -L /dummy/path2");
- }
- "#)
- .build();
-
- // TODO: TEST FAILS BECAUSE OF WRONG STDOUT (but otherwise, the build works)
- assert_that(p.cargo("build").arg("--verbose"),
- execs().with_status(101)
- .with_stderr(&format!("\
-[COMPILING] bar v0.5.0 ({url})
-[RUNNING] `rustc --crate-name test {dir}{sep}src{sep}lib.rs --crate-type lib -C debuginfo=2 \
- -C metadata=[..] \
- -C extra-filename=-[..] \
- --out-dir {dir}{sep}target \
- --emit=dep-info,link \
- -L {dir}{sep}target \
- -L {dir}{sep}target{sep}deps`
-", sep = path::SEP,
-dir = p.root().display(),
-url = p.url(),
-)));
-}
-*/
-
-#[test]
-fn links_no_build_cmd() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.5.0"
- authors = []
- links = "a"
- "#)
- .file("src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(101)
- .with_stderr("\
-[ERROR] package `foo v0.5.0 (file://[..])` specifies that it links to `a` but does \
-not have a custom build script
-"));
-}
-
-#[test]
-fn links_duplicates() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.5.0"
- authors = []
- links = "a"
- build = "build.rs"
-
- [dependencies.a-sys]
- path = "a-sys"
- "#)
- .file("src/lib.rs", "")
- .file("build.rs", "")
- .file("a-sys/Cargo.toml", r#"
- [project]
- name = "a-sys"
- version = "0.5.0"
- authors = []
- links = "a"
- build = "build.rs"
- "#)
- .file("a-sys/src/lib.rs", "")
- .file("a-sys/build.rs", "")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(101)
- .with_stderr("\
-[ERROR] multiple packages link to native library `a`, but a native library can \
-be linked only once
-
-package `foo v0.5.0 ([..])`
-links to native library `a`
-
-package `a-sys v0.5.0 ([..])`
- ... which is depended on by `foo v0.5.0 ([..])`
-also links to native library `a`
-"));
-}
-
-#[test]
-fn links_duplicates_deep_dependency() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.5.0"
- authors = []
- links = "a"
- build = "build.rs"
-
- [dependencies.a]
- path = "a"
- "#)
- .file("src/lib.rs", "")
- .file("build.rs", "")
- .file("a/Cargo.toml", r#"
- [project]
- name = "a"
- version = "0.5.0"
- authors = []
- build = "build.rs"
-
- [dependencies.a-sys]
- path = "a-sys"
- "#)
- .file("a/src/lib.rs", "")
- .file("a/build.rs", "")
- .file("a/a-sys/Cargo.toml", r#"
- [project]
- name = "a-sys"
- version = "0.5.0"
- authors = []
- links = "a"
- build = "build.rs"
- "#)
- .file("a/a-sys/src/lib.rs", "")
- .file("a/a-sys/build.rs", "")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(101)
- .with_stderr("\
-[ERROR] multiple packages link to native library `a`, but a native library can \
-be linked only once
-
-package `foo v0.5.0 ([..])`
-links to native library `a`
-
-package `a-sys v0.5.0 ([..])`
- ... which is depended on by `a v0.5.0 ([..])`
- ... which is depended on by `foo v0.5.0 ([..])`
-also links to native library `a`
-"));
-}
-
-#[test]
-fn overrides_and_links() {
- let target = rustc_host();
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.5.0"
- authors = []
- build = "build.rs"
-
- [dependencies.a]
- path = "a"
- "#)
- .file("src/lib.rs", "")
- .file("build.rs", r#"
- use std::env;
- fn main() {
- assert_eq!(env::var("DEP_FOO_FOO").ok().expect("FOO missing"),
- "bar");
- assert_eq!(env::var("DEP_FOO_BAR").ok().expect("BAR missing"),
- "baz");
- }
- "#)
- .file(".cargo/config", &format!(r#"
- [target.{}.foo]
- rustc-flags = "-L foo -L bar"
- foo = "bar"
- bar = "baz"
- "#, target))
- .file("a/Cargo.toml", r#"
- [project]
- name = "a"
- version = "0.5.0"
- authors = []
- links = "foo"
- build = "build.rs"
- "#)
- .file("a/src/lib.rs", "")
- .file("a/build.rs", "not valid rust code")
- .build();
-
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(0)
- .with_stderr("\
-[..]
-[..]
-[..]
-[..]
-[..]
-[RUNNING] `rustc --crate-name foo [..] -L foo -L bar`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-}
-
-#[test]
-fn unused_overrides() {
- let target = rustc_host();
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.5.0"
- authors = []
- build = "build.rs"
- "#)
- .file("src/lib.rs", "")
- .file("build.rs", "fn main() {}")
- .file(".cargo/config", &format!(r#"
- [target.{}.foo]
- rustc-flags = "-L foo -L bar"
- foo = "bar"
- bar = "baz"
- "#, target))
- .build();
-
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(0));
-}
-
-#[test]
-fn links_passes_env_vars() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.5.0"
- authors = []
- build = "build.rs"
-
- [dependencies.a]
- path = "a"
- "#)
- .file("src/lib.rs", "")
- .file("build.rs", r#"
- use std::env;
- fn main() {
- assert_eq!(env::var("DEP_FOO_FOO").unwrap(), "bar");
- assert_eq!(env::var("DEP_FOO_BAR").unwrap(), "baz");
- }
- "#)
- .file("a/Cargo.toml", r#"
- [project]
- name = "a"
- version = "0.5.0"
- authors = []
- links = "foo"
- build = "build.rs"
- "#)
- .file("a/src/lib.rs", "")
- .file("a/build.rs", r#"
- use std::env;
- fn main() {
- let lib = env::var("CARGO_MANIFEST_LINKS").unwrap();
- assert_eq!(lib, "foo");
-
- println!("cargo:foo=bar");
- println!("cargo:bar=baz");
- }
- "#)
- .build();
-
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(0));
-}
-
-#[test]
-fn only_rerun_build_script() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.5.0"
- authors = []
- build = "build.rs"
- "#)
- .file("src/lib.rs", "")
- .file("build.rs", r#"
- fn main() {}
- "#)
- .build();
-
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(0));
- p.root().move_into_the_past();
-
- File::create(&p.root().join("some-new-file")).unwrap();
- p.root().move_into_the_past();
-
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(0)
- .with_stderr("\
-[COMPILING] foo v0.5.0 (file://[..])
-[RUNNING] `[..][/]build-script-build`
-[RUNNING] `rustc --crate-name foo [..]`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-}
-
-#[test]
-fn rebuild_continues_to_pass_env_vars() {
- let a = project("a")
- .file("Cargo.toml", r#"
- [project]
- name = "a"
- version = "0.5.0"
- authors = []
- links = "foo"
- build = "build.rs"
- "#)
- .file("src/lib.rs", "")
- .file("build.rs", r#"
- use std::time::Duration;
- fn main() {
- println!("cargo:foo=bar");
- println!("cargo:bar=baz");
- std::thread::sleep(Duration::from_millis(500));
- }
- "#)
- .build();
- a.root().move_into_the_past();
-
- let p = project("foo")
- .file("Cargo.toml", &format!(r#"
- [project]
- name = "foo"
- version = "0.5.0"
- authors = []
- build = "build.rs"
-
- [dependencies.a]
- path = '{}'
- "#, a.root().display()))
- .file("src/lib.rs", "")
- .file("build.rs", r#"
- use std::env;
- fn main() {
- assert_eq!(env::var("DEP_FOO_FOO").unwrap(), "bar");
- assert_eq!(env::var("DEP_FOO_BAR").unwrap(), "baz");
- }
- "#)
- .build();
-
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(0));
- p.root().move_into_the_past();
-
- File::create(&p.root().join("some-new-file")).unwrap();
- p.root().move_into_the_past();
-
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(0));
-}
-
-#[test]
-fn testing_and_such() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.5.0"
- authors = []
- build = "build.rs"
- "#)
- .file("src/lib.rs", "")
- .file("build.rs", r#"
- fn main() {}
- "#)
- .build();
-
- println!("build");
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(0));
- p.root().move_into_the_past();
-
- File::create(&p.root().join("src/lib.rs")).unwrap();
- p.root().move_into_the_past();
-
- println!("test");
- assert_that(p.cargo("test").arg("-vj1"),
- execs().with_status(0)
- .with_stderr("\
-[COMPILING] foo v0.5.0 (file://[..])
-[RUNNING] `[..][/]build-script-build`
-[RUNNING] `rustc --crate-name foo [..]`
-[RUNNING] `rustc --crate-name foo [..]`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] `[..][/]foo-[..][EXE]`
-[DOCTEST] foo
-[RUNNING] `rustdoc --test [..]`")
- .with_stdout_contains_n("running 0 tests", 2));
-
- println!("doc");
- assert_that(p.cargo("doc").arg("-v"),
- execs().with_status(0)
- .with_stderr("\
-[DOCUMENTING] foo v0.5.0 (file://[..])
-[RUNNING] `rustdoc [..]`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-
- File::create(&p.root().join("src/main.rs")).unwrap()
- .write_all(b"fn main() {}").unwrap();
- println!("run");
- assert_that(p.cargo("run"),
- execs().with_status(0)
- .with_stderr("\
-[COMPILING] foo v0.5.0 (file://[..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] `target[/]debug[/]foo[EXE]`
-"));
-}
-
-#[test]
-fn propagation_of_l_flags() {
- let target = rustc_host();
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.5.0"
- authors = []
- [dependencies.a]
- path = "a"
- "#)
- .file("src/lib.rs", "")
- .file("a/Cargo.toml", r#"
- [project]
- name = "a"
- version = "0.5.0"
- authors = []
- links = "bar"
- build = "build.rs"
-
- [dependencies.b]
- path = "../b"
- "#)
- .file("a/src/lib.rs", "")
- .file("a/build.rs", r#"
- fn main() {
- println!("cargo:rustc-flags=-L bar");
- }
- "#)
- .file("b/Cargo.toml", r#"
- [project]
- name = "b"
- version = "0.5.0"
- authors = []
- links = "foo"
- build = "build.rs"
- "#)
- .file("b/src/lib.rs", "")
- .file("b/build.rs", "bad file")
- .file(".cargo/config", &format!(r#"
- [target.{}.foo]
- rustc-flags = "-L foo"
- "#, target))
- .build();
-
- assert_that(p.cargo("build").arg("-v").arg("-j1"),
- execs().with_status(0)
- .with_stderr_contains("\
-[RUNNING] `rustc --crate-name a [..] -L bar[..]-L foo[..]`
-[COMPILING] foo v0.5.0 (file://[..])
-[RUNNING] `rustc --crate-name foo [..] -L bar -L foo`
-"));
-}
-
-#[test]
-fn propagation_of_l_flags_new() {
- let target = rustc_host();
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.5.0"
- authors = []
- [dependencies.a]
- path = "a"
- "#)
- .file("src/lib.rs", "")
- .file("a/Cargo.toml", r#"
- [project]
- name = "a"
- version = "0.5.0"
- authors = []
- links = "bar"
- build = "build.rs"
-
- [dependencies.b]
- path = "../b"
- "#)
- .file("a/src/lib.rs", "")
- .file("a/build.rs", r#"
- fn main() {
- println!("cargo:rustc-link-search=bar");
- }
- "#)
- .file("b/Cargo.toml", r#"
- [project]
- name = "b"
- version = "0.5.0"
- authors = []
- links = "foo"
- build = "build.rs"
- "#)
- .file("b/src/lib.rs", "")
- .file("b/build.rs", "bad file")
- .file(".cargo/config", &format!(r#"
- [target.{}.foo]
- rustc-link-search = ["foo"]
- "#, target))
- .build();
-
- assert_that(p.cargo("build").arg("-v").arg("-j1"),
- execs().with_status(0)
- .with_stderr_contains("\
-[RUNNING] `rustc --crate-name a [..] -L bar[..]-L foo[..]`
-[COMPILING] foo v0.5.0 (file://[..])
-[RUNNING] `rustc --crate-name foo [..] -L bar -L foo`
-"));
-}
-
-#[test]
-fn build_deps_simple() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.5.0"
- authors = []
- build = "build.rs"
- [build-dependencies.a]
- path = "a"
- "#)
- .file("src/lib.rs", "")
- .file("build.rs", "
- #[allow(unused_extern_crates)]
- extern crate a;
- fn main() {}
- ")
- .file("a/Cargo.toml", r#"
- [project]
- name = "a"
- version = "0.5.0"
- authors = []
- "#)
- .file("a/src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(0)
- .with_stderr("\
-[COMPILING] a v0.5.0 (file://[..])
-[RUNNING] `rustc --crate-name a [..]`
-[COMPILING] foo v0.5.0 (file://[..])
-[RUNNING] `rustc [..] build.rs [..] --extern a=[..]`
-[RUNNING] `[..][/]foo-[..][/]build-script-build`
-[RUNNING] `rustc --crate-name foo [..]`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-}
-
-#[test]
-fn build_deps_not_for_normal() {
- let target = rustc_host();
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.5.0"
- authors = []
- build = "build.rs"
- [build-dependencies.aaaaa]
- path = "a"
- "#)
- .file("src/lib.rs", "#[allow(unused_extern_crates)] extern crate aaaaa;")
- .file("build.rs", "
- #[allow(unused_extern_crates)]
- extern crate aaaaa;
- fn main() {}
- ")
- .file("a/Cargo.toml", r#"
- [project]
- name = "aaaaa"
- version = "0.5.0"
- authors = []
- "#)
- .file("a/src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build").arg("-v").arg("--target").arg(&target),
- execs().with_status(101)
- .with_stderr_contains("\
-[..]can't find crate for `aaaaa`[..]
-")
- .with_stderr_contains("\
-[ERROR] Could not compile `foo`.
-
-Caused by:
- process didn't exit successfully: [..]
-"));
-}
-
-#[test]
-fn build_cmd_with_a_build_cmd() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.5.0"
- authors = []
- build = "build.rs"
-
- [build-dependencies.a]
- path = "a"
- "#)
- .file("src/lib.rs", "")
- .file("build.rs", "
- #[allow(unused_extern_crates)]
- extern crate a;
- fn main() {}
- ")
- .file("a/Cargo.toml", r#"
- [project]
- name = "a"
- version = "0.5.0"
- authors = []
- build = "build.rs"
-
- [build-dependencies.b]
- path = "../b"
- "#)
- .file("a/src/lib.rs", "")
- .file("a/build.rs", "#[allow(unused_extern_crates)] extern crate b; fn main() {}")
- .file("b/Cargo.toml", r#"
- [project]
- name = "b"
- version = "0.5.0"
- authors = []
- "#)
- .file("b/src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(0)
- .with_stderr("\
-[COMPILING] b v0.5.0 (file://[..])
-[RUNNING] `rustc --crate-name b [..]`
-[COMPILING] a v0.5.0 (file://[..])
-[RUNNING] `rustc [..] a[/]build.rs [..] --extern b=[..]`
-[RUNNING] `[..][/]a-[..][/]build-script-build`
-[RUNNING] `rustc --crate-name a [..]lib.rs --crate-type lib \
- --emit=dep-info,link -C debuginfo=2 \
- -C metadata=[..] \
- --out-dir [..]target[/]debug[/]deps \
- -L [..]target[/]debug[/]deps`
-[COMPILING] foo v0.5.0 (file://[..])
-[RUNNING] `rustc --crate-name build_script_build build.rs --crate-type bin \
- --emit=dep-info,link \
- -C debuginfo=2 -C metadata=[..] --out-dir [..] \
- -L [..]target[/]debug[/]deps \
- --extern a=[..]liba[..].rlib`
-[RUNNING] `[..][/]foo-[..][/]build-script-build`
-[RUNNING] `rustc --crate-name foo [..]lib.rs --crate-type lib \
- --emit=dep-info,link -C debuginfo=2 \
- -C metadata=[..] \
- --out-dir [..] \
- -L [..]target[/]debug[/]deps`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-}
-
-#[test]
-fn out_dir_is_preserved() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.5.0"
- authors = []
- build = "build.rs"
- "#)
- .file("src/lib.rs", "")
- .file("build.rs", r#"
- use std::env;
- use std::fs::File;
- use std::path::Path;
- fn main() {
- let out = env::var("OUT_DIR").unwrap();
- File::create(Path::new(&out).join("foo")).unwrap();
- }
- "#)
- .build();
-
- // Make the file
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(0));
- p.root().move_into_the_past();
-
- // Change to asserting that it's there
- File::create(&p.root().join("build.rs")).unwrap().write_all(br#"
- use std::env;
- use std::old_io::File;
- fn main() {
- let out = env::var("OUT_DIR").unwrap();
- File::open(&Path::new(&out).join("foo")).unwrap();
- }
- "#).unwrap();
- p.root().move_into_the_past();
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(0));
-
- // Run a fresh build where file should be preserved
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(0));
-
- // One last time to make sure it's still there.
- File::create(&p.root().join("foo")).unwrap();
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(0));
-}
-
-#[test]
-fn output_separate_lines() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.5.0"
- authors = []
- build = "build.rs"
- "#)
- .file("src/lib.rs", "")
- .file("build.rs", r#"
- fn main() {
- println!("cargo:rustc-flags=-L foo");
- println!("cargo:rustc-flags=-l static=foo");
- }
- "#)
- .build();
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(101)
- .with_stderr_contains("\
-[COMPILING] foo v0.5.0 (file://[..])
-[RUNNING] `rustc [..] build.rs [..]`
-[RUNNING] `[..][/]foo-[..][/]build-script-build`
-[RUNNING] `rustc --crate-name foo [..] -L foo -l static=foo`
-[ERROR] could not find native static library [..]
-"));
-}
-
-#[test]
-fn output_separate_lines_new() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.5.0"
- authors = []
- build = "build.rs"
- "#)
- .file("src/lib.rs", "")
- .file("build.rs", r#"
- fn main() {
- println!("cargo:rustc-link-search=foo");
- println!("cargo:rustc-link-lib=static=foo");
- }
- "#)
- .build();
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(101)
- .with_stderr_contains("\
-[COMPILING] foo v0.5.0 (file://[..])
-[RUNNING] `rustc [..] build.rs [..]`
-[RUNNING] `[..][/]foo-[..][/]build-script-build`
-[RUNNING] `rustc --crate-name foo [..] -L foo -l static=foo`
-[ERROR] could not find native static library [..]
-"));
-}
-
-#[cfg(not(windows))] // FIXME(#867)
-#[test]
-fn code_generation() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.5.0"
- authors = []
- build = "build.rs"
- "#)
- .file("src/main.rs", r#"
- include!(concat!(env!("OUT_DIR"), "/hello.rs"));
-
- fn main() {
- println!("{}", message());
- }
- "#)
- .file("build.rs", r#"
- use std::env;
- use std::fs::File;
- use std::io::prelude::*;
- use std::path::PathBuf;
-
- fn main() {
- let dst = PathBuf::from(env::var("OUT_DIR").unwrap());
- let mut f = File::create(&dst.join("hello.rs")).unwrap();
- f.write_all(b"
- pub fn message() -> &'static str {
- \"Hello, World!\"
- }
- ").unwrap();
- }
- "#)
- .build();
-
- assert_that(p.cargo("run"),
- execs().with_status(0)
- .with_stderr("\
-[COMPILING] foo v0.5.0 (file://[..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] `target[/]debug[/]foo`")
- .with_stdout("\
-Hello, World!
-"));
-
- assert_that(p.cargo("test"),
- execs().with_status(0));
-}
-
-#[test]
-fn release_with_build_script() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.5.0"
- authors = []
- build = "build.rs"
- "#)
- .file("src/lib.rs", "")
- .file("build.rs", r#"
- fn main() {}
- "#)
- .build();
-
- assert_that(p.cargo("build").arg("-v").arg("--release"),
- execs().with_status(0));
-}
-
-#[test]
-fn build_script_only() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.0"
- authors = []
- build = "build.rs"
- "#)
- .file("build.rs", r#"fn main() {}"#)
- .build();
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(101)
- .with_stderr("\
-[ERROR] failed to parse manifest at `[..]`
-
-Caused by:
- no targets specified in the manifest
- either src/lib.rs, src/main.rs, a [lib] section, or [[bin]] section must be present"));
-}
-
-#[test]
-fn shared_dep_with_a_build_script() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.5.0"
- authors = []
- build = "build.rs"
-
- [dependencies.a]
- path = "a"
-
- [build-dependencies.b]
- path = "b"
- "#)
- .file("src/lib.rs", "")
- .file("build.rs", "fn main() {}")
- .file("a/Cargo.toml", r#"
- [package]
- name = "a"
- version = "0.5.0"
- authors = []
- build = "build.rs"
- "#)
- .file("a/build.rs", "fn main() {}")
- .file("a/src/lib.rs", "")
- .file("b/Cargo.toml", r#"
- [package]
- name = "b"
- version = "0.5.0"
- authors = []
-
- [dependencies.a]
- path = "../a"
- "#)
- .file("b/src/lib.rs", "")
- .build();
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(0));
-}
-
-#[test]
-fn transitive_dep_host() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.5.0"
- authors = []
- build = "build.rs"
-
- [build-dependencies.b]
- path = "b"
- "#)
- .file("src/lib.rs", "")
- .file("build.rs", "fn main() {}")
- .file("a/Cargo.toml", r#"
- [package]
- name = "a"
- version = "0.5.0"
- authors = []
- links = "foo"
- build = "build.rs"
- "#)
- .file("a/build.rs", "fn main() {}")
- .file("a/src/lib.rs", "")
- .file("b/Cargo.toml", r#"
- [package]
- name = "b"
- version = "0.5.0"
- authors = []
-
- [lib]
- name = "b"
- plugin = true
-
- [dependencies.a]
- path = "../a"
- "#)
- .file("b/src/lib.rs", "")
- .build();
- assert_that(p.cargo("build"),
- execs().with_status(0));
-}
-
-#[test]
-fn test_a_lib_with_a_build_command() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.5.0"
- authors = []
- build = "build.rs"
- "#)
- .file("src/lib.rs", r#"
- include!(concat!(env!("OUT_DIR"), "/foo.rs"));
-
- /// ```
- /// foo::bar();
- /// ```
- pub fn bar() {
- assert_eq!(foo(), 1);
- }
- "#)
- .file("build.rs", r#"
- use std::env;
- use std::io::prelude::*;
- use std::fs::File;
- use std::path::PathBuf;
-
- fn main() {
- let out = PathBuf::from(env::var("OUT_DIR").unwrap());
- File::create(out.join("foo.rs")).unwrap().write_all(b"
- fn foo() -> i32 { 1 }
- ").unwrap();
- }
- "#)
- .build();
- assert_that(p.cargo("test"),
- execs().with_status(0));
-}
-
-#[test]
-fn test_dev_dep_build_script() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.5.0"
- authors = []
-
- [dev-dependencies.a]
- path = "a"
- "#)
- .file("src/lib.rs", "")
- .file("a/Cargo.toml", r#"
- [project]
- name = "a"
- version = "0.5.0"
- authors = []
- build = "build.rs"
- "#)
- .file("a/build.rs", "fn main() {}")
- .file("a/src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("test"), execs().with_status(0));
-}
-
-#[test]
-fn build_script_with_dynamic_native_dependency() {
-
- let _workspace = project("ws")
- .file("Cargo.toml", r#"
- [workspace]
- members = ["builder", "foo"]
- "#)
- .build();
-
- let build = project("ws/builder")
- .file("Cargo.toml", r#"
- [package]
- name = "builder"
- version = "0.0.1"
- authors = []
-
- [lib]
- name = "builder"
- crate-type = ["dylib"]
- plugin = true
- "#)
- .file("src/lib.rs", r#"
- #[no_mangle]
- pub extern fn foo() {}
- "#)
- .build();
-
- let foo = project("ws/foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- build = "build.rs"
-
- [build-dependencies.bar]
- path = "bar"
- "#)
- .file("build.rs", r#"
- extern crate bar;
- fn main() { bar::bar() }
- "#)
- .file("src/lib.rs", "")
- .file("bar/Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
- build = "build.rs"
- "#)
- .file("bar/build.rs", r#"
- use std::env;
- use std::path::PathBuf;
-
- fn main() {
- let src = PathBuf::from(env::var("SRC").unwrap());
- println!("cargo:rustc-link-search=native={}/target/debug/deps",
- src.display());
- }
- "#)
- .file("bar/src/lib.rs", r#"
- pub fn bar() {
- #[cfg_attr(not(target_env = "msvc"), link(name = "builder"))]
- #[cfg_attr(target_env = "msvc", link(name = "builder.dll"))]
- extern { fn foo(); }
- unsafe { foo() }
- }
- "#)
- .build();
-
- assert_that(build.cargo("build").arg("-v")
- .env("RUST_LOG", "cargo::ops::cargo_rustc"),
- execs().with_status(0));
-
- assert_that(foo.cargo("build").arg("-v").env("SRC", build.root())
- .env("RUST_LOG", "cargo::ops::cargo_rustc"),
- execs().with_status(0));
-}
-
-#[test]
-fn profile_and_opt_level_set_correctly() {
- let build = project("builder")
- .file("Cargo.toml", r#"
- [package]
- name = "builder"
- version = "0.0.1"
- authors = []
- build = "build.rs"
- "#)
- .file("src/lib.rs", "")
- .file("build.rs", r#"
- use std::env;
-
- fn main() {
- assert_eq!(env::var("OPT_LEVEL").unwrap(), "3");
- assert_eq!(env::var("PROFILE").unwrap(), "release");
- assert_eq!(env::var("DEBUG").unwrap(), "false");
- }
- "#)
- .build();
- assert_that(build.cargo("bench"),
- execs().with_status(0));
-}
-
-#[test]
-fn build_script_with_lto() {
- let build = project("builder")
- .file("Cargo.toml", r#"
- [package]
- name = "builder"
- version = "0.0.1"
- authors = []
- build = "build.rs"
-
- [profile.dev]
- lto = true
- "#)
- .file("src/lib.rs", "")
- .file("build.rs", r#"
- fn main() {
- }
- "#)
- .build();
- assert_that(build.cargo("build"),
- execs().with_status(0));
-}
-
-#[test]
-fn test_duplicate_deps() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.1.0"
- authors = []
- build = "build.rs"
-
- [dependencies.bar]
- path = "bar"
-
- [build-dependencies.bar]
- path = "bar"
- "#)
- .file("src/main.rs", r#"
- extern crate bar;
- fn main() { bar::do_nothing() }
- "#)
- .file("build.rs", r#"
- extern crate bar;
- fn main() { bar::do_nothing() }
- "#)
- .file("bar/Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.1.0"
- authors = []
- "#)
- .file("bar/src/lib.rs", "pub fn do_nothing() {}")
- .build();
-
- assert_that(p.cargo("build"), execs().with_status(0));
-}
-
-#[test]
-fn cfg_feedback() {
- let build = project("builder")
- .file("Cargo.toml", r#"
- [package]
- name = "builder"
- version = "0.0.1"
- authors = []
- build = "build.rs"
- "#)
- .file("src/main.rs", "
- #[cfg(foo)]
- fn main() {}
- ")
- .file("build.rs", r#"
- fn main() {
- println!("cargo:rustc-cfg=foo");
- }
- "#)
- .build();
- assert_that(build.cargo("build").arg("-v"),
- execs().with_status(0));
-}
-
-#[test]
-fn cfg_override() {
- let target = rustc_host();
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.5.0"
- authors = []
- links = "a"
- build = "build.rs"
- "#)
- .file("src/main.rs", "
- #[cfg(foo)]
- fn main() {}
- ")
- .file("build.rs", "")
- .file(".cargo/config", &format!(r#"
- [target.{}.a]
- rustc-cfg = ["foo"]
- "#, target))
- .build();
-
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(0));
-}
-
-#[test]
-fn cfg_test() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- build = "build.rs"
- "#)
- .file("build.rs", r#"
- fn main() {
- println!("cargo:rustc-cfg=foo");
- }
- "#)
- .file("src/lib.rs", r#"
- ///
- /// ```
- /// extern crate foo;
- ///
- /// fn main() {
- /// foo::foo()
- /// }
- /// ```
- ///
- #[cfg(foo)]
- pub fn foo() {}
-
- #[cfg(foo)]
- #[test]
- fn test_foo() {
- foo()
- }
- "#)
- .file("tests/test.rs", r#"
- #[cfg(foo)]
- #[test]
- fn test_bar() {}
- "#)
- .build();
- assert_that(p.cargo("test").arg("-v"),
- execs().with_stderr(format!("\
-[COMPILING] foo v0.0.1 ({dir})
-[RUNNING] [..] build.rs [..]
-[RUNNING] `[..][/]build-script-build`
-[RUNNING] [..] --cfg foo[..]
-[RUNNING] [..] --cfg foo[..]
-[RUNNING] [..] --cfg foo[..]
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] `[..][/]foo-[..][EXE]`
-[RUNNING] `[..][/]test-[..][EXE]`
-[DOCTEST] foo
-[RUNNING] [..] --cfg foo[..]", dir = p.url()))
- .with_stdout_contains("test test_foo ... ok")
- .with_stdout_contains("test test_bar ... ok")
- .with_stdout_contains_n("test [..] ... ok", 3));
-}
-
-#[test]
-fn cfg_doc() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- build = "build.rs"
-
- [dependencies.bar]
- path = "bar"
- "#)
- .file("build.rs", r#"
- fn main() {
- println!("cargo:rustc-cfg=foo");
- }
- "#)
- .file("src/lib.rs", r#"
- #[cfg(foo)]
- pub fn foo() {}
- "#)
- .file("bar/Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
- build = "build.rs"
- "#)
- .file("bar/build.rs", r#"
- fn main() {
- println!("cargo:rustc-cfg=bar");
- }
- "#)
- .file("bar/src/lib.rs", r#"
- #[cfg(bar)]
- pub fn bar() {}
- "#)
- .build();
- assert_that(p.cargo("doc"),
- execs().with_status(0));
- assert_that(&p.root().join("target/doc"), existing_dir());
- assert_that(&p.root().join("target/doc/foo/fn.foo.html"), existing_file());
- assert_that(&p.root().join("target/doc/bar/fn.bar.html"), existing_file());
-}
-
-#[test]
-fn cfg_override_test() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- build = "build.rs"
- links = "a"
- "#)
- .file("build.rs", "")
- .file(".cargo/config", &format!(r#"
- [target.{}.a]
- rustc-cfg = ["foo"]
- "#, rustc_host()))
- .file("src/lib.rs", r#"
- ///
- /// ```
- /// extern crate foo;
- ///
- /// fn main() {
- /// foo::foo()
- /// }
- /// ```
- ///
- #[cfg(foo)]
- pub fn foo() {}
-
- #[cfg(foo)]
- #[test]
- fn test_foo() {
- foo()
- }
- "#)
- .file("tests/test.rs", r#"
- #[cfg(foo)]
- #[test]
- fn test_bar() {}
- "#)
- .build();
- assert_that(p.cargo("test").arg("-v"),
- execs().with_stderr(format!("\
-[COMPILING] foo v0.0.1 ({dir})
-[RUNNING] `[..]`
-[RUNNING] `[..]`
-[RUNNING] `[..]`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] `[..][/]foo-[..][EXE]`
-[RUNNING] `[..][/]test-[..][EXE]`
-[DOCTEST] foo
-[RUNNING] [..] --cfg foo[..]", dir = p.url()))
- .with_stdout_contains("test test_foo ... ok")
- .with_stdout_contains("test test_bar ... ok")
- .with_stdout_contains_n("test [..] ... ok", 3));
-}
-
-#[test]
-fn cfg_override_doc() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- build = "build.rs"
- links = "a"
-
- [dependencies.bar]
- path = "bar"
- "#)
- .file(".cargo/config", &format!(r#"
- [target.{target}.a]
- rustc-cfg = ["foo"]
- [target.{target}.b]
- rustc-cfg = ["bar"]
- "#, target = rustc_host()))
- .file("build.rs", "")
- .file("src/lib.rs", r#"
- #[cfg(foo)]
- pub fn foo() {}
- "#)
- .file("bar/Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
- build = "build.rs"
- links = "b"
- "#)
- .file("bar/build.rs", "")
- .file("bar/src/lib.rs", r#"
- #[cfg(bar)]
- pub fn bar() {}
- "#)
- .build();
- assert_that(p.cargo("doc"),
- execs().with_status(0));
- assert_that(&p.root().join("target/doc"), existing_dir());
- assert_that(&p.root().join("target/doc/foo/fn.foo.html"), existing_file());
- assert_that(&p.root().join("target/doc/bar/fn.bar.html"), existing_file());
-}
-
-#[test]
-fn env_build() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- build = "build.rs"
- "#)
- .file("src/main.rs", r#"
- const FOO: &'static str = env!("FOO");
- fn main() {
- println!("{}", FOO);
- }
- "#)
- .file("build.rs", r#"
- fn main() {
- println!("cargo:rustc-env=FOO=foo");
- }
- "#)
- .build();
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(0));
- assert_that(p.cargo("run").arg("-v"),
- execs().with_status(0).with_stdout("foo\n"));
-}
-
-#[test]
-fn env_test() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- build = "build.rs"
- "#)
- .file("build.rs", r#"
- fn main() {
- println!("cargo:rustc-env=FOO=foo");
- }
- "#)
- .file("src/lib.rs", r#"
- pub const FOO: &'static str = env!("FOO");
- "#)
- .file("tests/test.rs", r#"
- extern crate foo;
-
- #[test]
- fn test_foo() {
- assert_eq!("foo", foo::FOO);
- }
- "#)
- .build();
- assert_that(p.cargo("test").arg("-v"),
- execs().with_stderr(format!("\
-[COMPILING] foo v0.0.1 ({dir})
-[RUNNING] [..] build.rs [..]
-[RUNNING] `[..][/]build-script-build`
-[RUNNING] [..] --crate-name foo[..]
-[RUNNING] [..] --crate-name foo[..]
-[RUNNING] [..] --crate-name test[..]
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] `[..][/]foo-[..][EXE]`
-[RUNNING] `[..][/]test-[..][EXE]`
-[DOCTEST] foo
-[RUNNING] [..] --crate-name foo[..]", dir = p.url()))
- .with_stdout_contains_n("running 0 tests", 2)
- .with_stdout_contains("test test_foo ... ok"));
-}
-
-#[test]
-fn env_doc() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- build = "build.rs"
- "#)
- .file("src/main.rs", r#"
- const FOO: &'static str = env!("FOO");
- fn main() {}
- "#)
- .file("build.rs", r#"
- fn main() {
- println!("cargo:rustc-env=FOO=foo");
- }
- "#)
- .build();
- assert_that(p.cargo("doc").arg("-v"),
- execs().with_status(0));
-}
-
-#[test]
-fn flags_go_into_tests() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.5.0"
- authors = []
-
- [dependencies]
- b = { path = "b" }
- "#)
- .file("src/lib.rs", "")
- .file("tests/foo.rs", "")
- .file("b/Cargo.toml", r#"
- [project]
- name = "b"
- version = "0.5.0"
- authors = []
- [dependencies]
- a = { path = "../a" }
- "#)
- .file("b/src/lib.rs", "")
- .file("a/Cargo.toml", r#"
- [project]
- name = "a"
- version = "0.5.0"
- authors = []
- build = "build.rs"
- "#)
- .file("a/src/lib.rs", "")
- .file("a/build.rs", r#"
- fn main() {
- println!("cargo:rustc-link-search=test");
- }
- "#)
- .build();
-
- assert_that(p.cargo("test").arg("-v").arg("--test=foo"),
- execs().with_status(0)
- .with_stderr("\
-[COMPILING] a v0.5.0 ([..]
-[RUNNING] `rustc [..] a[/]build.rs [..]`
-[RUNNING] `[..][/]build-script-build`
-[RUNNING] `rustc [..] a[/]src[/]lib.rs [..] -L test[..]`
-[COMPILING] b v0.5.0 ([..]
-[RUNNING] `rustc [..] b[/]src[/]lib.rs [..] -L test[..]`
-[COMPILING] foo v0.5.0 ([..]
-[RUNNING] `rustc [..] src[/]lib.rs [..] -L test[..]`
-[RUNNING] `rustc [..] tests[/]foo.rs [..] -L test[..]`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] `[..][/]foo-[..][EXE]`")
- .with_stdout_contains("running 0 tests"));
-
- assert_that(p.cargo("test").arg("-v").arg("-pb").arg("--lib"),
- execs().with_status(0)
- .with_stderr("\
-[FRESH] a v0.5.0 ([..]
-[COMPILING] b v0.5.0 ([..]
-[RUNNING] `rustc [..] b[/]src[/]lib.rs [..] -L test[..]`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] `[..][/]b-[..][EXE]`")
- .with_stdout_contains("running 0 tests"));
-}
-
-#[test]
-fn diamond_passes_args_only_once() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.5.0"
- authors = []
-
- [dependencies]
- a = { path = "a" }
- b = { path = "b" }
- "#)
- .file("src/lib.rs", "")
- .file("tests/foo.rs", "")
- .file("a/Cargo.toml", r#"
- [project]
- name = "a"
- version = "0.5.0"
- authors = []
- [dependencies]
- b = { path = "../b" }
- c = { path = "../c" }
- "#)
- .file("a/src/lib.rs", "")
- .file("b/Cargo.toml", r#"
- [project]
- name = "b"
- version = "0.5.0"
- authors = []
- [dependencies]
- c = { path = "../c" }
- "#)
- .file("b/src/lib.rs", "")
- .file("c/Cargo.toml", r#"
- [project]
- name = "c"
- version = "0.5.0"
- authors = []
- build = "build.rs"
- "#)
- .file("c/build.rs", r#"
- fn main() {
- println!("cargo:rustc-link-search=native=test");
- }
- "#)
- .file("c/src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(0).with_stderr("\
-[COMPILING] c v0.5.0 ([..]
-[RUNNING] `rustc [..]`
-[RUNNING] `[..]`
-[RUNNING] `rustc [..]`
-[COMPILING] b v0.5.0 ([..]
-[RUNNING] `rustc [..]`
-[COMPILING] a v0.5.0 ([..]
-[RUNNING] `rustc [..]`
-[COMPILING] foo v0.5.0 ([..]
-[RUNNING] `[..]rlib -L native=test`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-}
-
-#[test]
-fn adding_an_override_invalidates() {
- let target = rustc_host();
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.5.0"
- authors = []
- links = "foo"
- build = "build.rs"
- "#)
- .file("src/lib.rs", "")
- .file(".cargo/config", "")
- .file("build.rs", r#"
- fn main() {
- println!("cargo:rustc-link-search=native=foo");
- }
- "#)
- .build();
-
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(0).with_stderr("\
-[COMPILING] foo v0.5.0 ([..]
-[RUNNING] `rustc [..]`
-[RUNNING] `[..]`
-[RUNNING] `rustc [..] -L native=foo`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-
- File::create(p.root().join(".cargo/config")).unwrap().write_all(format!("
- [target.{}.foo]
- rustc-link-search = [\"native=bar\"]
- ", target).as_bytes()).unwrap();
-
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(0).with_stderr("\
-[COMPILING] foo v0.5.0 ([..]
-[RUNNING] `rustc [..] -L native=bar`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-}
-
-#[test]
-fn changing_an_override_invalidates() {
- let target = rustc_host();
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.5.0"
- authors = []
- links = "foo"
- build = "build.rs"
- "#)
- .file("src/lib.rs", "")
- .file(".cargo/config", &format!("
- [target.{}.foo]
- rustc-link-search = [\"native=foo\"]
- ", target))
- .file("build.rs", "")
- .build();
-
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(0).with_stderr("\
-[COMPILING] foo v0.5.0 ([..]
-[RUNNING] `rustc [..] -L native=foo`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-
- File::create(p.root().join(".cargo/config")).unwrap().write_all(format!("
- [target.{}.foo]
- rustc-link-search = [\"native=bar\"]
- ", target).as_bytes()).unwrap();
-
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(0).with_stderr("\
-[COMPILING] foo v0.5.0 ([..]
-[RUNNING] `rustc [..] -L native=bar`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-}
-
-
-#[test]
-fn fresh_builds_possible_with_link_libs() {
- // The bug is non-deterministic. Sometimes you can get a fresh build
- let target = rustc_host();
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.5.0"
- authors = []
- links = "nativefoo"
- build = "build.rs"
- "#)
- .file("src/lib.rs", "")
- .file(".cargo/config", &format!("
- [target.{}.nativefoo]
- rustc-link-lib = [\"a\"]
- rustc-link-search = [\"./b\"]
- rustc-flags = \"-l z -L ./\"
- ", target))
- .file("build.rs", "")
- .build();
-
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(0).with_stderr("\
-[COMPILING] foo v0.5.0 ([..]
-[RUNNING] `rustc [..]`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-
- assert_that(p.cargo("build")
- .arg("-v")
- .env("RUST_LOG", "cargo::ops::cargo_rustc::fingerprint=info"),
- execs().with_status(0).with_stderr("\
-[FRESH] foo v0.5.0 ([..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-}
-
-
-#[test]
-fn fresh_builds_possible_with_multiple_metadata_overrides() {
- // The bug is non-deterministic. Sometimes you can get a fresh build
- let target = rustc_host();
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.5.0"
- authors = []
- links = "foo"
- build = "build.rs"
- "#)
- .file("src/lib.rs", "")
- .file(".cargo/config", &format!("
- [target.{}.foo]
- a = \"\"
- b = \"\"
- c = \"\"
- d = \"\"
- e = \"\"
- ", target))
- .file("build.rs", "")
- .build();
-
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(0).with_stderr("\
-[COMPILING] foo v0.5.0 ([..]
-[RUNNING] `rustc [..]`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-
- assert_that(p.cargo("build")
- .arg("-v")
- .env("RUST_LOG", "cargo::ops::cargo_rustc::fingerprint=info"),
- execs().with_status(0).with_stderr("\
-[FRESH] foo v0.5.0 ([..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-}
-
-
-#[test]
-fn rebuild_only_on_explicit_paths() {
- let p = project("a")
- .file("Cargo.toml", r#"
- [project]
- name = "a"
- version = "0.5.0"
- authors = []
- build = "build.rs"
- "#)
- .file("src/lib.rs", "")
- .file("build.rs", r#"
- fn main() {
- println!("cargo:rerun-if-changed=foo");
- println!("cargo:rerun-if-changed=bar");
- }
- "#)
- .build();
-
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(0));
-
- // files don't exist, so should always rerun if they don't exist
- println!("run without");
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(0).with_stderr("\
-[COMPILING] a v0.5.0 ([..])
-[RUNNING] `[..][/]build-script-build`
-[RUNNING] `rustc [..] src[/]lib.rs [..]`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-
- sleep_ms(1000);
- File::create(p.root().join("foo")).unwrap();
- File::create(p.root().join("bar")).unwrap();
-
- // now the exist, so run once, catch the mtime, then shouldn't run again
- println!("run with");
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(0).with_stderr("\
-[COMPILING] a v0.5.0 ([..])
-[RUNNING] `[..][/]build-script-build`
-[RUNNING] `rustc [..] src[/]lib.rs [..]`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-
- println!("run with2");
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(0).with_stderr("\
-[FRESH] a v0.5.0 ([..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-
- sleep_ms(1000);
-
- // random other files do not affect freshness
- println!("run baz");
- File::create(p.root().join("baz")).unwrap();
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(0).with_stderr("\
-[FRESH] a v0.5.0 ([..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-
- // but changing dependent files does
- println!("run foo change");
- File::create(p.root().join("foo")).unwrap();
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(0).with_stderr("\
-[COMPILING] a v0.5.0 ([..])
-[RUNNING] `[..][/]build-script-build`
-[RUNNING] `rustc [..] src[/]lib.rs [..]`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-
- // .. as does deleting a file
- println!("run foo delete");
- fs::remove_file(p.root().join("bar")).unwrap();
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(0).with_stderr("\
-[COMPILING] a v0.5.0 ([..])
-[RUNNING] `[..][/]build-script-build`
-[RUNNING] `rustc [..] src[/]lib.rs [..]`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-}
-
-
-#[test]
-fn doctest_recieves_build_link_args() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.5.0"
- authors = []
- [dependencies.a]
- path = "a"
- "#)
- .file("src/lib.rs", "")
- .file("a/Cargo.toml", r#"
- [project]
- name = "a"
- version = "0.5.0"
- authors = []
- links = "bar"
- build = "build.rs"
- "#)
- .file("a/src/lib.rs", "")
- .file("a/build.rs", r#"
- fn main() {
- println!("cargo:rustc-link-search=native=bar");
- }
- "#)
- .build();
-
- assert_that(p.cargo("test").arg("-v"),
- execs().with_status(0)
- .with_stderr_contains("\
-[RUNNING] `rustdoc --test [..] --crate-name foo [..]-L native=bar[..]`
-"));
-}
-
-#[test]
-fn please_respect_the_dag() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.5.0"
- authors = []
- build = "build.rs"
-
- [dependencies]
- a = { path = 'a' }
- "#)
- .file("src/lib.rs", "")
- .file("build.rs", r#"
- fn main() {
- println!("cargo:rustc-link-search=native=foo");
- }
- "#)
- .file("a/Cargo.toml", r#"
- [project]
- name = "a"
- version = "0.5.0"
- authors = []
- links = "bar"
- build = "build.rs"
- "#)
- .file("a/src/lib.rs", "")
- .file("a/build.rs", r#"
- fn main() {
- println!("cargo:rustc-link-search=native=bar");
- }
- "#)
- .build();
-
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(0)
- .with_stderr_contains("\
-[RUNNING] `rustc [..] -L native=foo -L native=bar[..]`
-"));
-}
-
-#[test]
-fn non_utf8_output() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.5.0"
- authors = []
- build = "build.rs"
- "#)
- .file("build.rs", r#"
- use std::io::prelude::*;
-
- fn main() {
- let mut out = std::io::stdout();
- // print something that's not utf8
- out.write_all(b"\xff\xff\n").unwrap();
-
- // now print some cargo metadata that's utf8
- println!("cargo:rustc-cfg=foo");
-
- // now print more non-utf8
- out.write_all(b"\xff\xff\n").unwrap();
- }
- "#)
- .file("src/main.rs", r#"
- #[cfg(foo)]
- fn main() {}
- "#)
- .build();
-
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(0));
-}
-
-#[test]
-fn custom_target_dir() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.5.0"
- authors = []
-
- [dependencies]
- a = { path = "a" }
- "#)
- .file("src/lib.rs", "")
- .file(".cargo/config", r#"
- [build]
- target-dir = 'test'
- "#)
- .file("a/Cargo.toml", r#"
- [project]
- name = "a"
- version = "0.5.0"
- authors = []
- build = "build.rs"
- "#)
- .file("a/build.rs", "fn main() {}")
- .file("a/src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(0));
-}
-
-#[test]
-fn panic_abort_with_build_scripts() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.5.0"
- authors = []
-
- [profile.release]
- panic = 'abort'
-
- [dependencies]
- a = { path = "a" }
- "#)
- .file("src/lib.rs", "#[allow(unused_extern_crates)] extern crate a;")
- .file("a/Cargo.toml", r#"
- [project]
- name = "a"
- version = "0.5.0"
- authors = []
- build = "build.rs"
-
- [build-dependencies]
- b = { path = "../b" }
- "#)
- .file("a/src/lib.rs", "")
- .file("a/build.rs", "#[allow(unused_extern_crates)] extern crate b; fn main() {}")
- .file("b/Cargo.toml", r#"
- [project]
- name = "b"
- version = "0.5.0"
- authors = []
- "#)
- .file("b/src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build").arg("-v").arg("--release"),
- execs().with_status(0));
-}
-
-#[test]
-fn warnings_emitted() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.5.0"
- authors = []
- build = "build.rs"
- "#)
- .file("src/lib.rs", "")
- .file("build.rs", r#"
- fn main() {
- println!("cargo:warning=foo");
- println!("cargo:warning=bar");
- }
- "#)
- .build();
-
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(0)
- .with_stderr("\
-[COMPILING] foo v0.5.0 ([..])
-[RUNNING] `rustc [..]`
-[RUNNING] `[..]`
-warning: foo
-warning: bar
-[RUNNING] `rustc [..]`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-}
-
-#[test]
-fn warnings_hidden_for_upstream() {
- Package::new("bar", "0.1.0")
- .file("build.rs", r#"
- fn main() {
- println!("cargo:warning=foo");
- println!("cargo:warning=bar");
- }
- "#)
- .file("Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.1.0"
- authors = []
- build = "build.rs"
- "#)
- .file("src/lib.rs", "")
- .publish();
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.5.0"
- authors = []
-
- [dependencies]
- bar = "*"
- "#)
- .file("src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(0)
- .with_stderr("\
-[UPDATING] registry `[..]`
-[DOWNLOADING] bar v0.1.0 ([..])
-[COMPILING] bar v0.1.0
-[RUNNING] `rustc [..]`
-[RUNNING] `[..]`
-[RUNNING] `rustc [..]`
-[COMPILING] foo v0.5.0 ([..])
-[RUNNING] `rustc [..]`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-}
-
-#[test]
-fn warnings_printed_on_vv() {
- Package::new("bar", "0.1.0")
- .file("build.rs", r#"
- fn main() {
- println!("cargo:warning=foo");
- println!("cargo:warning=bar");
- }
- "#)
- .file("Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.1.0"
- authors = []
- build = "build.rs"
- "#)
- .file("src/lib.rs", "")
- .publish();
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.5.0"
- authors = []
-
- [dependencies]
- bar = "*"
- "#)
- .file("src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build").arg("-vv"),
- execs().with_status(0)
- .with_stderr("\
-[UPDATING] registry `[..]`
-[DOWNLOADING] bar v0.1.0 ([..])
-[COMPILING] bar v0.1.0
-[RUNNING] `rustc [..]`
-[RUNNING] `[..]`
-warning: foo
-warning: bar
-[RUNNING] `rustc [..]`
-[COMPILING] foo v0.5.0 ([..])
-[RUNNING] `rustc [..]`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-}
-
-#[test]
-fn output_shows_on_vv() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.5.0"
- authors = []
- build = "build.rs"
- "#)
- .file("src/lib.rs", "")
- .file("build.rs", r#"
- use std::io::prelude::*;
-
- fn main() {
- std::io::stderr().write_all(b"stderr\n").unwrap();
- std::io::stdout().write_all(b"stdout\n").unwrap();
- }
- "#)
- .build();
-
- assert_that(p.cargo("build").arg("-vv"),
- execs().with_status(0)
- .with_stdout("\
-stdout
-")
- .with_stderr("\
-[COMPILING] foo v0.5.0 ([..])
-[RUNNING] `rustc [..]`
-[RUNNING] `[..]`
-stderr
-[RUNNING] `rustc [..]`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-}
-
-#[test]
-fn links_with_dots() {
- let target = rustc_host();
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.5.0"
- authors = []
- build = "build.rs"
- links = "a.b"
- "#)
- .file("src/lib.rs", "")
- .file("build.rs", r#"
- fn main() {
- println!("cargo:rustc-link-search=bar")
- }
- "#)
- .file(".cargo/config", &format!(r#"
- [target.{}.'a.b']
- rustc-link-search = ["foo"]
- "#, target))
- .build();
-
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(0)
- .with_stderr_contains("\
-[RUNNING] `rustc --crate-name foo [..] [..] -L foo[..]`
-"));
-}
-
-#[test]
-fn rustc_and_rustdoc_set_correctly() {
- let p = project("builder")
- .file("Cargo.toml", r#"
- [package]
- name = "builder"
- version = "0.0.1"
- authors = []
- build = "build.rs"
- "#)
- .file("src/lib.rs", "")
- .file("build.rs", r#"
- use std::env;
-
- fn main() {
- assert_eq!(env::var("RUSTC").unwrap(), "rustc");
- assert_eq!(env::var("RUSTDOC").unwrap(), "rustdoc");
- }
- "#)
- .build();
- assert_that(p.cargo("bench"),
- execs().with_status(0));
-}
-
-#[test]
-fn cfg_env_vars_available() {
- let p = project("builder")
- .file("Cargo.toml", r#"
- [package]
- name = "builder"
- version = "0.0.1"
- authors = []
- build = "build.rs"
- "#)
- .file("src/lib.rs", "")
- .file("build.rs", r#"
- use std::env;
-
- fn main() {
- let fam = env::var("CARGO_CFG_TARGET_FAMILY").unwrap();
- if cfg!(unix) {
- assert_eq!(fam, "unix");
- } else {
- assert_eq!(fam, "windows");
- }
- }
- "#)
- .build();
- assert_that(p.cargo("bench"),
- execs().with_status(0));
-}
-
-#[test]
-fn switch_features_rerun() {
- let p = project("builder")
- .file("Cargo.toml", r#"
- [package]
- name = "builder"
- version = "0.0.1"
- authors = []
- build = "build.rs"
-
- [features]
- foo = []
- "#)
- .file("src/main.rs", r#"
- fn main() {
- println!(include_str!(concat!(env!("OUT_DIR"), "/output")));
- }
- "#)
- .file("build.rs", r#"
- use std::env;
- use std::fs::File;
- use std::io::Write;
- use std::path::Path;
-
- fn main() {
- let out_dir = env::var_os("OUT_DIR").unwrap();
- let out_dir = Path::new(&out_dir).join("output");
- let mut f = File::create(&out_dir).unwrap();
-
- if env::var_os("CARGO_FEATURE_FOO").is_some() {
- f.write_all(b"foo").unwrap();
- } else {
- f.write_all(b"bar").unwrap();
- }
- }
- "#)
- .build();
-
- assert_that(p.cargo("run").arg("-v").arg("--features=foo"),
- execs().with_status(0).with_stdout("foo\n"));
- assert_that(p.cargo("run").arg("-v"),
- execs().with_status(0).with_stdout("bar\n"));
- assert_that(p.cargo("run").arg("-v").arg("--features=foo"),
- execs().with_status(0).with_stdout("foo\n"));
-}
-
-#[test]
-fn assume_build_script_when_build_rs_present() {
- let p = project("builder")
- .file("Cargo.toml", r#"
- [package]
- name = "builder"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/main.rs", r#"
- fn main() {
- if ! cfg!(foo) {
- panic!("the build script was not run");
- }
- }
- "#)
- .file("build.rs", r#"
- fn main() {
- println!("cargo:rustc-cfg=foo");
- }
- "#)
- .build();
-
- assert_that(p.cargo("run").arg("-v"),
- execs().with_status(0));
-}
-
-#[test]
-fn if_build_set_to_false_dont_treat_build_rs_as_build_script() {
- let p = project("builder")
- .file("Cargo.toml", r#"
- [package]
- name = "builder"
- version = "0.0.1"
- authors = []
- build = false
- "#)
- .file("src/main.rs", r#"
- fn main() {
- if cfg!(foo) {
- panic!("the build script was run");
- }
- }
- "#)
- .file("build.rs", r#"
- fn main() {
- println!("cargo:rustc-cfg=foo");
- }
- "#)
- .build();
-
- assert_that(p.cargo("run").arg("-v"),
- execs().with_status(0));
-}
-
-#[test]
-fn deterministic_rustc_dependency_flags() {
- // This bug is non-deterministic hence the large number of dependencies
- // in the hopes it will have a much higher chance of triggering it.
-
- Package::new("dep1", "0.1.0")
- .file("Cargo.toml", r#"
- [project]
- name = "dep1"
- version = "0.1.0"
- authors = []
- build = "build.rs"
- "#)
- .file("build.rs", r#"
- fn main() {
- println!("cargo:rustc-flags=-L native=test1");
- }
- "#)
- .file("src/lib.rs", "")
- .publish();
- Package::new("dep2", "0.1.0")
- .file("Cargo.toml", r#"
- [project]
- name = "dep2"
- version = "0.1.0"
- authors = []
- build = "build.rs"
- "#)
- .file("build.rs", r#"
- fn main() {
- println!("cargo:rustc-flags=-L native=test2");
- }
- "#)
- .file("src/lib.rs", "")
- .publish();
- Package::new("dep3", "0.1.0")
- .file("Cargo.toml", r#"
- [project]
- name = "dep3"
- version = "0.1.0"
- authors = []
- build = "build.rs"
- "#)
- .file("build.rs", r#"
- fn main() {
- println!("cargo:rustc-flags=-L native=test3");
- }
- "#)
- .file("src/lib.rs", "")
- .publish();
- Package::new("dep4", "0.1.0")
- .file("Cargo.toml", r#"
- [project]
- name = "dep4"
- version = "0.1.0"
- authors = []
- build = "build.rs"
- "#)
- .file("build.rs", r#"
- fn main() {
- println!("cargo:rustc-flags=-L native=test4");
- }
- "#)
- .file("src/lib.rs", "")
- .publish();
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.1.0"
- authors = []
-
- [dependencies]
- dep1 = "*"
- dep2 = "*"
- dep3 = "*"
- dep4 = "*"
- "#)
- .file("src/main.rs", r#"
- fn main() {}
- "#)
- .build();
-
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(0)
- .with_stderr_contains("\
-[RUNNING] `rustc --crate-name foo [..] -L native=test1 -L native=test2 \
--L native=test3 -L native=test4`
-"));
-}
-
-#[test]
-fn links_duplicates_with_cycle() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.5.0"
- authors = []
- links = "a"
- build = "build.rs"
-
- [dependencies.a]
- path = "a"
-
- [dev-dependencies]
- b = { path = "b" }
- "#)
- .file("src/lib.rs", "")
- .file("build.rs", "")
- .file("a/Cargo.toml", r#"
- [project]
- name = "a"
- version = "0.5.0"
- authors = []
- links = "a"
- build = "build.rs"
- "#)
- .file("a/src/lib.rs", "")
- .file("a/build.rs", "")
- .file("b/Cargo.toml", r#"
- [project]
- name = "b"
- version = "0.5.0"
- authors = []
-
- [dependencies]
- foo = { path = ".." }
- "#)
- .file("b/src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(101)
- .with_stderr("\
-[ERROR] multiple packages link to native library `a`, but a native library can \
-be linked only once
-
-package `foo v0.5.0 ([..])`
- ... which is depended on by `b v0.5.0 ([..])`
-links to native library `a`
-
-package `a v0.5.0 (file://[..])`
- ... which is depended on by `foo v0.5.0 ([..])`
- ... which is depended on by `b v0.5.0 ([..])`
-also links to native library `a`
-"));
-}
-
-#[test]
-fn rename_with_link_search_path() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.5.0"
- authors = []
-
- [lib]
- crate-type = ["cdylib"]
- "#)
- .file("src/lib.rs", "
- #[no_mangle]
- pub extern fn cargo_test_foo() {}
- ");
- let p = p.build();
-
- assert_that(p.cargo("build"), execs().with_status(0));
-
- let p2 = project("bar")
- .file("Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.5.0"
- authors = []
- "#)
- .file("build.rs", r#"
- use std::env;
- use std::fs;
- use std::path::PathBuf;
-
- fn main() {
- // Move the `libfoo.so` from the root of our project into the
- // build directory. This way Cargo should automatically manage
- // `LD_LIBRARY_PATH` and such.
- let root = PathBuf::from(env::var_os("CARGO_MANIFEST_DIR").unwrap());
- let file = format!("{}foo{}", env::consts::DLL_PREFIX, env::consts::DLL_SUFFIX);
- let src = root.join(&file);
-
- let dst_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
- let dst = dst_dir.join(&file);
-
- fs::copy(&src, &dst).unwrap();
- // handle windows, like below
- drop(fs::copy(root.join("foo.dll.lib"), dst_dir.join("foo.dll.lib")));
-
- println!("cargo:rerun-if-changed=build.rs");
- if cfg!(target_env = "msvc") {
- println!("cargo:rustc-link-lib=foo.dll");
- } else {
- println!("cargo:rustc-link-lib=foo");
- }
- println!("cargo:rustc-link-search={}",
- dst.parent().unwrap().display());
- }
- "#)
- .file("src/main.rs", r#"
- extern {
- #[link_name = "cargo_test_foo"]
- fn foo();
- }
-
- fn main() {
- unsafe { foo(); }
- }
- "#);
- let p2 = p2.build();
-
- // Move the output `libfoo.so` into the directory of `p2`, and then delete
- // the `p` project. On OSX the `libfoo.dylib` artifact references the
- // original path in `p` so we want to make sure that it can't find it (hence
- // the deletion).
- let root = PathBuf::from(p.root());
- let root = root.join("target").join("debug").join("deps");
- let file = format!("{}foo{}", env::consts::DLL_PREFIX, env::consts::DLL_SUFFIX);
- let src = root.join(&file);
-
- let dst = p2.root().join(&file);
-
- fs::copy(&src, &dst).unwrap();
- // copy the import library for windows, if it exists
- drop(fs::copy(&root.join("foo.dll.lib"), p2.root().join("foo.dll.lib")));
- fs::remove_dir_all(p.root()).unwrap();
-
- // Everything should work the first time
- assert_that(p2.cargo("run"),
- execs().with_status(0));
-
- // Now rename the root directory and rerun `cargo run`. Not only should we
- // not build anything but we also shouldn't crash.
- let mut new = p2.root();
- new.pop();
- new.push("bar2");
- fs::rename(p2.root(), &new).unwrap();
- assert_that(p2.cargo("run").cwd(&new),
- execs().with_status(0)
- .with_stderr("\
-[FINISHED] [..]
-[RUNNING] [..]
-"));
-}
+++ /dev/null
-extern crate cargo;
-#[macro_use]
-extern crate cargotest;
-extern crate hamcrest;
-extern crate tempdir;
-
-use std::env;
-use std::fs::{self, File};
-use std::io::prelude::*;
-
-use cargo::util::paths::dylib_path_envvar;
-use cargo::util::{process, ProcessBuilder};
-use cargotest::{is_nightly, rustc_host, sleep_ms};
-use cargotest::support::paths::{CargoPathExt,root};
-use cargotest::support::{ProjectBuilder};
-use cargotest::support::{project, execs, main_file, basic_bin_manifest};
-use cargotest::support::registry::Package;
-use cargotest::ChannelChanger;
-use hamcrest::{assert_that, existing_file, existing_dir, is_not};
-use tempdir::TempDir;
-
-#[test]
-fn cargo_compile_simple() {
- let p = project("foo")
- .file("Cargo.toml", &basic_bin_manifest("foo"))
- .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
- .build();
-
- assert_that(p.cargo("build"), execs().with_status(0));
- assert_that(&p.bin("foo"), existing_file());
-
- assert_that(process(&p.bin("foo")),
- execs().with_status(0).with_stdout("i am foo\n"));
-}
-
-#[test]
-fn cargo_fail_with_no_stderr() {
- let p = project("foo")
- .file("Cargo.toml", &basic_bin_manifest("foo"))
- .file("src/foo.rs", &String::from("refusal"))
- .build();
- assert_that(p.cargo("build").arg("--message-format=json"), execs().with_status(101)
- .with_stderr_does_not_contain("--- stderr"));
-}
-
-/// Check that the `CARGO_INCREMENTAL` environment variable results in
-/// `rustc` getting `-Zincremental` passed to it.
-#[test]
-fn cargo_compile_incremental() {
- if !is_nightly() {
- return
- }
-
- let p = project("foo")
- .file("Cargo.toml", &basic_bin_manifest("foo"))
- .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
- .build();
-
- assert_that(
- p.cargo("build").arg("-v").env("CARGO_INCREMENTAL", "1"),
- execs().with_stderr_contains(
- "[RUNNING] `rustc [..] -C incremental=[..][/]target[/]debug[/]incremental[..]`\n")
- .with_status(0));
-
- assert_that(
- p.cargo("test").arg("-v").env("CARGO_INCREMENTAL", "1"),
- execs().with_stderr_contains(
- "[RUNNING] `rustc [..] -C incremental=[..][/]target[/]debug[/]incremental[..]`\n")
- .with_status(0));
-}
-
-#[test]
-fn incremental_profile() {
- if !is_nightly() {
- return
- }
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
-
- [profile.dev]
- incremental = false
-
- [profile.release]
- incremental = true
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- assert_that(
- p.cargo("build").arg("-v").env_remove("CARGO_INCREMENTAL"),
- execs().with_stderr_does_not_contain("[..]C incremental=[..]")
- .with_status(0));
-
- assert_that(
- p.cargo("build").arg("-v").env("CARGO_INCREMENTAL", "1"),
- execs().with_stderr_contains("[..]C incremental=[..]")
- .with_status(0));
-
- assert_that(
- p.cargo("build").arg("--release").arg("-v").env_remove("CARGO_INCREMENTAL"),
- execs().with_stderr_contains("[..]C incremental=[..]")
- .with_status(0));
-
- assert_that(
- p.cargo("build").arg("--release").arg("-v").env("CARGO_INCREMENTAL", "0"),
- execs().with_stderr_does_not_contain("[..]C incremental=[..]")
- .with_status(0));
-}
-
-#[test]
-fn incremental_config() {
- if !is_nightly() {
- return
- }
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
- "#)
- .file("src/main.rs", "fn main() {}")
- .file(".cargo/config", r#"
- [build]
- incremental = false
- "#)
- .build();
-
- assert_that(
- p.cargo("build").arg("-v").env_remove("CARGO_INCREMENTAL"),
- execs().with_stderr_does_not_contain("[..]C incremental=[..]")
- .with_status(0));
-
- assert_that(
- p.cargo("build").arg("-v").env("CARGO_INCREMENTAL", "1"),
- execs().with_stderr_contains("[..]C incremental=[..]")
- .with_status(0));
-}
-
-#[test]
-fn cargo_compile_manifest_path() {
- let p = project("foo")
- .file("Cargo.toml", &basic_bin_manifest("foo"))
- .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
- .build();
-
- assert_that(p.cargo("build")
- .arg("--manifest-path").arg("foo/Cargo.toml")
- .cwd(p.root().parent().unwrap()),
- execs().with_status(0));
- assert_that(&p.bin("foo"), existing_file());
-}
-
-#[test]
-fn cargo_compile_with_invalid_manifest() {
- let p = project("foo")
- .file("Cargo.toml", "")
- .build();
-
- assert_that(p.cargo("build"),
- execs()
- .with_status(101)
- .with_stderr("\
-[ERROR] failed to parse manifest at `[..]`
-
-Caused by:
- virtual manifests must be configured with [workspace]
-"))
-}
-
-#[test]
-fn cargo_compile_with_invalid_manifest2() {
- let p = project("foo")
- .file("Cargo.toml", r"
- [project]
- foo = bar
- ")
- .build();
-
- assert_that(p.cargo("build"),
- execs()
- .with_status(101)
- .with_stderr("\
-[ERROR] failed to parse manifest at `[..]`
-
-Caused by:
- could not parse input as TOML
-
-Caused by:
- invalid number at line 3
-"))
-}
-
-#[test]
-fn cargo_compile_with_invalid_manifest3() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/Cargo.toml", "a = bar")
- .build();
-
- assert_that(p.cargo("build").arg("--manifest-path")
- .arg("src/Cargo.toml"),
- execs()
- .with_status(101)
- .with_stderr("\
-[ERROR] failed to parse manifest at `[..]`
-
-Caused by:
- could not parse input as TOML
-
-Caused by:
- invalid number at line 1
-"))
-}
-
-#[test]
-fn cargo_compile_duplicate_build_targets() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [lib]
- name = "main"
- path = "src/main.rs"
- crate-type = ["dylib"]
-
- [dependencies]
- "#)
- .file("src/main.rs", r#"
- #![allow(warnings)]
- fn main() {}
- "#)
- .build();
-
- assert_that(p.cargo("build"),
- execs()
- .with_status(0)
- .with_stderr("\
-warning: file found to be present in multiple build targets: [..]main.rs
-[COMPILING] foo v0.0.1 ([..])
-[FINISHED] [..]
-"));
-}
-
-#[test]
-fn cargo_compile_with_invalid_version() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- authors = []
- version = "1.0"
- "#)
- .build();
-
- assert_that(p.cargo("build"),
- execs()
- .with_status(101)
- .with_stderr("\
-[ERROR] failed to parse manifest at `[..]`
-
-Caused by:
- Expected dot for key `project.version`
-"))
-
-}
-
-#[test]
-fn cargo_compile_with_invalid_package_name() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = ""
- authors = []
- version = "0.0.0"
- "#)
- .build();
-
- assert_that(p.cargo("build"),
- execs()
- .with_status(101)
- .with_stderr("\
-[ERROR] failed to parse manifest at `[..]`
-
-Caused by:
- package name cannot be an empty string
-"))
-}
-
-#[test]
-fn cargo_compile_with_invalid_bin_target_name() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- authors = []
- version = "0.0.0"
-
- [[bin]]
- name = ""
- "#)
- .build();
-
- assert_that(p.cargo("build"),
- execs()
- .with_status(101)
- .with_stderr("\
-[ERROR] failed to parse manifest at `[..]`
-
-Caused by:
- binary target names cannot be empty
-"))
-}
-
-#[test]
-fn cargo_compile_with_forbidden_bin_target_name() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- authors = []
- version = "0.0.0"
-
- [[bin]]
- name = "build"
- "#)
- .build();
-
- assert_that(p.cargo("build"),
- execs()
- .with_status(101)
- .with_stderr("\
-[ERROR] failed to parse manifest at `[..]`
-
-Caused by:
- the binary target name `build` is forbidden
-"))
-}
-
-#[test]
-fn cargo_compile_with_invalid_lib_target_name() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- authors = []
- version = "0.0.0"
-
- [lib]
- name = ""
- "#)
- .build();
-
- assert_that(p.cargo("build"),
- execs()
- .with_status(101)
- .with_stderr("\
-[ERROR] failed to parse manifest at `[..]`
-
-Caused by:
- library target names cannot be empty
-"))
-}
-
-#[test]
-fn cargo_compile_without_manifest() {
- let tmpdir = TempDir::new("cargo").unwrap();
- let p = ProjectBuilder::new("foo", tmpdir.path().to_path_buf()).build();
-
- assert_that(p.cargo("build"),
- execs().with_status(101)
- .with_stderr("\
-[ERROR] could not find `Cargo.toml` in `[..]` or any parent directory
-"));
-}
-
-#[test]
-fn cargo_compile_with_invalid_code() {
- let p = project("foo")
- .file("Cargo.toml", &basic_bin_manifest("foo"))
- .file("src/foo.rs", "invalid rust code!")
- .build();
-
- assert_that(p.cargo("build"),
- execs()
- .with_status(101)
- .with_stderr_contains("\
-[ERROR] Could not compile `foo`.
-
-To learn more, run the command again with --verbose.\n"));
- assert_that(&p.root().join("Cargo.lock"), existing_file());
-}
-
-#[test]
-fn cargo_compile_with_invalid_code_in_deps() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies.bar]
- path = "../bar"
- [dependencies.baz]
- path = "../baz"
- "#)
- .file("src/main.rs", "invalid rust code!")
- .build();
- let _bar = project("bar")
- .file("Cargo.toml", &basic_bin_manifest("bar"))
- .file("src/lib.rs", "invalid rust code!")
- .build();
- let _baz = project("baz")
- .file("Cargo.toml", &basic_bin_manifest("baz"))
- .file("src/lib.rs", "invalid rust code!")
- .build();
- assert_that(p.cargo("build"), execs().with_status(101));
-}
-
-#[test]
-fn cargo_compile_with_warnings_in_the_root_package() {
- let p = project("foo")
- .file("Cargo.toml", &basic_bin_manifest("foo"))
- .file("src/foo.rs", "fn main() {} fn dead() {}")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr_contains("\
-[..]function is never used: `dead`[..]
-"));
-}
-
-#[test]
-fn cargo_compile_with_warnings_in_a_dep_package() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
-
- name = "foo"
- version = "0.5.0"
- authors = ["wycats@example.com"]
-
- [dependencies.bar]
- path = "bar"
-
- [[bin]]
-
- name = "foo"
- "#)
- .file("src/foo.rs",
- &main_file(r#""{}", bar::gimme()"#, &["bar"]))
- .file("bar/Cargo.toml", r#"
- [project]
-
- name = "bar"
- version = "0.5.0"
- authors = ["wycats@example.com"]
-
- [lib]
-
- name = "bar"
- "#)
- .file("bar/src/bar.rs", r#"
- pub fn gimme() -> &'static str {
- "test passed"
- }
-
- fn dead() {}
- "#)
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr_contains("\
-[..]function is never used: `dead`[..]
-"));
-
- assert_that(&p.bin("foo"), existing_file());
-
- assert_that(
- process(&p.bin("foo")),
- execs().with_status(0).with_stdout("test passed\n"));
-}
-
-#[test]
-fn cargo_compile_with_nested_deps_inferred() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
-
- name = "foo"
- version = "0.5.0"
- authors = ["wycats@example.com"]
-
- [dependencies.bar]
- path = 'bar'
-
- [[bin]]
- name = "foo"
- "#)
- .file("src/foo.rs",
- &main_file(r#""{}", bar::gimme()"#, &["bar"]))
- .file("bar/Cargo.toml", r#"
- [project]
-
- name = "bar"
- version = "0.5.0"
- authors = ["wycats@example.com"]
-
- [dependencies.baz]
- path = "../baz"
- "#)
- .file("bar/src/lib.rs", r#"
- extern crate baz;
-
- pub fn gimme() -> String {
- baz::gimme()
- }
- "#)
- .file("baz/Cargo.toml", r#"
- [project]
-
- name = "baz"
- version = "0.5.0"
- authors = ["wycats@example.com"]
- "#)
- .file("baz/src/lib.rs", r#"
- pub fn gimme() -> String {
- "test passed".to_string()
- }
- "#)
- .build();
-
- p.cargo("build")
- .exec_with_output()
- .unwrap();
-
- assert_that(&p.bin("foo"), existing_file());
- assert_that(&p.bin("libbar.rlib"), is_not(existing_file()));
- assert_that(&p.bin("libbaz.rlib"), is_not(existing_file()));
-
- assert_that(
- process(&p.bin("foo")),
- execs().with_status(0).with_stdout("test passed\n"));
-}
-
-#[test]
-fn cargo_compile_with_nested_deps_correct_bin() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
-
- name = "foo"
- version = "0.5.0"
- authors = ["wycats@example.com"]
-
- [dependencies.bar]
- path = "bar"
-
- [[bin]]
- name = "foo"
- "#)
- .file("src/main.rs",
- &main_file(r#""{}", bar::gimme()"#, &["bar"]))
- .file("bar/Cargo.toml", r#"
- [project]
-
- name = "bar"
- version = "0.5.0"
- authors = ["wycats@example.com"]
-
- [dependencies.baz]
- path = "../baz"
- "#)
- .file("bar/src/lib.rs", r#"
- extern crate baz;
-
- pub fn gimme() -> String {
- baz::gimme()
- }
- "#)
- .file("baz/Cargo.toml", r#"
- [project]
-
- name = "baz"
- version = "0.5.0"
- authors = ["wycats@example.com"]
- "#)
- .file("baz/src/lib.rs", r#"
- pub fn gimme() -> String {
- "test passed".to_string()
- }
- "#)
- .build();
-
- p.cargo("build")
- .exec_with_output()
- .unwrap();
-
- assert_that(&p.bin("foo"), existing_file());
- assert_that(&p.bin("libbar.rlib"), is_not(existing_file()));
- assert_that(&p.bin("libbaz.rlib"), is_not(existing_file()));
-
- assert_that(
- process(&p.bin("foo")),
- execs().with_status(0).with_stdout("test passed\n"));
-}
-
-#[test]
-fn cargo_compile_with_nested_deps_shorthand() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
-
- name = "foo"
- version = "0.5.0"
- authors = ["wycats@example.com"]
-
- [dependencies.bar]
- path = "bar"
- "#)
- .file("src/main.rs",
- &main_file(r#""{}", bar::gimme()"#, &["bar"]))
- .file("bar/Cargo.toml", r#"
- [project]
-
- name = "bar"
- version = "0.5.0"
- authors = ["wycats@example.com"]
-
- [dependencies.baz]
- path = "../baz"
-
- [lib]
-
- name = "bar"
- "#)
- .file("bar/src/bar.rs", r#"
- extern crate baz;
-
- pub fn gimme() -> String {
- baz::gimme()
- }
- "#)
- .file("baz/Cargo.toml", r#"
- [project]
-
- name = "baz"
- version = "0.5.0"
- authors = ["wycats@example.com"]
-
- [lib]
-
- name = "baz"
- "#)
- .file("baz/src/baz.rs", r#"
- pub fn gimme() -> String {
- "test passed".to_string()
- }
- "#)
- .build();
-
- p.cargo("build")
- .exec_with_output()
- .unwrap();
-
- assert_that(&p.bin("foo"), existing_file());
- assert_that(&p.bin("libbar.rlib"), is_not(existing_file()));
- assert_that(&p.bin("libbaz.rlib"), is_not(existing_file()));
-
- assert_that(
- process(&p.bin("foo")),
- execs().with_status(0).with_stdout("test passed\n"));
-}
-
-#[test]
-fn cargo_compile_with_nested_deps_longhand() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
-
- name = "foo"
- version = "0.5.0"
- authors = ["wycats@example.com"]
-
- [dependencies.bar]
- path = "bar"
- version = "0.5.0"
-
- [[bin]]
-
- name = "foo"
- "#)
- .file("src/foo.rs",
- &main_file(r#""{}", bar::gimme()"#, &["bar"]))
- .file("bar/Cargo.toml", r#"
- [project]
-
- name = "bar"
- version = "0.5.0"
- authors = ["wycats@example.com"]
-
- [dependencies.baz]
- path = "../baz"
- version = "0.5.0"
-
- [lib]
-
- name = "bar"
- "#)
- .file("bar/src/bar.rs", r#"
- extern crate baz;
-
- pub fn gimme() -> String {
- baz::gimme()
- }
- "#)
- .file("baz/Cargo.toml", r#"
- [project]
-
- name = "baz"
- version = "0.5.0"
- authors = ["wycats@example.com"]
-
- [lib]
-
- name = "baz"
- "#)
- .file("baz/src/baz.rs", r#"
- pub fn gimme() -> String {
- "test passed".to_string()
- }
- "#)
- .build();
-
- assert_that(p.cargo("build"), execs());
-
- assert_that(&p.bin("foo"), existing_file());
- assert_that(&p.bin("libbar.rlib"), is_not(existing_file()));
- assert_that(&p.bin("libbaz.rlib"), is_not(existing_file()));
-
- assert_that(process(&p.bin("foo")),
- execs().with_status(0).with_stdout("test passed\n"));
-}
-
-// Check that Cargo gives a sensible error if a dependency can't be found
-// because of a name mismatch.
-#[test]
-fn cargo_compile_with_dep_name_mismatch() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
-
- name = "foo"
- version = "0.0.1"
- authors = ["wycats@example.com"]
-
- [[bin]]
-
- name = "foo"
-
- [dependencies.notquitebar]
-
- path = "bar"
- "#)
- .file("src/bin/foo.rs", &main_file(r#""i am foo""#, &["bar"]))
- .file("bar/Cargo.toml", &basic_bin_manifest("bar"))
- .file("bar/src/bar.rs", &main_file(r#""i am bar""#, &[]))
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(101).with_stderr(&format!(
-r#"error: no matching package named `notquitebar` found
-location searched: {proj_dir}/bar
-required by package `foo v0.0.1 ({proj_dir})`
-"#, proj_dir = p.url())));
-}
-
-#[test]
-fn cargo_compile_with_filename() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/lib.rs", "")
- .file("src/bin/a.rs", r#"
- extern crate foo;
- fn main() { println!("hello a.rs"); }
- "#)
- .file("examples/a.rs", r#"
- fn main() { println!("example"); }
- "#)
- .build();
-
- assert_that(p.cargo("build").arg("--bin").arg("bin.rs"),
- execs().with_status(101).with_stderr("\
-[ERROR] no bin target named `bin.rs`"));
-
- assert_that(p.cargo("build").arg("--bin").arg("a.rs"),
- execs().with_status(101).with_stderr("\
-[ERROR] no bin target named `a.rs`
-
-Did you mean `a`?"));
-
- assert_that(p.cargo("build").arg("--example").arg("example.rs"),
- execs().with_status(101).with_stderr("\
-[ERROR] no example target named `example.rs`"));
-
- assert_that(p.cargo("build").arg("--example").arg("a.rs"),
- execs().with_status(101).with_stderr("\
-[ERROR] no example target named `a.rs`
-
-Did you mean `a`?"));
-}
-
-#[test]
-fn cargo_compile_path_with_offline() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies.bar]
- path = "bar"
- "#)
- .file("src/lib.rs", "")
- .file("bar/Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
- "#)
- .file("bar/src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build").masquerade_as_nightly_cargo().arg("-Zoffline"),
- execs().with_status(0));
-}
-
-#[test]
-fn cargo_compile_with_downloaded_dependency_with_offline() {
- Package::new("present_dep", "1.2.3")
- .file("Cargo.toml", r#"
- [project]
- name = "present_dep"
- version = "1.2.3"
- "#)
- .file("src/lib.rs", "")
- .publish();
-
- {
- // make package downloaded
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.1.0"
-
- [dependencies]
- present_dep = "1.2.3"
- "#)
- .file("src/lib.rs", "")
- .build();
- assert_that(p.cargo("build"),execs().with_status(0));
- }
-
- let p2 = project("bar")
- .file("Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.1.0"
-
- [dependencies]
- present_dep = "1.2.3"
- "#)
- .file("src/lib.rs", "")
- .build();
-
- assert_that(p2.cargo("build").masquerade_as_nightly_cargo().arg("-Zoffline"),
- execs().with_status(0)
- .with_stderr(format!("\
-[COMPILING] present_dep v1.2.3
-[COMPILING] bar v0.1.0 ([..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]")));
-
-}
-
-#[test]
-fn cargo_compile_offline_not_try_update() {
- let p = project("bar")
- .file("Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.1.0"
-
- [dependencies]
- not_cached_dep = "1.2.5"
- "#)
- .file("src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build").masquerade_as_nightly_cargo().arg("-Zoffline"),
- execs().with_status(101)
- .with_stderr("\
-error: no matching package named `not_cached_dep` found
-location searched: registry `[..]`
-required by package `bar v0.1.0 ([..])`
-As a reminder, you're using offline mode (-Z offline) \
-which can sometimes cause surprising resolution failures, \
-if this error is too confusing you may with to retry \
-without the offline flag."));
-}
-
-#[test]
-fn compile_offline_without_maxvers_cached(){
- Package::new("present_dep", "1.2.1").publish();
- Package::new("present_dep", "1.2.2").publish();
-
- Package::new("present_dep", "1.2.3")
- .file("Cargo.toml", r#"
- [project]
- name = "present_dep"
- version = "1.2.3"
- "#)
- .file("src/lib.rs", r#"pub fn get_version()->&'static str {"1.2.3"}"#)
- .publish();
-
- Package::new("present_dep", "1.2.5")
- .file("Cargo.toml", r#"
- [project]
- name = "present_dep"
- version = "1.2.5"
- "#)
- .file("src/lib.rs", r#"pub fn get_version(){"1.2.5"}"#)
- .publish();
-
- {
- // make package cached
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.1.0"
-
- [dependencies]
- present_dep = "=1.2.3"
- "#)
- .file("src/lib.rs", "")
- .build();
- assert_that(p.cargo("build"),execs().with_status(0));
- }
-
- let p2 = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.1.0"
-
- [dependencies]
- present_dep = "1.2"
- "#)
- .file("src/main.rs", "\
-extern crate present_dep;
-fn main(){
- println!(\"{}\", present_dep::get_version());
-}")
- .build();
-
- assert_that(p2.cargo("run").masquerade_as_nightly_cargo().arg("-Zoffline"),
- execs().with_status(0)
- .with_stderr(format!("\
-[COMPILING] present_dep v1.2.3
-[COMPILING] foo v0.1.0 ({url})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
- Running `[..]`", url = p2.url()))
- .with_stdout("1.2.3")
- );
-}
-
-#[test]
-fn incompatible_dependencies() {
- Package::new("bad", "0.1.0").publish();
- Package::new("bad", "1.0.0").publish();
- Package::new("bad", "1.0.1").publish();
- Package::new("bad", "1.0.2").publish();
- Package::new("foo", "0.1.0").dep("bad", "0.1.0").publish();
- Package::new("bar", "0.1.1").dep("bad", "=1.0.0").publish();
- Package::new("bar", "0.1.0").dep("bad", "=1.0.0").publish();
- Package::new("baz", "0.1.2").dep("bad", ">=1.0.1").publish();
- Package::new("baz", "0.1.1").dep("bad", ">=1.0.1").publish();
- Package::new("baz", "0.1.0").dep("bad", ">=1.0.1").publish();
-
- let p = project("transitive_load_test")
- .file("Cargo.toml", r#"
- [project]
- name = "incompatible_dependencies"
- version = "0.0.1"
-
- [dependencies]
- foo = "0.1.0"
- bar = "0.1.0"
- baz = "0.1.0"
- "#)
- .file("src/main.rs", "fn main(){}")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(101)
- .with_stderr_contains("\
-error: failed to select a version for `bad`.
-all possible versions conflict with previously selected packages.
-required by package `baz v0.1.0`
- ... which is depended on by `incompatible_dependencies v0.0.1 ([..])`
- previously selected package `bad v1.0.0`
- ... which is depended on by `bar v0.1.0`
- ... which is depended on by `incompatible_dependencies v0.0.1 ([..])`
- possible versions to select: 1.0.2, 1.0.1"));
-}
-
-#[test]
-fn incompatible_dependencies_with_multi_semver() {
- Package::new("bad", "1.0.0").publish();
- Package::new("bad", "1.0.1").publish();
- Package::new("bad", "2.0.0").publish();
- Package::new("bad", "2.0.1").publish();
- Package::new("bar", "0.1.0").dep("bad", "=1.0.0").publish();
- Package::new("baz", "0.1.0").dep("bad", ">=2.0.1").publish();
-
- let p = project("transitive_load_test")
- .file("Cargo.toml", r#"
- [project]
- name = "incompatible_dependencies"
- version = "0.0.1"
-
- [dependencies]
- bar = "0.1.0"
- baz = "0.1.0"
- bad = ">=1.0.1, <=2.0.0"
- "#)
- .file("src/main.rs", "fn main(){}")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(101)
- .with_stderr_contains("\
-error: failed to select a version for `bad`.
-all possible versions conflict with previously selected packages.
-required by package `incompatible_dependencies v0.0.1 ([..])`
- previously selected package `bad v2.0.1`
- ... which is depended on by `baz v0.1.0`
- ... which is depended on by `incompatible_dependencies v0.0.1 ([..])`
- previously selected package `bad v1.0.0`
- ... which is depended on by `bar v0.1.0`
- ... which is depended on by `incompatible_dependencies v0.0.1 ([..])`
- possible versions to select: 2.0.0, 1.0.1"));
-}
-
-#[test]
-fn compile_offline_while_transitive_dep_not_cached() {
- let bar = Package::new("bar", "1.0.0");
- let bar_path = bar.archive_dst();
- bar.publish();
-
- let mut content = Vec::new();
-
- let mut file = File::open(bar_path.clone()).ok().unwrap();
- let _ok = file.read_to_end(&mut content).ok().unwrap();
- drop(file);
- drop(File::create(bar_path.clone()).ok().unwrap() );
-
- Package::new("foo", "0.1.0").dep("bar", "1.0.0").publish();
-
- let p = project("transitive_load_test")
- .file("Cargo.toml", r#"
- [project]
- name = "transitive_load_test"
- version = "0.0.1"
-
- [dependencies]
- foo = "0.1.0"
- "#)
- .file("src/main.rs", "fn main(){}")
- .build();
-
- // simulate download foo, but fail to download bar
- let _out = p.cargo("build").exec_with_output();
-
- drop( File::create(bar_path).ok().unwrap().write_all(&content) );
-
- assert_that(p.cargo("build").masquerade_as_nightly_cargo().arg("-Zoffline"),
- execs().with_status(101)
- .with_stderr("\
-error: no matching package named `bar` found
-location searched: registry `[..]`
-required by package `foo v0.1.0`
- ... which is depended on by `transitive_load_test v0.0.1 ([..]/transitive_load_test)`
-As a reminder, you're using offline mode (-Z offline) \
-which can sometimes cause surprising resolution failures, \
-if this error is too confusing you may with to retry \
-without the offline flag."));
-}
-
-#[test]
-fn compile_path_dep_then_change_version() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies.bar]
- path = "bar"
- "#)
- .file("src/lib.rs", "")
- .file("bar/Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
- "#)
- .file("bar/src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build"), execs().with_status(0));
-
- File::create(&p.root().join("bar/Cargo.toml")).unwrap().write_all(br#"
- [package]
- name = "bar"
- version = "0.0.2"
- authors = []
- "#).unwrap();
-
- assert_that(p.cargo("build"),
- execs().with_status(101).with_stderr("\
-error: no matching version `= 0.0.1` found for package `bar`
-location searched: [..]
-versions found: 0.0.2
-required by package `foo v0.0.1 ([..]/foo)`
-consider running `cargo update` to update a path dependency's locked version
-"));
-}
-
-#[test]
-fn ignores_carriage_return_in_lockfile() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- authors = []
- version = "0.0.1"
- "#)
- .file("src/main.rs", r#"
- mod a; fn main() {}
- "#)
- .file("src/a.rs", "")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0));
-
- let lockfile = p.root().join("Cargo.lock");
- let mut lock = String::new();
- File::open(&lockfile).unwrap().read_to_string(&mut lock).unwrap();
- let lock = lock.replace("\n", "\r\n");
- File::create(&lockfile).unwrap().write_all(lock.as_bytes()).unwrap();
- assert_that(p.cargo("build"),
- execs().with_status(0));
-}
-
-#[test]
-fn cargo_default_env_metadata_env_var() {
- // Ensure that path dep + dylib + env_var get metadata
- // (even though path_dep + dylib should not)
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies.bar]
- path = "bar"
- "#)
- .file("src/lib.rs", "// hi")
- .file("bar/Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
-
- [lib]
- name = "bar"
- crate_type = ["dylib"]
- "#)
- .file("bar/src/lib.rs", "// hello")
- .build();
-
- // No metadata on libbar since it's a dylib path dependency
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(0).with_stderr(&format!("\
-[COMPILING] bar v0.0.1 ({url}/bar)
-[RUNNING] `rustc --crate-name bar bar[/]src[/]lib.rs --crate-type dylib \
- --emit=dep-info,link \
- -C prefer-dynamic -C debuginfo=2 \
- -C metadata=[..] \
- --out-dir [..] \
- -L dependency={dir}[/]target[/]debug[/]deps`
-[COMPILING] foo v0.0.1 ({url})
-[RUNNING] `rustc --crate-name foo src[/]lib.rs --crate-type lib \
- --emit=dep-info,link -C debuginfo=2 \
- -C metadata=[..] \
- -C extra-filename=[..] \
- --out-dir [..] \
- -L dependency={dir}[/]target[/]debug[/]deps \
- --extern bar={dir}[/]target[/]debug[/]deps[/]{prefix}bar{suffix}`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]",
-dir = p.root().display(),
-url = p.url(),
-prefix = env::consts::DLL_PREFIX,
-suffix = env::consts::DLL_SUFFIX,
-)));
-
- assert_that(p.cargo("clean"), execs().with_status(0));
-
- // If you set the env-var, then we expect metadata on libbar
- assert_that(p.cargo("build").arg("-v").env("__CARGO_DEFAULT_LIB_METADATA", "stable"),
- execs().with_status(0).with_stderr(&format!("\
-[COMPILING] bar v0.0.1 ({url}/bar)
-[RUNNING] `rustc --crate-name bar bar[/]src[/]lib.rs --crate-type dylib \
- --emit=dep-info,link \
- -C prefer-dynamic -C debuginfo=2 \
- -C metadata=[..] \
- --out-dir [..] \
- -L dependency={dir}[/]target[/]debug[/]deps`
-[COMPILING] foo v0.0.1 ({url})
-[RUNNING] `rustc --crate-name foo src[/]lib.rs --crate-type lib \
- --emit=dep-info,link -C debuginfo=2 \
- -C metadata=[..] \
- -C extra-filename=[..] \
- --out-dir [..] \
- -L dependency={dir}[/]target[/]debug[/]deps \
- --extern bar={dir}[/]target[/]debug[/]deps[/]{prefix}bar-[..]{suffix}`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-",
-dir = p.root().display(),
-url = p.url(),
-prefix = env::consts::DLL_PREFIX,
-suffix = env::consts::DLL_SUFFIX,
-)));
-}
-
-#[test]
-fn crate_env_vars() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.5.1-alpha.1"
- description = "This is foo"
- homepage = "http://example.com"
- authors = ["wycats@example.com"]
- "#)
- .file("src/main.rs", r#"
- extern crate foo;
-
-
- static VERSION_MAJOR: &'static str = env!("CARGO_PKG_VERSION_MAJOR");
- static VERSION_MINOR: &'static str = env!("CARGO_PKG_VERSION_MINOR");
- static VERSION_PATCH: &'static str = env!("CARGO_PKG_VERSION_PATCH");
- static VERSION_PRE: &'static str = env!("CARGO_PKG_VERSION_PRE");
- static VERSION: &'static str = env!("CARGO_PKG_VERSION");
- static CARGO_MANIFEST_DIR: &'static str = env!("CARGO_MANIFEST_DIR");
- static PKG_NAME: &'static str = env!("CARGO_PKG_NAME");
- static HOMEPAGE: &'static str = env!("CARGO_PKG_HOMEPAGE");
- static DESCRIPTION: &'static str = env!("CARGO_PKG_DESCRIPTION");
-
- fn main() {
- let s = format!("{}-{}-{} @ {} in {}", VERSION_MAJOR,
- VERSION_MINOR, VERSION_PATCH, VERSION_PRE,
- CARGO_MANIFEST_DIR);
- assert_eq!(s, foo::version());
- println!("{}", s);
- assert_eq!("foo", PKG_NAME);
- assert_eq!("http://example.com", HOMEPAGE);
- assert_eq!("This is foo", DESCRIPTION);
- let s = format!("{}.{}.{}-{}", VERSION_MAJOR,
- VERSION_MINOR, VERSION_PATCH, VERSION_PRE);
- assert_eq!(s, VERSION);
- }
- "#)
- .file("src/lib.rs", r#"
- pub fn version() -> String {
- format!("{}-{}-{} @ {} in {}",
- env!("CARGO_PKG_VERSION_MAJOR"),
- env!("CARGO_PKG_VERSION_MINOR"),
- env!("CARGO_PKG_VERSION_PATCH"),
- env!("CARGO_PKG_VERSION_PRE"),
- env!("CARGO_MANIFEST_DIR"))
- }
- "#)
- .build();
-
- println!("build");
- assert_that(p.cargo("build").arg("-v"), execs().with_status(0));
-
- println!("bin");
- assert_that(process(&p.bin("foo")),
- execs().with_status(0).with_stdout(&format!("0-5-1 @ alpha.1 in {}\n",
- p.root().display())));
-
- println!("test");
- assert_that(p.cargo("test").arg("-v"),
- execs().with_status(0));
-}
-
-#[test]
-fn crate_authors_env_vars() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.5.1-alpha.1"
- authors = ["wycats@example.com", "neikos@example.com"]
- "#)
- .file("src/main.rs", r#"
- extern crate foo;
-
- static AUTHORS: &'static str = env!("CARGO_PKG_AUTHORS");
-
- fn main() {
- let s = "wycats@example.com:neikos@example.com";
- assert_eq!(AUTHORS, foo::authors());
- println!("{}", AUTHORS);
- assert_eq!(s, AUTHORS);
- }
- "#)
- .file("src/lib.rs", r#"
- pub fn authors() -> String {
- format!("{}", env!("CARGO_PKG_AUTHORS"))
- }
- "#)
- .build();
-
- println!("build");
- assert_that(p.cargo("build").arg("-v"), execs().with_status(0));
-
- println!("bin");
- assert_that(process(&p.bin("foo")),
- execs().with_status(0).with_stdout("wycats@example.com:neikos@example.com"));
-
- println!("test");
- assert_that(p.cargo("test").arg("-v"),
- execs().with_status(0));
-}
-
-// The tester may already have LD_LIBRARY_PATH=::/foo/bar which leads to a false positive error
-fn setenv_for_removing_empty_component(mut p: ProcessBuilder) -> ProcessBuilder {
- let v = dylib_path_envvar();
- if let Ok(search_path) = env::var(v) {
- let new_search_path =
- env::join_paths(env::split_paths(&search_path).filter(|e| !e.as_os_str().is_empty()))
- .expect("join_paths");
- p.env(v, new_search_path); // build_command() will override LD_LIBRARY_PATH accordingly
- }
- p
-}
-
-// Regression test for #4277
-#[test]
-fn crate_library_path_env_var() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/main.rs", &format!(r##"
- fn main() {{
- let search_path = env!("{}");
- let paths = std::env::split_paths(&search_path).collect::<Vec<_>>();
- assert!(!paths.contains(&"".into()));
- }}
- "##, dylib_path_envvar()))
- .build();
-
- assert_that(setenv_for_removing_empty_component(p.cargo("run")),
- execs().with_status(0));
-}
-
-// Regression test for #4277
-#[test]
-fn build_with_fake_libc_not_loading() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/main.rs", r#"
- fn main() {}
- "#)
- .file("src/lib.rs", r#" "#)
- .file("libc.so.6", r#""#)
- .build();
-
- assert_that(setenv_for_removing_empty_component(p.cargo("build")),
- execs().with_status(0));
-}
-
-// this is testing that src/<pkg-name>.rs still works (for now)
-#[test]
-fn many_crate_types_old_style_lib_location() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
-
- name = "foo"
- version = "0.5.0"
- authors = ["wycats@example.com"]
-
- [lib]
-
- name = "foo"
- crate_type = ["rlib", "dylib"]
- "#)
- .file("src/foo.rs", r#"
- pub fn foo() {}
- "#)
- .build();
- assert_that(p.cargo("build"), execs().with_status(0).with_stderr_contains("\
-[WARNING] path `[..]src[/]foo.rs` was erroneously implicitly accepted for library `foo`,
-please rename the file to `src/lib.rs` or set lib.path in Cargo.toml"));
-
- assert_that(&p.root().join("target/debug/libfoo.rlib"), existing_file());
- let fname = format!("{}foo{}", env::consts::DLL_PREFIX,
- env::consts::DLL_SUFFIX);
- assert_that(&p.root().join("target/debug").join(&fname), existing_file());
-}
-
-#[test]
-fn many_crate_types_correct() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
-
- name = "foo"
- version = "0.5.0"
- authors = ["wycats@example.com"]
-
- [lib]
-
- name = "foo"
- crate_type = ["rlib", "dylib"]
- "#)
- .file("src/lib.rs", r#"
- pub fn foo() {}
- "#)
- .build();
- assert_that(p.cargo("build"),
- execs().with_status(0));
-
- assert_that(&p.root().join("target/debug/libfoo.rlib"), existing_file());
- let fname = format!("{}foo{}", env::consts::DLL_PREFIX,
- env::consts::DLL_SUFFIX);
- assert_that(&p.root().join("target/debug").join(&fname), existing_file());
-}
-
-#[test]
-fn self_dependency() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
-
- name = "test"
- version = "0.0.0"
- authors = []
-
- [dependencies.test]
-
- path = "."
-
- [lib]
- name = "test"
- path = "src/test.rs"
- "#)
- .file("src/test.rs", "fn main() {}")
- .build();
- assert_that(p.cargo("build"),
- execs().with_status(101)
- .with_stderr("\
-[ERROR] cyclic package dependency: package `test v0.0.0 ([..])` depends on itself
-"));
-}
-
-#[test]
-fn ignore_broken_symlinks() {
- // windows and symlinks don't currently agree that well
- if cfg!(windows) { return }
-
- let p = project("foo")
- .file("Cargo.toml", &basic_bin_manifest("foo"))
- .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
- .symlink("Notafile", "bar")
- .build();
-
- assert_that(p.cargo("build"), execs().with_status(0));
- assert_that(&p.bin("foo"), existing_file());
-
- assert_that(process(&p.bin("foo")),
- execs().with_status(0).with_stdout("i am foo\n"));
-}
-
-#[test]
-fn missing_lib_and_bin() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
-
- name = "test"
- version = "0.0.0"
- authors = []
- "#)
- .build();
- assert_that(p.cargo("build"),
- execs().with_status(101)
- .with_stderr("\
-[ERROR] failed to parse manifest at `[..]Cargo.toml`
-
-Caused by:
- no targets specified in the manifest
- either src/lib.rs, src/main.rs, a [lib] section, or [[bin]] section must be present\n"));
-}
-
-#[test]
-fn lto_build() {
- // FIXME: currently this hits a linker bug on 32-bit MSVC
- if cfg!(all(target_env = "msvc", target_pointer_width = "32")) {
- return
- }
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
-
- name = "test"
- version = "0.0.0"
- authors = []
-
- [profile.release]
- lto = true
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
- assert_that(p.cargo("build").arg("-v").arg("--release"),
- execs().with_status(0).with_stderr(&format!("\
-[COMPILING] test v0.0.0 ({url})
-[RUNNING] `rustc --crate-name test src[/]main.rs --crate-type bin \
- --emit=dep-info,link \
- -C opt-level=3 \
- -C lto \
- -C metadata=[..] \
- --out-dir {dir}[/]target[/]release[/]deps \
- -L dependency={dir}[/]target[/]release[/]deps`
-[FINISHED] release [optimized] target(s) in [..]
-",
-dir = p.root().display(),
-url = p.url(),
-)));
-}
-
-#[test]
-fn verbose_build() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
-
- name = "test"
- version = "0.0.0"
- authors = []
- "#)
- .file("src/lib.rs", "")
- .build();
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(0).with_stderr(&format!("\
-[COMPILING] test v0.0.0 ({url})
-[RUNNING] `rustc --crate-name test src[/]lib.rs --crate-type lib \
- --emit=dep-info,link -C debuginfo=2 \
- -C metadata=[..] \
- --out-dir [..] \
- -L dependency={dir}[/]target[/]debug[/]deps`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-",
-dir = p.root().display(),
-url = p.url(),
-)));
-}
-
-#[test]
-fn verbose_release_build() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
-
- name = "test"
- version = "0.0.0"
- authors = []
- "#)
- .file("src/lib.rs", "")
- .build();
- assert_that(p.cargo("build").arg("-v").arg("--release"),
- execs().with_status(0).with_stderr(&format!("\
-[COMPILING] test v0.0.0 ({url})
-[RUNNING] `rustc --crate-name test src[/]lib.rs --crate-type lib \
- --emit=dep-info,link \
- -C opt-level=3 \
- -C metadata=[..] \
- --out-dir [..] \
- -L dependency={dir}[/]target[/]release[/]deps`
-[FINISHED] release [optimized] target(s) in [..]
-",
-dir = p.root().display(),
-url = p.url(),
-)));
-}
-
-#[test]
-fn verbose_release_build_deps() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
-
- name = "test"
- version = "0.0.0"
- authors = []
-
- [dependencies.foo]
- path = "foo"
- "#)
- .file("src/lib.rs", "")
- .file("foo/Cargo.toml", r#"
- [package]
-
- name = "foo"
- version = "0.0.0"
- authors = []
-
- [lib]
- name = "foo"
- crate_type = ["dylib", "rlib"]
- "#)
- .file("foo/src/lib.rs", "")
- .build();
- assert_that(p.cargo("build").arg("-v").arg("--release"),
- execs().with_status(0).with_stderr(&format!("\
-[COMPILING] foo v0.0.0 ({url}/foo)
-[RUNNING] `rustc --crate-name foo foo[/]src[/]lib.rs \
- --crate-type dylib --crate-type rlib \
- --emit=dep-info,link \
- -C prefer-dynamic \
- -C opt-level=3 \
- -C metadata=[..] \
- --out-dir [..] \
- -L dependency={dir}[/]target[/]release[/]deps`
-[COMPILING] test v0.0.0 ({url})
-[RUNNING] `rustc --crate-name test src[/]lib.rs --crate-type lib \
- --emit=dep-info,link \
- -C opt-level=3 \
- -C metadata=[..] \
- --out-dir [..] \
- -L dependency={dir}[/]target[/]release[/]deps \
- --extern foo={dir}[/]target[/]release[/]deps[/]{prefix}foo{suffix} \
- --extern foo={dir}[/]target[/]release[/]deps[/]libfoo.rlib`
-[FINISHED] release [optimized] target(s) in [..]
-",
- dir = p.root().display(),
- url = p.url(),
- prefix = env::consts::DLL_PREFIX,
- suffix = env::consts::DLL_SUFFIX)));
-}
-
-#[test]
-fn explicit_examples() {
- let p = project("world")
- .file("Cargo.toml", r#"
- [package]
- name = "world"
- version = "1.0.0"
- authors = []
-
- [lib]
- name = "world"
- path = "src/lib.rs"
-
- [[example]]
- name = "hello"
- path = "examples/ex-hello.rs"
-
- [[example]]
- name = "goodbye"
- path = "examples/ex-goodbye.rs"
- "#)
- .file("src/lib.rs", r#"
- pub fn get_hello() -> &'static str { "Hello" }
- pub fn get_goodbye() -> &'static str { "Goodbye" }
- pub fn get_world() -> &'static str { "World" }
- "#)
- .file("examples/ex-hello.rs", r#"
- extern crate world;
- fn main() { println!("{}, {}!", world::get_hello(), world::get_world()); }
- "#)
- .file("examples/ex-goodbye.rs", r#"
- extern crate world;
- fn main() { println!("{}, {}!", world::get_goodbye(), world::get_world()); }
- "#)
- .build();
-
- assert_that(p.cargo("test").arg("-v"), execs().with_status(0));
- assert_that(process(&p.bin("examples/hello")),
- execs().with_status(0).with_stdout("Hello, World!\n"));
- assert_that(process(&p.bin("examples/goodbye")),
- execs().with_status(0).with_stdout("Goodbye, World!\n"));
-}
-
-#[test]
-fn non_existing_example() {
- let p = project("world")
- .file("Cargo.toml", r#"
- [package]
- name = "world"
- version = "1.0.0"
- authors = []
-
- [lib]
- name = "world"
- path = "src/lib.rs"
-
- [[example]]
- name = "hello"
- "#)
- .file("src/lib.rs", "")
- .file("examples/ehlo.rs", "")
- .build();
-
- assert_that(p.cargo("test").arg("-v"), execs().with_status(101).with_stderr("\
-[ERROR] failed to parse manifest at `[..]`
-
-Caused by:
- can't find `hello` example, specify example.path"));
-}
-
-#[test]
-fn non_existing_binary() {
- let p = project("world")
- .file("Cargo.toml", r#"
- [package]
- name = "world"
- version = "1.0.0"
- authors = []
-
- [[bin]]
- name = "hello"
- "#)
- .file("src/lib.rs", "")
- .file("src/bin/ehlo.rs", "")
- .build();
-
- assert_that(p.cargo("build").arg("-v"), execs().with_status(101).with_stderr("\
-[ERROR] failed to parse manifest at `[..]`
-
-Caused by:
- can't find `hello` bin, specify bin.path"));
-}
-
-#[test]
-fn legacy_binary_paths_warinigs() {
- let p = project("world")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "1.0.0"
- authors = []
-
- [[bin]]
- name = "bar"
- "#)
- .file("src/lib.rs", "")
- .file("src/main.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("build").arg("-v"), execs().with_status(0).with_stderr_contains("\
-[WARNING] path `[..]src[/]main.rs` was erroneously implicitly accepted for binary `bar`,
-please set bin.path in Cargo.toml"));
-
- let p = project("world")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "1.0.0"
- authors = []
-
- [[bin]]
- name = "bar"
- "#)
- .file("src/lib.rs", "")
- .file("src/bin/main.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("build").arg("-v"), execs().with_status(0).with_stderr_contains("\
-[WARNING] path `[..]src[/]bin[/]main.rs` was erroneously implicitly accepted for binary `bar`,
-please set bin.path in Cargo.toml"));
-
- let p = project("world")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "1.0.0"
- authors = []
-
- [[bin]]
- name = "bar"
- "#)
- .file("src/bar.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("build").arg("-v"), execs().with_status(0).with_stderr_contains("\
-[WARNING] path `[..]src[/]bar.rs` was erroneously implicitly accepted for binary `bar`,
-please set bin.path in Cargo.toml"));
-}
-
-#[test]
-fn implicit_examples() {
- let p = project("world")
- .file("Cargo.toml", r#"
- [package]
- name = "world"
- version = "1.0.0"
- authors = []
- "#)
- .file("src/lib.rs", r#"
- pub fn get_hello() -> &'static str { "Hello" }
- pub fn get_goodbye() -> &'static str { "Goodbye" }
- pub fn get_world() -> &'static str { "World" }
- "#)
- .file("examples/hello.rs", r#"
- extern crate world;
- fn main() {
- println!("{}, {}!", world::get_hello(), world::get_world());
- }
- "#)
- .file("examples/goodbye.rs", r#"
- extern crate world;
- fn main() {
- println!("{}, {}!", world::get_goodbye(), world::get_world());
- }
- "#)
- .build();
-
- assert_that(p.cargo("test"), execs().with_status(0));
- assert_that(process(&p.bin("examples/hello")),
- execs().with_status(0).with_stdout("Hello, World!\n"));
- assert_that(process(&p.bin("examples/goodbye")),
- execs().with_status(0).with_stdout("Goodbye, World!\n"));
-}
-
-#[test]
-fn standard_build_no_ndebug() {
- let p = project("world")
- .file("Cargo.toml", &basic_bin_manifest("foo"))
- .file("src/foo.rs", r#"
- fn main() {
- if cfg!(debug_assertions) {
- println!("slow")
- } else {
- println!("fast")
- }
- }
- "#)
- .build();
-
- assert_that(p.cargo("build"), execs().with_status(0));
- assert_that(process(&p.bin("foo")),
- execs().with_status(0).with_stdout("slow\n"));
-}
-
-#[test]
-fn release_build_ndebug() {
- let p = project("world")
- .file("Cargo.toml", &basic_bin_manifest("foo"))
- .file("src/foo.rs", r#"
- fn main() {
- if cfg!(debug_assertions) {
- println!("slow")
- } else {
- println!("fast")
- }
- }
- "#)
- .build();
-
- assert_that(p.cargo("build").arg("--release"),
- execs().with_status(0));
- assert_that(process(&p.release_bin("foo")),
- execs().with_status(0).with_stdout("fast\n"));
-}
-
-#[test]
-fn inferred_main_bin() {
- let p = project("world")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/main.rs", r#"
- fn main() {}
- "#)
- .build();
-
- assert_that(p.cargo("build"), execs().with_status(0));
- assert_that(process(&p.bin("foo")), execs().with_status(0));
-}
-
-#[test]
-fn deletion_causes_failure() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies.bar]
- path = "bar"
- "#)
- .file("src/main.rs", r#"
- extern crate bar;
- fn main() {}
- "#)
- .file("bar/Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
- "#)
- .file("bar/src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build"), execs().with_status(0));
- p.change_file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#);
- assert_that(p.cargo("build"), execs().with_status(101));
-}
-
-#[test]
-fn bad_cargo_toml_in_target_dir() {
- let p = project("world")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/main.rs", r#"
- fn main() {}
- "#)
- .file("target/Cargo.toml", "bad-toml")
- .build();
-
- assert_that(p.cargo("build"), execs().with_status(0));
- assert_that(process(&p.bin("foo")), execs().with_status(0));
-}
-
-#[test]
-fn lib_with_standard_name() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "syntax"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/lib.rs", "
- pub fn foo() {}
- ")
- .file("src/main.rs", "
- extern crate syntax;
- fn main() { syntax::foo() }
- ")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0)
- .with_stderr(&format!("\
-[COMPILING] syntax v0.0.1 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-",
- dir = p.url())));
-}
-
-#[test]
-fn simple_staticlib() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- authors = []
- version = "0.0.1"
-
- [lib]
- name = "foo"
- crate-type = ["staticlib"]
- "#)
- .file("src/lib.rs", "pub fn foo() {}")
- .build();
-
- // env var is a test for #1381
- assert_that(p.cargo("build").env("RUST_LOG", "nekoneko=trace"),
- execs().with_status(0));
-}
-
-#[test]
-fn staticlib_rlib_and_bin() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- authors = []
- version = "0.0.1"
-
- [lib]
- name = "foo"
- crate-type = ["staticlib", "rlib"]
- "#)
- .file("src/lib.rs", "pub fn foo() {}")
- .file("src/main.rs", r#"
- extern crate foo;
-
- fn main() {
- foo::foo();
- }"#)
- .build();
-
- assert_that(p.cargo("build").arg("-v"), execs().with_status(0));
-}
-
-#[test]
-fn opt_out_of_bin() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- bin = []
-
- [package]
- name = "foo"
- authors = []
- version = "0.0.1"
- "#)
- .file("src/lib.rs", "")
- .file("src/main.rs", "bad syntax")
- .build();
- assert_that(p.cargo("build"), execs().with_status(0));
-}
-
-#[test]
-fn single_lib() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- authors = []
- version = "0.0.1"
-
- [lib]
- name = "foo"
- path = "src/bar.rs"
- "#)
- .file("src/bar.rs", "")
- .build();
- assert_that(p.cargo("build"), execs().with_status(0));
-}
-
-#[test]
-fn freshness_ignores_excluded() {
- let foo = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.0"
- authors = []
- build = "build.rs"
- exclude = ["src/b*.rs"]
- "#)
- .file("build.rs", "fn main() {}")
- .file("src/lib.rs", "pub fn bar() -> i32 { 1 }")
- .build();
- foo.root().move_into_the_past();
-
- assert_that(foo.cargo("build"),
- execs().with_status(0)
- .with_stderr(&format!("\
-[COMPILING] foo v0.0.0 ({url})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-", url = foo.url())));
-
- // Smoke test to make sure it doesn't compile again
- println!("first pass");
- assert_that(foo.cargo("build"),
- execs().with_status(0)
- .with_stdout(""));
-
- // Modify an ignored file and make sure we don't rebuild
- println!("second pass");
- File::create(&foo.root().join("src/bar.rs")).unwrap();
- assert_that(foo.cargo("build"),
- execs().with_status(0)
- .with_stdout(""));
-}
-
-#[test]
-fn rebuild_preserves_out_dir() {
- let foo = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.0"
- authors = []
- build = 'build.rs'
- "#)
- .file("build.rs", r#"
- use std::env;
- use std::fs::File;
- use std::path::Path;
-
- fn main() {
- let path = Path::new(&env::var("OUT_DIR").unwrap()).join("foo");
- if env::var_os("FIRST").is_some() {
- File::create(&path).unwrap();
- } else {
- File::create(&path).unwrap();
- }
- }
- "#)
- .file("src/lib.rs", "pub fn bar() -> i32 { 1 }")
- .build();
- foo.root().move_into_the_past();
-
- assert_that(foo.cargo("build").env("FIRST", "1"),
- execs().with_status(0)
- .with_stderr(&format!("\
-[COMPILING] foo v0.0.0 ({url})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-", url = foo.url())));
-
- File::create(&foo.root().join("src/bar.rs")).unwrap();
- assert_that(foo.cargo("build"),
- execs().with_status(0)
- .with_stderr(&format!("\
-[COMPILING] foo v0.0.0 ({url})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-", url = foo.url())));
-}
-
-#[test]
-fn dep_no_libs() {
- let foo = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.0"
- authors = []
-
- [dependencies.bar]
- path = "bar"
- "#)
- .file("src/lib.rs", "pub fn bar() -> i32 { 1 }")
- .file("bar/Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.0"
- authors = []
- "#)
- .file("bar/src/main.rs", "")
- .build();
- assert_that(foo.cargo("build"),
- execs().with_status(0));
-}
-
-#[test]
-fn recompile_space_in_name() {
- let foo = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.0"
- authors = []
-
- [lib]
- name = "foo"
- path = "src/my lib.rs"
- "#)
- .file("src/my lib.rs", "")
- .build();
- assert_that(foo.cargo("build"), execs().with_status(0));
- foo.root().move_into_the_past();
- assert_that(foo.cargo("build"),
- execs().with_status(0).with_stdout(""));
-}
-
-#[cfg(unix)]
-#[test]
-fn ignore_bad_directories() {
- use std::os::unix::prelude::*;
- let foo = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.0"
- authors = []
- "#)
- .file("src/lib.rs", "")
- .build();
- let dir = foo.root().join("tmp");
- fs::create_dir(&dir).unwrap();
- let stat = fs::metadata(&dir).unwrap();
- let mut perms = stat.permissions();
- perms.set_mode(0o644);
- fs::set_permissions(&dir, perms.clone()).unwrap();
- assert_that(foo.cargo("build"),
- execs().with_status(0));
- perms.set_mode(0o755);
- fs::set_permissions(&dir, perms).unwrap();
-}
-
-#[test]
-fn bad_cargo_config() {
- let foo = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.0"
- authors = []
- "#)
- .file("src/lib.rs", "")
- .file(".cargo/config", r#"
- this is not valid toml
- "#)
- .build();
- assert_that(foo.cargo("build").arg("-v"),
- execs().with_status(101).with_stderr("\
-[ERROR] Couldn't load Cargo configuration
-
-Caused by:
- could not parse TOML configuration in `[..]`
-
-Caused by:
- could not parse input as TOML
-
-Caused by:
- expected an equals, found an identifier at line 2
-"));
-}
-
-#[test]
-fn cargo_platform_specific_dependency() {
- let host = rustc_host();
- let p = project("foo")
- .file("Cargo.toml", &format!(r#"
- [project]
- name = "foo"
- version = "0.5.0"
- authors = ["wycats@example.com"]
- build = "build.rs"
-
- [target.{host}.dependencies]
- dep = {{ path = "dep" }}
- [target.{host}.build-dependencies]
- build = {{ path = "build" }}
- [target.{host}.dev-dependencies]
- dev = {{ path = "dev" }}
- "#, host = host))
- .file("src/main.rs", r#"
- extern crate dep;
- fn main() { dep::dep() }
- "#)
- .file("tests/foo.rs", r#"
- extern crate dev;
- #[test]
- fn foo() { dev::dev() }
- "#)
- .file("build.rs", r#"
- extern crate build;
- fn main() { build::build(); }
- "#)
- .file("dep/Cargo.toml", r#"
- [project]
- name = "dep"
- version = "0.5.0"
- authors = ["wycats@example.com"]
- "#)
- .file("dep/src/lib.rs", "pub fn dep() {}")
- .file("build/Cargo.toml", r#"
- [project]
- name = "build"
- version = "0.5.0"
- authors = ["wycats@example.com"]
- "#)
- .file("build/src/lib.rs", "pub fn build() {}")
- .file("dev/Cargo.toml", r#"
- [project]
- name = "dev"
- version = "0.5.0"
- authors = ["wycats@example.com"]
- "#)
- .file("dev/src/lib.rs", "pub fn dev() {}")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0));
-
- assert_that(&p.bin("foo"), existing_file());
- assert_that(p.cargo("test"),
- execs().with_status(0));
-}
-
-#[test]
-fn bad_platform_specific_dependency() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
-
- name = "foo"
- version = "0.5.0"
- authors = ["wycats@example.com"]
-
- [target.wrong-target.dependencies.bar]
- path = "bar"
- "#)
- .file("src/main.rs",
- &main_file(r#""{}", bar::gimme()"#, &["bar"]))
- .file("bar/Cargo.toml", r#"
- [project]
-
- name = "bar"
- version = "0.5.0"
- authors = ["wycats@example.com"]
- "#)
- .file("bar/src/lib.rs", r#"
- extern crate baz;
-
- pub fn gimme() -> String {
- format!("")
- }
- "#)
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(101));
-}
-
-#[test]
-fn cargo_platform_specific_dependency_wrong_platform() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
-
- name = "foo"
- version = "0.5.0"
- authors = ["wycats@example.com"]
-
- [target.non-existing-triplet.dependencies.bar]
- path = "bar"
- "#)
- .file("src/main.rs", r#"
- fn main() {}
- "#)
- .file("bar/Cargo.toml", r#"
- [project]
-
- name = "bar"
- version = "0.5.0"
- authors = ["wycats@example.com"]
- "#)
- .file("bar/src/lib.rs", r#"
- invalid rust file, should not be compiled
- "#)
- .build();
-
- p.cargo("build").exec_with_output().unwrap();
-
- assert_that(&p.bin("foo"), existing_file());
- assert_that(process(&p.bin("foo")),
- execs().with_status(0));
-
- let loc = p.root().join("Cargo.lock");
- let mut lockfile = String::new();
- File::open(&loc).unwrap().read_to_string(&mut lockfile).unwrap();
- assert!(lockfile.contains("bar"))
-}
-
-#[test]
-fn example_as_lib() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [[example]]
- name = "ex"
- crate-type = ["lib"]
- "#)
- .file("src/lib.rs", "")
- .file("examples/ex.rs", "")
- .build();
-
- assert_that(p.cargo("build").arg("--example=ex"), execs().with_status(0));
- assert_that(&p.example_lib("ex", "lib"), existing_file());
-}
-
-#[test]
-fn example_as_rlib() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [[example]]
- name = "ex"
- crate-type = ["rlib"]
- "#)
- .file("src/lib.rs", "")
- .file("examples/ex.rs", "")
- .build();
-
- assert_that(p.cargo("build").arg("--example=ex"), execs().with_status(0));
- assert_that(&p.example_lib("ex", "rlib"), existing_file());
-}
-
-#[test]
-fn example_as_dylib() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [[example]]
- name = "ex"
- crate-type = ["dylib"]
- "#)
- .file("src/lib.rs", "")
- .file("examples/ex.rs", "")
- .build();
-
- assert_that(p.cargo("build").arg("--example=ex"), execs().with_status(0));
- assert_that(&p.example_lib("ex", "dylib"), existing_file());
-}
-
-#[test]
-fn example_as_proc_macro() {
- if !is_nightly() {
- return;
- }
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [[example]]
- name = "ex"
- crate-type = ["proc-macro"]
- "#)
- .file("src/lib.rs", "")
- .file("examples/ex.rs", "#![feature(proc_macro)]")
- .build();
-
- assert_that(p.cargo("build").arg("--example=ex"), execs().with_status(0));
- assert_that(&p.example_lib("ex", "proc-macro"), existing_file());
-}
-
-#[test]
-fn example_bin_same_name() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/main.rs", "fn main() {}")
- .file("examples/foo.rs", "fn main() {}")
- .build();
-
- p.cargo("test").arg("--no-run").arg("-v")
- .exec_with_output()
- .unwrap();
-
- assert_that(&p.bin("foo"), is_not(existing_file()));
- // We expect a file of the form bin/foo-{metadata_hash}
- assert_that(&p.bin("examples/foo"), existing_file());
-
- p.cargo("test").arg("--no-run").arg("-v")
- .exec_with_output()
- .unwrap();
-
- assert_that(&p.bin("foo"), is_not(existing_file()));
- // We expect a file of the form bin/foo-{metadata_hash}
- assert_that(&p.bin("examples/foo"), existing_file());
-}
-
-#[test]
-fn compile_then_delete() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("run").arg("-v"), execs().with_status(0));
- assert_that(&p.bin("foo"), existing_file());
- if cfg!(windows) {
- // On windows unlinking immediately after running often fails, so sleep
- sleep_ms(100);
- }
- fs::remove_file(&p.bin("foo")).unwrap();
- assert_that(p.cargo("run").arg("-v"),
- execs().with_status(0));
-}
-
-#[test]
-fn transitive_dependencies_not_available() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies.aaaaa]
- path = "a"
- "#)
- .file("src/main.rs", "extern crate bbbbb; extern crate aaaaa; fn main() {}")
- .file("a/Cargo.toml", r#"
- [package]
- name = "aaaaa"
- version = "0.0.1"
- authors = []
-
- [dependencies.bbbbb]
- path = "../b"
- "#)
- .file("a/src/lib.rs", "extern crate bbbbb;")
- .file("b/Cargo.toml", r#"
- [package]
- name = "bbbbb"
- version = "0.0.1"
- authors = []
- "#)
- .file("b/src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(101)
- .with_stderr_contains("\
-[..] can't find crate for `bbbbb`[..]
-"));
-}
-
-#[test]
-fn cyclic_deps_rejected() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies.a]
- path = "a"
- "#)
- .file("src/lib.rs", "")
- .file("a/Cargo.toml", r#"
- [package]
- name = "a"
- version = "0.0.1"
- authors = []
-
- [dependencies.foo]
- path = ".."
- "#)
- .file("a/src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(101)
- .with_stderr("\
-[ERROR] cyclic package dependency: package `a v0.0.1 ([..])` depends on itself
-"));
-}
-
-#[test]
-fn predictable_filenames() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [lib]
- name = "foo"
- crate-type = ["dylib", "rlib"]
- "#)
- .file("src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(0));
- assert_that(&p.root().join("target/debug/libfoo.rlib"), existing_file());
- let dylib_name = format!("{}foo{}", env::consts::DLL_PREFIX,
- env::consts::DLL_SUFFIX);
- assert_that(&p.root().join("target/debug").join(dylib_name),
- existing_file());
-}
-
-#[test]
-fn dashes_to_underscores() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo-bar"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/lib.rs", "")
- .file("src/main.rs", "extern crate foo_bar; fn main() {}")
- .build();
-
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(0));
- assert_that(&p.bin("foo-bar"), existing_file());
-}
-
-#[test]
-fn dashes_in_crate_name_bad() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [lib]
- name = "foo-bar"
- "#)
- .file("src/lib.rs", "")
- .file("src/main.rs", "extern crate foo_bar; fn main() {}")
- .build();
-
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(101));
-}
-
-#[test]
-fn rustc_env_var() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build")
- .env("RUSTC", "rustc-that-does-not-exist").arg("-v"),
- execs().with_status(101)
- .with_stderr("\
-[ERROR] could not execute process `rustc-that-does-not-exist -vV` ([..])
-
-Caused by:
-[..]
-"));
- assert_that(&p.bin("a"), is_not(existing_file()));
-}
-
-#[test]
-fn filtering() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/lib.rs", "")
- .file("src/bin/a.rs", "fn main() {}")
- .file("src/bin/b.rs", "fn main() {}")
- .file("examples/a.rs", "fn main() {}")
- .file("examples/b.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("build").arg("--lib"),
- execs().with_status(0));
- assert_that(&p.bin("a"), is_not(existing_file()));
-
- assert_that(p.cargo("build").arg("--bin=a").arg("--example=a"),
- execs().with_status(0));
- assert_that(&p.bin("a"), existing_file());
- assert_that(&p.bin("b"), is_not(existing_file()));
- assert_that(&p.bin("examples/a"), existing_file());
- assert_that(&p.bin("examples/b"), is_not(existing_file()));
-}
-
-#[test]
-fn filtering_implicit_bins() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/lib.rs", "")
- .file("src/bin/a.rs", "fn main() {}")
- .file("src/bin/b.rs", "fn main() {}")
- .file("examples/a.rs", "fn main() {}")
- .file("examples/b.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("build").arg("--bins"),
- execs().with_status(0));
- assert_that(&p.bin("a"), existing_file());
- assert_that(&p.bin("b"), existing_file());
- assert_that(&p.bin("examples/a"), is_not(existing_file()));
- assert_that(&p.bin("examples/b"), is_not(existing_file()));
-}
-
-#[test]
-fn filtering_implicit_examples() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/lib.rs", "")
- .file("src/bin/a.rs", "fn main() {}")
- .file("src/bin/b.rs", "fn main() {}")
- .file("examples/a.rs", "fn main() {}")
- .file("examples/b.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("build").arg("--examples"),
- execs().with_status(0));
- assert_that(&p.bin("a"), is_not(existing_file()));
- assert_that(&p.bin("b"), is_not(existing_file()));
- assert_that(&p.bin("examples/a"), existing_file());
- assert_that(&p.bin("examples/b"), existing_file());
-}
-
-#[test]
-fn ignore_dotfile() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/bin/.a.rs", "")
- .file("src/bin/a.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0));
-}
-
-#[test]
-fn ignore_dotdirs() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/bin/a.rs", "fn main() {}")
- .file(".git/Cargo.toml", "")
- .file(".pc/dummy-fix.patch/Cargo.toml", "")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0));
-}
-
-#[test]
-fn dotdir_root() {
- let p = ProjectBuilder::new("foo", root().join(".foo"))
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/bin/a.rs", "fn main() {}")
- .build();
- assert_that(p.cargo("build"),
- execs().with_status(0));
-}
-
-
-#[test]
-fn custom_target_dir() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- let exe_name = format!("foo{}", env::consts::EXE_SUFFIX);
-
- assert_that(p.cargo("build").env("CARGO_TARGET_DIR", "foo/target"),
- execs().with_status(0));
- assert_that(&p.root().join("foo/target/debug").join(&exe_name),
- existing_file());
- assert_that(&p.root().join("target/debug").join(&exe_name),
- is_not(existing_file()));
-
- assert_that(p.cargo("build"),
- execs().with_status(0));
- assert_that(&p.root().join("foo/target/debug").join(&exe_name),
- existing_file());
- assert_that(&p.root().join("target/debug").join(&exe_name),
- existing_file());
-
- fs::create_dir(p.root().join(".cargo")).unwrap();
- File::create(p.root().join(".cargo/config")).unwrap().write_all(br#"
- [build]
- target-dir = "foo/target"
- "#).unwrap();
- assert_that(p.cargo("build").env("CARGO_TARGET_DIR", "bar/target"),
- execs().with_status(0));
- assert_that(&p.root().join("bar/target/debug").join(&exe_name),
- existing_file());
- assert_that(&p.root().join("foo/target/debug").join(&exe_name),
- existing_file());
- assert_that(&p.root().join("target/debug").join(&exe_name),
- existing_file());
-}
-
-#[test]
-fn rustc_no_trans() {
- if !is_nightly() { return }
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("rustc").arg("-v").arg("--").arg("-Zno-trans"),
- execs().with_status(0));
-}
-
-#[test]
-fn build_multiple_packages() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies.d1]
- path = "d1"
- [dependencies.d2]
- path = "d2"
-
- [[bin]]
- name = "foo"
- "#)
- .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
- .file("d1/Cargo.toml", r#"
- [package]
- name = "d1"
- version = "0.0.1"
- authors = []
-
- [[bin]]
- name = "d1"
- "#)
- .file("d1/src/lib.rs", "")
- .file("d1/src/main.rs", "fn main() { println!(\"d1\"); }")
- .file("d2/Cargo.toml", r#"
- [package]
- name = "d2"
- version = "0.0.1"
- authors = []
-
- [[bin]]
- name = "d2"
- doctest = false
- "#)
- .file("d2/src/main.rs", "fn main() { println!(\"d2\"); }")
- .build();
-
- assert_that(p.cargo("build").arg("-p").arg("d1").arg("-p").arg("d2")
- .arg("-p").arg("foo"),
- execs().with_status(0));
-
- assert_that(&p.bin("foo"), existing_file());
- assert_that(process(&p.bin("foo")),
- execs().with_status(0).with_stdout("i am foo\n"));
-
- let d1_path = &p.build_dir().join("debug")
- .join(format!("d1{}", env::consts::EXE_SUFFIX));
- let d2_path = &p.build_dir().join("debug")
- .join(format!("d2{}", env::consts::EXE_SUFFIX));
-
- assert_that(d1_path, existing_file());
- assert_that(process(d1_path), execs().with_status(0).with_stdout("d1"));
-
- assert_that(d2_path, existing_file());
- assert_that(process(d2_path),
- execs().with_status(0).with_stdout("d2"));
-}
-
-#[test]
-fn invalid_spec() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies.d1]
- path = "d1"
-
- [[bin]]
- name = "foo"
- "#)
- .file("src/bin/foo.rs", &main_file(r#""i am foo""#, &[]))
- .file("d1/Cargo.toml", r#"
- [package]
- name = "d1"
- version = "0.0.1"
- authors = []
-
- [[bin]]
- name = "d1"
- "#)
- .file("d1/src/lib.rs", "")
- .file("d1/src/main.rs", "fn main() { println!(\"d1\"); }")
- .build();
-
- assert_that(p.cargo("build").arg("-p").arg("notAValidDep"),
- execs().with_status(101).with_stderr("\
-[ERROR] package id specification `notAValidDep` matched no packages
-"));
-
- assert_that(p.cargo("build").arg("-p").arg("d1").arg("-p").arg("notAValidDep"),
- execs().with_status(101).with_stderr("\
-[ERROR] package id specification `notAValidDep` matched no packages
-"));
-}
-
-#[test]
-fn manifest_with_bom_is_ok() {
- let p = project("foo")
- .file("Cargo.toml", "\u{FEFF}
- [package]
- name = \"foo\"
- version = \"0.0.1\"
- authors = []
- ")
- .file("src/lib.rs", "")
- .build();
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(0));
-}
-
-#[test]
-fn panic_abort_compiles_with_panic_abort() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [profile.dev]
- panic = 'abort'
- "#)
- .file("src/lib.rs", "")
- .build();
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(0)
- .with_stderr_contains("[..] -C panic=abort [..]"));
-}
-
-#[test]
-fn explicit_color_config_is_propagated_to_rustc() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
-
- name = "test"
- version = "0.0.0"
- authors = []
- "#)
- .file("src/lib.rs", "")
- .build();
- assert_that(p.cargo("build").arg("-v").arg("--color").arg("always"),
- execs().with_status(0).with_stderr_contains(
- "[..]rustc [..] src[/]lib.rs --color always[..]"));
-
- assert_that(p.cargo("clean"), execs().with_status(0));
-
- assert_that(p.cargo("build").arg("-v").arg("--color").arg("never"),
- execs().with_status(0).with_stderr("\
-[COMPILING] test v0.0.0 ([..])
-[RUNNING] `rustc [..] --color never [..]`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-}
-
-#[test]
-fn compiler_json_error_format() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
-
- name = "foo"
- version = "0.5.0"
- authors = ["wycats@example.com"]
-
- [profile.dev]
- debug = false # prevent the *.dSYM from affecting the test result
-
- [dependencies.bar]
- path = "bar"
- "#)
- .file("src/main.rs", "fn main() { let unused = 92; }")
- .file("bar/Cargo.toml", r#"
- [project]
-
- name = "bar"
- version = "0.5.0"
- authors = ["wycats@example.com"]
- "#)
- .file("bar/src/lib.rs", r#"fn dead() {}"#)
- .build();
-
- assert_that(p.cargo("build").arg("-v")
- .arg("--message-format").arg("json"),
- execs().with_status(0).with_json(r#"
- {
- "reason":"compiler-message",
- "package_id":"bar 0.5.0 ([..])",
- "target":{
- "kind":["lib"],
- "crate_types":["lib"],
- "name":"bar",
- "src_path":"[..]lib.rs"
- },
- "message":"{...}"
- }
-
- {
- "reason":"compiler-artifact",
- "profile": {
- "debug_assertions": true,
- "debuginfo": null,
- "opt_level": "0",
- "overflow_checks": true,
- "test": false
- },
- "features": [],
- "package_id":"bar 0.5.0 ([..])",
- "target":{
- "kind":["lib"],
- "crate_types":["lib"],
- "name":"bar",
- "src_path":"[..]lib.rs"
- },
- "filenames":["[..].rlib"],
- "fresh": false
- }
-
- {
- "reason":"compiler-message",
- "package_id":"foo 0.5.0 ([..])",
- "target":{
- "kind":["bin"],
- "crate_types":["bin"],
- "name":"foo",
- "src_path":"[..]main.rs"
- },
- "message":"{...}"
- }
-
- {
- "reason":"compiler-artifact",
- "package_id":"foo 0.5.0 ([..])",
- "target":{
- "kind":["bin"],
- "crate_types":["bin"],
- "name":"foo",
- "src_path":"[..]main.rs"
- },
- "profile": {
- "debug_assertions": true,
- "debuginfo": null,
- "opt_level": "0",
- "overflow_checks": true,
- "test": false
- },
- "features": [],
- "filenames": ["[..]"],
- "fresh": false
- }
-"#));
-
- // With fresh build, we should repeat the artifacts,
- // but omit compiler warnings.
- assert_that(p.cargo("build").arg("-v")
- .arg("--message-format").arg("json"),
- execs().with_status(0).with_json(r#"
- {
- "reason":"compiler-artifact",
- "profile": {
- "debug_assertions": true,
- "debuginfo": null,
- "opt_level": "0",
- "overflow_checks": true,
- "test": false
- },
- "features": [],
- "package_id":"bar 0.5.0 ([..])",
- "target":{
- "kind":["lib"],
- "crate_types":["lib"],
- "name":"bar",
- "src_path":"[..]lib.rs"
- },
- "filenames":["[..].rlib"],
- "fresh": true
- }
-
- {
- "reason":"compiler-artifact",
- "package_id":"foo 0.5.0 ([..])",
- "target":{
- "kind":["bin"],
- "crate_types":["bin"],
- "name":"foo",
- "src_path":"[..]main.rs"
- },
- "profile": {
- "debug_assertions": true,
- "debuginfo": null,
- "opt_level": "0",
- "overflow_checks": true,
- "test": false
- },
- "features": [],
- "filenames": ["[..]"],
- "fresh": true
- }
-"#));
-}
-
-#[test]
-fn wrong_message_format_option() {
- let p = project("foo")
- .file("Cargo.toml", &basic_bin_manifest("foo"))
- .file("src/main.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("build").arg("--message-format").arg("XML"),
- execs().with_status(1)
- .with_stderr_contains(
-r#"[ERROR] Could not match 'xml' with any of the allowed variants: ["Human", "Json"]"#));
-}
-
-#[test]
-fn message_format_json_forward_stderr() {
- let p = project("foo")
- .file("Cargo.toml", &basic_bin_manifest("foo"))
- .file("src/main.rs", "fn main() { let unused = 0; }")
- .build();
-
- assert_that(p.cargo("rustc").arg("--release").arg("--bin").arg("foo")
- .arg("--message-format").arg("JSON"),
- execs().with_status(0)
- .with_json(r#"
- {
- "reason":"compiler-message",
- "package_id":"foo 0.5.0 ([..])",
- "target":{
- "kind":["bin"],
- "crate_types":["bin"],
- "name":"foo",
- "src_path":"[..]"
- },
- "message":"{...}"
- }
-
- {
- "reason":"compiler-artifact",
- "package_id":"foo 0.5.0 ([..])",
- "target":{
- "kind":["bin"],
- "crate_types":["bin"],
- "name":"foo",
- "src_path":"[..]"
- },
- "profile":{
- "debug_assertions":false,
- "debuginfo":null,
- "opt_level":"3",
- "overflow_checks": false,
- "test":false
- },
- "features":[],
- "filenames":["[..]"],
- "fresh": false
- }
-"#));
-}
-
-#[test]
-fn no_warn_about_package_metadata() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [package.metadata]
- foo = "bar"
- a = true
- b = 3
-
- [package.metadata.another]
- bar = 3
- "#)
- .file("src/lib.rs", "")
- .build();
- assert_that(p.cargo("build"),
- execs().with_status(0)
- .with_stderr("[..] foo v0.0.1 ([..])\n\
- [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]\n"));
-}
-
-#[test]
-fn cargo_build_empty_target() {
- let p = project("foo")
- .file("Cargo.toml", &basic_bin_manifest("foo"))
- .file("src/main.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("build").arg("--target").arg(""),
- execs().with_status(101)
- .with_stderr_contains("[..] target was empty"));
-}
-
-#[test]
-fn build_all_workspace() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.1.0"
-
- [dependencies]
- bar = { path = "bar" }
-
- [workspace]
- "#)
- .file("src/main.rs", r#"
- fn main() {}
- "#)
- .file("bar/Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.1.0"
- "#)
- .file("bar/src/lib.rs", r#"
- pub fn bar() {}
- "#)
- .build();
-
- assert_that(p.cargo("build")
- .arg("--all"),
- execs().with_status(0)
- .with_stderr("[..] Compiling bar v0.1.0 ([..])\n\
- [..] Compiling foo v0.1.0 ([..])\n\
- [..] Finished dev [unoptimized + debuginfo] target(s) in [..]\n"));
-}
-
-#[test]
-fn build_all_exclude() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.1.0"
-
- [workspace]
- members = ["bar", "baz"]
- "#)
- .file("src/main.rs", r#"
- fn main() {}
- "#)
- .file("bar/Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.1.0"
- "#)
- .file("bar/src/lib.rs", r#"
- pub fn bar() {}
- "#)
- .file("baz/Cargo.toml", r#"
- [project]
- name = "baz"
- version = "0.1.0"
- "#)
- .file("baz/src/lib.rs", r#"
- pub fn baz() {
- break_the_build();
- }
- "#)
- .build();
-
- assert_that(p.cargo("build")
- .arg("--all")
- .arg("--exclude")
- .arg("baz"),
- execs().with_status(0)
- .with_stderr_contains("[..]Compiling foo v0.1.0 [..]")
- .with_stderr_contains("[..]Compiling bar v0.1.0 [..]")
- .with_stderr_does_not_contain("[..]Compiling baz v0.1.0 [..]"));
-}
-
-#[test]
-fn build_all_workspace_implicit_examples() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.1.0"
-
- [dependencies]
- bar = { path = "bar" }
-
- [workspace]
- "#)
- .file("src/lib.rs", "")
- .file("src/bin/a.rs", "fn main() {}")
- .file("src/bin/b.rs", "fn main() {}")
- .file("examples/c.rs", "fn main() {}")
- .file("examples/d.rs", "fn main() {}")
- .file("bar/Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.1.0"
- "#)
- .file("bar/src/lib.rs", "")
- .file("bar/src/bin/e.rs", "fn main() {}")
- .file("bar/src/bin/f.rs", "fn main() {}")
- .file("bar/examples/g.rs", "fn main() {}")
- .file("bar/examples/h.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("build")
- .arg("--all").arg("--examples"),
- execs().with_status(0)
- .with_stderr("[..] Compiling bar v0.1.0 ([..])\n\
- [..] Compiling foo v0.1.0 ([..])\n\
- [..] Finished dev [unoptimized + debuginfo] target(s) in [..]\n"));
- assert_that(&p.bin("a"), is_not(existing_file()));
- assert_that(&p.bin("b"), is_not(existing_file()));
- assert_that(&p.bin("examples/c"), existing_file());
- assert_that(&p.bin("examples/d"), existing_file());
- assert_that(&p.bin("e"), is_not(existing_file()));
- assert_that(&p.bin("f"), is_not(existing_file()));
- assert_that(&p.bin("examples/g"), existing_file());
- assert_that(&p.bin("examples/h"), existing_file());
-}
-
-#[test]
-fn build_all_virtual_manifest() {
- let p = project("workspace")
- .file("Cargo.toml", r#"
- [workspace]
- members = ["foo", "bar"]
- "#)
- .file("foo/Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.1.0"
- "#)
- .file("foo/src/lib.rs", r#"
- pub fn foo() {}
- "#)
- .file("bar/Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.1.0"
- "#)
- .file("bar/src/lib.rs", r#"
- pub fn bar() {}
- "#)
- .build();
-
- // The order in which foo and bar are built is not guaranteed
- assert_that(p.cargo("build")
- .arg("--all"),
- execs().with_status(0)
- .with_stderr_contains("[..] Compiling bar v0.1.0 ([..])")
- .with_stderr_contains("[..] Compiling foo v0.1.0 ([..])")
- .with_stderr("[..] Compiling [..] v0.1.0 ([..])\n\
- [..] Compiling [..] v0.1.0 ([..])\n\
- [..] Finished dev [unoptimized + debuginfo] target(s) in [..]\n"));
-}
-
-#[test]
-fn build_virtual_manifest_all_implied() {
- let p = project("workspace")
- .file("Cargo.toml", r#"
- [workspace]
- members = ["foo", "bar"]
- "#)
- .file("foo/Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.1.0"
- "#)
- .file("foo/src/lib.rs", r#"
- pub fn foo() {}
- "#)
- .file("bar/Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.1.0"
- "#)
- .file("bar/src/lib.rs", r#"
- pub fn bar() {}
- "#)
- .build();
-
- // The order in which foo and bar are built is not guaranteed
- assert_that(p.cargo("build"),
- execs().with_status(0)
- .with_stderr_contains("[..] Compiling bar v0.1.0 ([..])")
- .with_stderr_contains("[..] Compiling foo v0.1.0 ([..])")
- .with_stderr("[..] Compiling [..] v0.1.0 ([..])\n\
- [..] Compiling [..] v0.1.0 ([..])\n\
- [..] Finished dev [unoptimized + debuginfo] target(s) in [..]\n"));
-}
-
-#[test]
-fn build_virtual_manifest_one_project() {
- let p = project("workspace")
- .file("Cargo.toml", r#"
- [workspace]
- members = ["foo", "bar"]
- "#)
- .file("foo/Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.1.0"
- "#)
- .file("foo/src/lib.rs", r#"
- pub fn foo() {}
- "#)
- .file("bar/Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.1.0"
- "#)
- .file("bar/src/lib.rs", r#"
- pub fn bar() {}
- "#)
- .build();
-
- assert_that(p.cargo("build")
- .arg("-p").arg("foo"),
- execs().with_status(0)
- .with_stderr_does_not_contain("bar")
- .with_stderr_contains("[..] Compiling foo v0.1.0 ([..])")
- .with_stderr("[..] Compiling [..] v0.1.0 ([..])\n\
- [..] Finished dev [unoptimized + debuginfo] target(s) in [..]\n"));
-}
-
-#[test]
-fn build_all_virtual_manifest_implicit_examples() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [workspace]
- members = ["foo", "bar"]
- "#)
- .file("foo/Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.1.0"
- "#)
- .file("foo/src/lib.rs", "")
- .file("foo/src/bin/a.rs", "fn main() {}")
- .file("foo/src/bin/b.rs", "fn main() {}")
- .file("foo/examples/c.rs", "fn main() {}")
- .file("foo/examples/d.rs", "fn main() {}")
- .file("bar/Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.1.0"
- "#)
- .file("bar/src/lib.rs", "")
- .file("bar/src/bin/e.rs", "fn main() {}")
- .file("bar/src/bin/f.rs", "fn main() {}")
- .file("bar/examples/g.rs", "fn main() {}")
- .file("bar/examples/h.rs", "fn main() {}")
- .build();
-
- // The order in which foo and bar are built is not guaranteed
- assert_that(p.cargo("build")
- .arg("--all").arg("--examples"),
- execs().with_status(0)
- .with_stderr_contains("[..] Compiling bar v0.1.0 ([..])")
- .with_stderr_contains("[..] Compiling foo v0.1.0 ([..])")
- .with_stderr("[..] Compiling [..] v0.1.0 ([..])\n\
- [..] Compiling [..] v0.1.0 ([..])\n\
- [..] Finished dev [unoptimized + debuginfo] target(s) in [..]\n"));
- assert_that(&p.bin("a"), is_not(existing_file()));
- assert_that(&p.bin("b"), is_not(existing_file()));
- assert_that(&p.bin("examples/c"), existing_file());
- assert_that(&p.bin("examples/d"), existing_file());
- assert_that(&p.bin("e"), is_not(existing_file()));
- assert_that(&p.bin("f"), is_not(existing_file()));
- assert_that(&p.bin("examples/g"), existing_file());
- assert_that(&p.bin("examples/h"), existing_file());
-}
-
-#[test]
-fn build_all_member_dependency_same_name() {
- let p = project("workspace")
- .file("Cargo.toml", r#"
- [workspace]
- members = ["a"]
- "#)
- .file("a/Cargo.toml", r#"
- [project]
- name = "a"
- version = "0.1.0"
-
- [dependencies]
- a = "0.1.0"
- "#)
- .file("a/src/lib.rs", r#"
- pub fn a() {}
- "#)
- .build();
-
- Package::new("a", "0.1.0").publish();
-
- assert_that(p.cargo("build")
- .arg("--all"),
- execs().with_status(0)
- .with_stderr("[..] Updating registry `[..]`\n\
- [..] Downloading a v0.1.0 ([..])\n\
- [..] Compiling a v0.1.0\n\
- [..] Compiling a v0.1.0 ([..])\n\
- [..] Finished dev [unoptimized + debuginfo] target(s) in [..]\n"));
-}
-
-#[test]
-fn run_proper_binary() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- authors = []
- version = "0.0.0"
- [[bin]]
- name = "main"
- [[bin]]
- name = "other"
- "#)
- .file("src/lib.rs", "")
- .file("src/bin/main.rs", r#"
- fn main() {
- panic!("This should never be run.");
- }
- "#)
- .file("src/bin/other.rs", r#"
- fn main() {
- }
- "#)
- .build();
-
- assert_that(p.cargo("run").arg("--bin").arg("other"),
- execs().with_status(0));
-}
-
-#[test]
-fn run_proper_binary_main_rs() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- authors = []
- version = "0.0.0"
- [[bin]]
- name = "foo"
- "#)
- .file("src/lib.rs", "")
- .file("src/bin/main.rs", r#"
- fn main() {
- }
- "#)
- .build();
-
- assert_that(p.cargo("run").arg("--bin").arg("foo"),
- execs().with_status(0));
-}
-
-#[test]
-fn run_proper_alias_binary_from_src() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- authors = []
- version = "0.0.0"
- [[bin]]
- name = "foo"
- [[bin]]
- name = "bar"
- "#)
- .file("src/foo.rs", r#"
- fn main() {
- println!("foo");
- }
- "#).file("src/bar.rs", r#"
- fn main() {
- println!("bar");
- }
- "#)
- .build();
-
- assert_that(p.cargo("build")
- .arg("--all"),
- execs().with_status(0)
- );
- assert_that(process(&p.bin("foo")),
- execs().with_status(0).with_stdout("foo\n"));
- assert_that(process(&p.bin("bar")),
- execs().with_status(0).with_stdout("bar\n"));
-}
-
-#[test]
-fn run_proper_alias_binary_main_rs() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- authors = []
- version = "0.0.0"
- [[bin]]
- name = "foo"
- [[bin]]
- name = "bar"
- "#)
- .file("src/main.rs", r#"
- fn main() {
- println!("main");
- }
- "#)
- .build();
-
- assert_that(p.cargo("build")
- .arg("--all"),
- execs().with_status(0)
- );
- assert_that(process(&p.bin("foo")),
- execs().with_status(0).with_stdout("main\n"));
- assert_that(process(&p.bin("bar")),
- execs().with_status(0).with_stdout("main\n"));
-}
-
-#[test]
-fn run_proper_binary_main_rs_as_foo() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- authors = []
- version = "0.0.0"
- [[bin]]
- name = "foo"
- "#)
- .file("src/foo.rs", r#"
- fn main() {
- panic!("This should never be run.");
- }
- "#)
- .file("src/main.rs", r#"
- fn main() {
- }
- "#)
- .build();
-
- assert_that(p.cargo("run").arg("--bin").arg("foo"),
- execs().with_status(0));
-}
-
-#[test]
-fn rustc_wrapper() {
- // We don't have /usr/bin/env on Windows.
- if cfg!(windows) { return }
-
- let p = project("foo")
- .file("Cargo.toml", &basic_bin_manifest("foo"))
- .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
- .build();
-
- assert_that(p.cargo("build").arg("-v").env("RUSTC_WRAPPER", "/usr/bin/env"),
- execs().with_stderr_contains(
- "[RUNNING] `/usr/bin/env rustc --crate-name foo [..]")
- .with_status(0));
-}
-
-#[test]
-fn cdylib_not_lifted() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- authors = []
- version = "0.1.0"
-
- [lib]
- crate-type = ["cdylib"]
- "#)
- .file("src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build"), execs().with_status(0));
-
- let files = if cfg!(windows) {
- vec!["foo.dll.lib", "foo.dll.exp", "foo.dll"]
- } else if cfg!(target_os = "macos") {
- vec!["libfoo.dylib"]
- } else {
- vec!["libfoo.so"]
- };
-
- for file in files {
- println!("checking: {}", file);
- assert_that(&p.root().join("target/debug/deps").join(&file),
- existing_file());
- }
-}
-
-#[test]
-fn cdylib_final_outputs() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo-bar"
- authors = []
- version = "0.1.0"
-
- [lib]
- crate-type = ["cdylib"]
- "#)
- .file("src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build"), execs().with_status(0));
-
- let files = if cfg!(windows) {
- vec!["foo_bar.dll.lib", "foo_bar.dll"]
- } else if cfg!(target_os = "macos") {
- vec!["libfoo_bar.dylib"]
- } else {
- vec!["libfoo_bar.so"]
- };
-
- for file in files {
- println!("checking: {}", file);
- assert_that(&p.root().join("target/debug").join(&file), existing_file());
- }
-}
-
-#[test]
-fn deterministic_cfg_flags() {
- // This bug is non-deterministic
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.1.0"
- authors = []
- build = "build.rs"
-
- [features]
- default = ["f_a", "f_b", "f_c", "f_d"]
- f_a = []
- f_b = []
- f_c = []
- f_d = []
- "#)
- .file("build.rs", r#"
- fn main() {
- println!("cargo:rustc-cfg=cfg_a");
- println!("cargo:rustc-cfg=cfg_b");
- println!("cargo:rustc-cfg=cfg_c");
- println!("cargo:rustc-cfg=cfg_d");
- println!("cargo:rustc-cfg=cfg_e");
- }
- "#)
- .file("src/main.rs", r#"
- fn main() {}
- "#)
- .build();
-
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(0)
- .with_stderr("\
-[COMPILING] foo v0.1.0 [..]
-[RUNNING] [..]
-[RUNNING] [..]
-[RUNNING] `rustc --crate-name foo [..] \
---cfg[..]default[..]--cfg[..]f_a[..]--cfg[..]f_b[..]\
---cfg[..]f_c[..]--cfg[..]f_d[..] \
---cfg cfg_a --cfg cfg_b --cfg cfg_c --cfg cfg_d --cfg cfg_e`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]"));
-}
-
-#[test]
-fn explicit_bins_without_paths() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
-
- [[bin]]
- name = "foo"
-
- [[bin]]
- name = "bar"
- "#)
- .file("src/lib.rs", "")
- .file("src/main.rs", "fn main() {}")
- .file("src/bin/bar.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("build"), execs().with_status(0));
-}
-
-#[test]
-fn no_bin_in_src_with_lib() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
-
- [[bin]]
- name = "foo"
- "#)
- .file("src/lib.rs", "")
- .file("src/foo.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(101)
- .with_stderr_contains("\
-[ERROR] failed to parse manifest at `[..]`
-
-Caused by:
- can't find `foo` bin, specify bin.path"));
-}
-
-
-#[test]
-fn inferred_bins() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
- "#)
- .file("src/main.rs", "fn main() {}")
- .file("src/bin/bar.rs", "fn main() {}")
- .file("src/bin/baz/main.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("build"), execs().with_status(0));
- assert_that(&p.bin("foo"), existing_file());
- assert_that(&p.bin("bar"), existing_file());
- assert_that(&p.bin("baz"), existing_file());
-}
-
-#[test]
-fn inferred_bins_duplicate_name() {
- // this should fail, because we have two binaries with the same name
- let p = project("bar")
- .file("Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.1.0"
- authors = []
- "#)
- .file("src/main.rs", "fn main() {}")
- .file("src/bin/foo.rs", "fn main() {}")
- .file("src/bin/foo/main.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(101)
- .with_stderr_contains("\
-[..]found duplicate binary name foo, but all binary targets must have a unique name[..]
-"));
-}
-
-#[test]
-fn inferred_bin_path() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
-
- [[bin]]
- name = "bar"
- # Note, no `path` key!
- "#)
- .file("src/bin/bar/main.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("build"), execs().with_status(0));
- assert_that(&p.bin("bar"), existing_file());
-}
-
-#[test]
-fn inferred_examples() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
- "#)
- .file("src/lib.rs", "fn main() {}")
- .file("examples/bar.rs", "fn main() {}")
- .file("examples/baz/main.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("test"), execs().with_status(0));
- assert_that(&p.bin("examples/bar"), existing_file());
- assert_that(&p.bin("examples/baz"), existing_file());
-}
-
-#[test]
-fn inferred_tests() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
- "#)
- .file("src/lib.rs", "fn main() {}")
- .file("tests/bar.rs", "fn main() {}")
- .file("tests/baz/main.rs", "fn main() {}")
- .build();
-
- assert_that(
- p.cargo("test").arg("--test=bar").arg("--test=baz"),
- execs().with_status(0));
-}
-
-#[test]
-fn inferred_benchmarks() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
- "#)
- .file("src/lib.rs", "fn main() {}")
- .file("benches/bar.rs", "fn main() {}")
- .file("benches/baz/main.rs", "fn main() {}")
- .build();
-
- assert_that(
- p.cargo("bench").arg("--bench=bar").arg("--bench=baz"),
- execs().with_status(0));
-}
-
-#[test]
-fn same_metadata_different_directory() {
- // A top-level crate built in two different workspaces should have the
- // same metadata hash.
- let p = project("foo1")
- .file("Cargo.toml", &basic_bin_manifest("foo"))
- .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
- .build();
- let output = t!(String::from_utf8(
- t!(p.cargo("build").arg("-v").exec_with_output())
- .stderr,
- ));
- let metadata = output
- .split_whitespace()
- .find(|arg| arg.starts_with("metadata="))
- .unwrap();
-
- let p = project("foo2")
- .file("Cargo.toml", &basic_bin_manifest("foo"))
- .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
- .build();
-
- assert_that(
- p.cargo("build").arg("-v"),
- execs().with_status(0).with_stderr_contains(
- format!("[..]{}[..]", metadata),
- ),
- );
-}
-
-#[test]
-fn building_a_dependent_crate_witout_bin_should_fail() {
- Package::new("testless", "0.1.0")
- .file("Cargo.toml", r#"
- [project]
- name = "testless"
- version = "0.1.0"
-
- [[bin]]
- name = "a_bin"
- "#)
- .file("src/lib.rs", "")
- .publish();
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.1.0"
-
- [dependencies]
- testless = "0.1.0"
- "#)
- .file("src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(101).with_stderr_contains(
- "[..]can't find `a_bin` bin, specify bin.path"
- ));
-}
-
-#[test]
-fn uplift_dsym_of_bin_on_mac() {
- if !cfg!(any(target_os = "macos", target_os = "ios")) {
- return
- }
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.1.0"
- "#)
- .file("src/main.rs", "fn main() { panic!(); }")
- .file("src/bin/b.rs", "fn main() { panic!(); }")
- .file("examples/c.rs", "fn main() { panic!(); }")
- .file("tests/d.rs", "fn main() { panic!(); }")
- .build();
-
- assert_that(
- p.cargo("build").arg("--bins").arg("--examples").arg("--tests"),
- execs().with_status(0)
- );
- assert_that(&p.bin("foo.dSYM"), existing_dir());
- assert_that(&p.bin("b.dSYM"), existing_dir());
- assert!(
- p.bin("b.dSYM")
- .symlink_metadata()
- .expect("read metadata from b.dSYM")
- .file_type()
- .is_symlink()
- );
- assert_that(&p.bin("c.dSYM"), is_not(existing_dir()));
- assert_that(&p.bin("d.dSYM"), is_not(existing_dir()));
-}
-
-// Make sure that `cargo build` chooses the correct profile for building
-// targets based on filters (assuming --profile is not specified).
-#[test]
-fn build_filter_infer_profile() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
- "#)
- .file("src/lib.rs", "")
- .file("src/main.rs", "fn main() {}")
- .file("tests/t1.rs", "")
- .file("benches/b1.rs", "")
- .file("examples/ex1.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(0)
- .with_stderr_contains("\
- [RUNNING] `rustc --crate-name foo src[/]lib.rs --crate-type lib \
- --emit=dep-info,link[..]")
- .with_stderr_contains("\
- [RUNNING] `rustc --crate-name foo src[/]main.rs --crate-type bin \
- --emit=dep-info,link[..]")
- );
-
- p.root().join("target").rm_rf();
- assert_that(p.cargo("build").arg("-v").arg("--test=t1"),
- execs().with_status(0)
- .with_stderr_contains("\
- [RUNNING] `rustc --crate-name foo src[/]lib.rs --crate-type lib \
- --emit=dep-info,link[..]")
- .with_stderr_contains("\
- [RUNNING] `rustc --crate-name t1 tests[/]t1.rs --emit=dep-info,link[..]")
- .with_stderr_contains("\
- [RUNNING] `rustc --crate-name foo src[/]main.rs --crate-type bin \
- --emit=dep-info,link[..]")
- );
-
- p.root().join("target").rm_rf();
- assert_that(p.cargo("build").arg("-v").arg("--bench=b1"),
- execs().with_status(0)
- .with_stderr_contains("\
- [RUNNING] `rustc --crate-name foo src[/]lib.rs --crate-type lib \
- --emit=dep-info,link[..]")
- .with_stderr_contains("\
- [RUNNING] `rustc --crate-name b1 benches[/]b1.rs --emit=dep-info,link \
- -C opt-level=3[..]")
- .with_stderr_contains("\
- [RUNNING] `rustc --crate-name foo src[/]main.rs --crate-type bin \
- --emit=dep-info,link[..]")
- );
-}
-
-#[test]
-fn all_targets_no_lib() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
- assert_that(p.cargo("build").arg("-v").arg("--all-targets"),
- execs().with_status(0)
- // bin
- .with_stderr_contains("\
- [RUNNING] `rustc --crate-name foo src[/]main.rs --crate-type bin \
- --emit=dep-info,link[..]")
- // bench
- .with_stderr_contains("\
- [RUNNING] `rustc --crate-name foo src[/]main.rs --emit=dep-info,link \
- -C opt-level=3 --test [..]")
- // unit test
- .with_stderr_contains("\
- [RUNNING] `rustc --crate-name foo src[/]main.rs --emit=dep-info,link \
- -C debuginfo=2 --test [..]")
- );
-}
-
-#[test]
-fn no_linkable_target() {
- // Issue 3169. This is currently not an error as per discussion in PR #4797
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
- [dependencies]
- the_lib = { path = "the_lib" }
- "#)
- .file("src/main.rs", "fn main() {}")
- .file("the_lib/Cargo.toml", r#"
- [package]
- name = "the_lib"
- version = "0.1.0"
- [lib]
- name = "the_lib"
- crate-type = ["staticlib"]
- "#)
- .file("the_lib/src/lib.rs", "pub fn foo() {}")
- .build();
- assert_that(p.cargo("build"),
- execs()
- .with_status(0)
- .with_stderr_contains("\
- [WARNING] The package `the_lib` provides no linkable [..] \
-while compiling `foo`. [..] in `the_lib`'s Cargo.toml. [..]"));
-}
+++ /dev/null
-extern crate cargotest;
-extern crate hamcrest;
-
-use cargotest::ChannelChanger;
-use cargotest::support::{project, execs};
-use hamcrest::assert_that;
-
-#[test]
-fn feature_required() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "a"
- version = "0.0.1"
- authors = []
- im-a-teapot = true
- "#)
- .file("src/lib.rs", "")
- .build();
- assert_that(p.cargo("build")
- .masquerade_as_nightly_cargo(),
- execs().with_status(101)
- .with_stderr("\
-error: failed to parse manifest at `[..]`
-
-Caused by:
- the `im-a-teapot` manifest key is unstable and may not work properly in England
-
-Caused by:
- feature `test-dummy-unstable` is required
-
-consider adding `cargo-features = [\"test-dummy-unstable\"]` to the manifest
-"));
-
- assert_that(p.cargo("build"),
- execs().with_status(101)
- .with_stderr("\
-error: failed to parse manifest at `[..]`
-
-Caused by:
- the `im-a-teapot` manifest key is unstable and may not work properly in England
-
-Caused by:
- feature `test-dummy-unstable` is required
-
-this Cargo does not support nightly features, but if you
-switch to nightly channel you can add
-`cargo-features = [\"test-dummy-unstable\"]` to enable this feature
-"));
-}
-
-#[test]
-fn unknown_feature() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- cargo-features = ["foo"]
-
- [package]
- name = "a"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/lib.rs", "")
- .build();
- assert_that(p.cargo("build"),
- execs().with_status(101)
- .with_stderr("\
-error: failed to parse manifest at `[..]`
-
-Caused by:
- unknown cargo feature `foo`
-"));
-}
-
-#[test]
-fn stable_feature_warns() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- cargo-features = ["test-dummy-stable"]
-
- [package]
- name = "a"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/lib.rs", "")
- .build();
- assert_that(p.cargo("build"),
- execs().with_status(0)
- .with_stderr("\
-warning: the cargo feature `test-dummy-stable` is now stable and is no longer \
-necessary to be listed in the manifest
-[COMPILING] a [..]
-[FINISHED] [..]
-"));
-}
-
-#[test]
-fn nightly_feature_requires_nightly() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- cargo-features = ["test-dummy-unstable"]
-
- [package]
- name = "a"
- version = "0.0.1"
- authors = []
- im-a-teapot = true
- "#)
- .file("src/lib.rs", "")
- .build();
- assert_that(p.cargo("build")
- .masquerade_as_nightly_cargo(),
- execs().with_status(0)
- .with_stderr("\
-[COMPILING] a [..]
-[FINISHED] [..]
-"));
-
- assert_that(p.cargo("build"),
- execs().with_status(101)
- .with_stderr("\
-error: failed to parse manifest at `[..]`
-
-Caused by:
- the cargo feature `test-dummy-unstable` requires a nightly version of Cargo, \
- but this is the `stable` channel
-"));
-}
-
-#[test]
-fn nightly_feature_requires_nightly_in_dep() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "b"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- a = { path = "a" }
- "#)
- .file("src/lib.rs", "")
- .file("a/Cargo.toml", r#"
- cargo-features = ["test-dummy-unstable"]
-
- [package]
- name = "a"
- version = "0.0.1"
- authors = []
- im-a-teapot = true
- "#)
- .file("a/src/lib.rs", "")
- .build();
- assert_that(p.cargo("build")
- .masquerade_as_nightly_cargo(),
- execs().with_status(0)
- .with_stderr("\
-[COMPILING] a [..]
-[COMPILING] b [..]
-[FINISHED] [..]
-"));
-
- assert_that(p.cargo("build"),
- execs().with_status(101)
- .with_stderr("\
-error: failed to load source for a dependency on `a`
-
-Caused by:
- Unable to update [..]
-
-Caused by:
- failed to parse manifest at `[..]`
-
-Caused by:
- the cargo feature `test-dummy-unstable` requires a nightly version of Cargo, \
- but this is the `stable` channel
-"));
-}
-
-#[test]
-fn cant_publish() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- cargo-features = ["test-dummy-unstable"]
-
- [package]
- name = "a"
- version = "0.0.1"
- authors = []
- im-a-teapot = true
- "#)
- .file("src/lib.rs", "")
- .build();
- assert_that(p.cargo("build")
- .masquerade_as_nightly_cargo(),
- execs().with_status(0)
- .with_stderr("\
-[COMPILING] a [..]
-[FINISHED] [..]
-"));
-
- assert_that(p.cargo("build"),
- execs().with_status(101)
- .with_stderr("\
-error: failed to parse manifest at `[..]`
-
-Caused by:
- the cargo feature `test-dummy-unstable` requires a nightly version of Cargo, \
- but this is the `stable` channel
-"));
-}
-
-#[test]
-fn z_flags_rejected() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- cargo-features = ["test-dummy-unstable"]
-
- [package]
- name = "a"
- version = "0.0.1"
- authors = []
- im-a-teapot = true
- "#)
- .file("src/lib.rs", "")
- .build();
- assert_that(p.cargo("build")
- .arg("-Zprint-im-a-teapot"),
- execs().with_status(101)
- .with_stderr("\
-error: the `-Z` flag is only accepted on the nightly channel of Cargo
-"));
-
- assert_that(p.cargo("build")
- .masquerade_as_nightly_cargo()
- .arg("-Zarg"),
- execs().with_status(101)
- .with_stderr("\
-error: unknown `-Z` flag specified: arg
-"));
-
- assert_that(p.cargo("build")
- .masquerade_as_nightly_cargo()
- .arg("-Zprint-im-a-teapot"),
- execs().with_status(0)
- .with_stdout("im-a-teapot = true\n")
- .with_stderr("\
-[COMPILING] a [..]
-[FINISHED] [..]
-"));
-}
-
-#[test]
-fn publish_rejected() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- cargo-features = ["test-dummy-unstable"]
-
- [package]
- name = "a"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/lib.rs", "")
- .build();
- assert_that(p.cargo("publish")
- .masquerade_as_nightly_cargo(),
- execs().with_status(101)
- .with_stderr("\
-error: cannot publish crates which activate nightly-only cargo features to crates.io
-"));
-}
+++ /dev/null
-extern crate cargo;
-extern crate cargotest;
-extern crate hamcrest;
-
-use std::env;
-use std::fs::{self, File};
-use std::io::prelude::*;
-use std::path::{Path, PathBuf};
-use std::str;
-
-use cargotest::cargo_process;
-use cargotest::support::paths::{self, CargoPathExt};
-use cargotest::support::{execs, project, Project, basic_bin_manifest};
-use hamcrest::{assert_that, existing_file};
-
-#[cfg_attr(windows,allow(dead_code))]
-enum FakeKind<'a> {
- Executable,
- Symlink{target:&'a Path},
-}
-
-/// Add an empty file with executable flags (and platform-dependent suffix).
-/// TODO: move this to `Project` if other cases using this emerge.
-fn fake_file(proj: Project, dir: &Path, name: &str, kind: &FakeKind) -> Project {
- let path = proj.root().join(dir).join(&format!("{}{}", name,
- env::consts::EXE_SUFFIX));
- path.parent().unwrap().mkdir_p();
- match *kind {
- FakeKind::Executable => {
- File::create(&path).unwrap();
- make_executable(&path);
- },
- FakeKind::Symlink{target} => {
- make_symlink(&path,target);
- }
- }
- return proj;
-
- #[cfg(unix)]
- fn make_executable(p: &Path) {
- use std::os::unix::prelude::*;
-
- let mut perms = fs::metadata(p).unwrap().permissions();
- let mode = perms.mode();
- perms.set_mode(mode | 0o111);
- fs::set_permissions(p, perms).unwrap();
- }
- #[cfg(windows)]
- fn make_executable(_: &Path) {}
- #[cfg(unix)]
- fn make_symlink(p: &Path, t: &Path) {
- ::std::os::unix::fs::symlink(t,p).expect("Failed to create symlink");
- }
- #[cfg(windows)]
- fn make_symlink(_: &Path, _: &Path) {
- panic!("Not supported")
- }
-}
-
-fn path() -> Vec<PathBuf> {
- env::split_paths(&env::var_os("PATH").unwrap_or_default()).collect()
-}
-
-#[test]
-fn list_command_looks_at_path() {
- let proj = project("list-non-overlapping").build();
- let proj = fake_file(proj, Path::new("path-test"), "cargo-1", &FakeKind::Executable);
- let mut pr = cargo_process();
-
- let mut path = path();
- path.push(proj.root().join("path-test"));
- let path = env::join_paths(path.iter()).unwrap();
- let output = pr.arg("-v").arg("--list")
- .env("PATH", &path);
- let output = output.exec_with_output().unwrap();
- let output = str::from_utf8(&output.stdout).unwrap();
- assert!(output.contains("\n 1 "), "missing 1: {}", output);
-}
-
-// windows and symlinks don't currently agree that well
-#[cfg(unix)]
-#[test]
-fn list_command_resolves_symlinks() {
- use cargotest::support::cargo_exe;
-
- let proj = project("list-non-overlapping").build();
- let proj = fake_file(proj, Path::new("path-test"), "cargo-2",
- &FakeKind::Symlink{target:&cargo_exe()});
- let mut pr = cargo_process();
-
- let mut path = path();
- path.push(proj.root().join("path-test"));
- let path = env::join_paths(path.iter()).unwrap();
- let output = pr.arg("-v").arg("--list")
- .env("PATH", &path);
- let output = output.exec_with_output().unwrap();
- let output = str::from_utf8(&output.stdout).unwrap();
- assert!(output.contains("\n 2 "), "missing 2: {}", output);
-}
-
-#[test]
-fn find_closest_biuld_to_build() {
- let mut pr = cargo_process();
- pr.arg("biuld");
-
- assert_that(pr,
- execs().with_status(101)
- .with_stderr("[ERROR] no such subcommand: `biuld`
-
-<tab>Did you mean `build`?
-
-"));
-}
-
-// if a subcommand is more than 3 edit distance away, we don't make a suggestion
-#[test]
-fn find_closest_dont_correct_nonsense() {
- let mut pr = cargo_process();
- pr.arg("there-is-no-way-that-there-is-a-command-close-to-this")
- .cwd(&paths::root());
-
- assert_that(pr,
- execs().with_status(101)
- .with_stderr("[ERROR] no such subcommand: \
- `there-is-no-way-that-there-is-a-command-close-to-this`
-"));
-}
-
-#[test]
-fn displays_subcommand_on_error() {
- let mut pr = cargo_process();
- pr.arg("invalid-command");
-
- assert_that(pr,
- execs().with_status(101)
- .with_stderr("[ERROR] no such subcommand: `invalid-command`
-"));
-}
-
-#[test]
-fn override_cargo_home() {
- let root = paths::root();
- let my_home = root.join("my_home");
- fs::create_dir(&my_home).unwrap();
- File::create(&my_home.join("config")).unwrap().write_all(br#"
- [cargo-new]
- name = "foo"
- email = "bar"
- git = false
- "#).unwrap();
-
- assert_that(cargo_process()
- .arg("new").arg("foo")
- .env("USER", "foo")
- .env("CARGO_HOME", &my_home),
- execs().with_status(0));
-
- let toml = paths::root().join("foo/Cargo.toml");
- let mut contents = String::new();
- File::open(&toml).unwrap().read_to_string(&mut contents).unwrap();
- assert!(contents.contains(r#"authors = ["foo <bar>"]"#));
-}
-
-#[test]
-fn cargo_subcommand_env() {
- use cargotest::support::cargo_exe;
-
- let src = format!(r#"
- use std::env;
-
- fn main() {{
- println!("{{}}", env::var("{}").unwrap());
- }}
- "#, cargo::CARGO_ENV);
-
- let p = project("cargo-envtest")
- .file("Cargo.toml", &basic_bin_manifest("cargo-envtest"))
- .file("src/main.rs", &src)
- .build();
-
- let target_dir = p.target_debug_dir();
-
- assert_that(p.cargo("build"), execs().with_status(0));
- assert_that(&p.bin("cargo-envtest"), existing_file());
-
- let mut pr = cargo_process();
- let cargo = cargo_exe().canonicalize().unwrap();
- let mut path = path();
- path.push(target_dir);
- let path = env::join_paths(path.iter()).unwrap();
-
- assert_that(pr.arg("envtest").env("PATH", &path),
- execs().with_status(0).with_stdout(cargo.to_str().unwrap()));
-}
-
-#[test]
-fn cargo_help() {
- assert_that(cargo_process(),
- execs().with_status(0));
- assert_that(cargo_process().arg("help"),
- execs().with_status(0));
- assert_that(cargo_process().arg("-h"),
- execs().with_status(0));
- assert_that(cargo_process().arg("help").arg("build"),
- execs().with_status(0));
- assert_that(cargo_process().arg("build").arg("-h"),
- execs().with_status(0));
- assert_that(cargo_process().arg("help").arg("-h"),
- execs().with_status(0));
- assert_that(cargo_process().arg("help").arg("help"),
- execs().with_status(0));
-}
-
-#[test]
-fn explain() {
- assert_that(cargo_process().arg("--explain").arg("E0001"),
- execs().with_status(0));
-}
+++ /dev/null
-extern crate cargotest;
-extern crate hamcrest;
-use cargotest::support::{project, execs, basic_bin_manifest};
-use hamcrest::{assert_that};
-
-#[test]
-fn alias_incorrect_config_type() {
- let p = project("foo")
- .file("Cargo.toml", &basic_bin_manifest("foo"))
- .file("src/main.rs", r#"
- fn main() {
- }"#)
- .file(".cargo/config",r#"
- [alias]
- b-cargo-test = 5
- "#)
- .build();
-
- assert_that(p.cargo("b-cargo-test").arg("-v"),
- execs().with_status(101).
- with_stderr_contains("[ERROR] invalid configuration \
-for key `alias.b-cargo-test`
-expected a list, but found a integer for [..]"));
-}
-
-
-#[test]
-fn alias_default_config_overrides_config() {
- let p = project("foo")
- .file("Cargo.toml", &basic_bin_manifest("foo"))
- .file("src/main.rs", r#"
- fn main() {
- }"#)
- .file(".cargo/config",r#"
- [alias]
- b = "not_build"
- "#)
- .build();
-
- assert_that(p.cargo("b").arg("-v"),
- execs().with_status(0).
- with_stderr_contains("[COMPILING] foo v0.5.0 [..]"));
-}
-
-#[test]
-fn alias_config() {
- let p = project("foo")
- .file("Cargo.toml", &basic_bin_manifest("foo"))
- .file("src/main.rs", r#"
- fn main() {
- }"#)
- .file(".cargo/config",r#"
- [alias]
- b-cargo-test = "build"
- "#)
- .build();
-
- assert_that(p.cargo("b-cargo-test").arg("-v"),
- execs().with_status(0).
- with_stderr_contains("[COMPILING] foo v0.5.0 [..]
-[RUNNING] `rustc --crate-name foo [..]"));
-}
-
-#[test]
-fn alias_list_test() {
- let p = project("foo")
- .file("Cargo.toml", &basic_bin_manifest("foo"))
- .file("src/main.rs", r#"
- fn main() {
- }"#)
- .file(".cargo/config",r#"
- [alias]
- b-cargo-test = ["build", "--release"]
- "#)
- .build();
-
- assert_that(p.cargo("b-cargo-test").arg("-v"),
- execs().with_status(0).
- with_stderr_contains("[COMPILING] foo v0.5.0 [..]").
- with_stderr_contains("[RUNNING] `rustc --crate-name [..]")
- );
-}
-
-#[test]
-fn alias_with_flags_config() {
- let p = project("foo")
- .file("Cargo.toml", &basic_bin_manifest("foo"))
- .file("src/main.rs", r#"
- fn main() {
- }"#)
- .file(".cargo/config",r#"
- [alias]
- b-cargo-test = "build --release"
- "#)
- .build();
-
- assert_that(p.cargo("b-cargo-test").arg("-v"),
- execs().with_status(0).
- with_stderr_contains("[COMPILING] foo v0.5.0 [..]").
- with_stderr_contains("[RUNNING] `rustc --crate-name foo [..]")
- );
-}
-
-#[test]
-fn cant_shadow_builtin() {
- let p = project("foo")
- .file("Cargo.toml", &basic_bin_manifest("foo"))
- .file("src/main.rs", r#"
- fn main() {
- }"#)
- .file(".cargo/config",r#"
- [alias]
- build = "fetch"
- "#)
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0)
- .with_stderr("\
-[COMPILING] foo v0.5.0 ([..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-}
+++ /dev/null
-[package]
-name = "cargotest"
-version = "0.1.0"
-authors = ["Alex Crichton <alex@alexcrichton.com>"]
-
-[lib]
-path = "lib.rs"
-
-[dependencies]
-cargo = { path = "../.." }
-filetime = "0.1"
-flate2 = "1.0"
-git2 = { version = "0.6", default-features = false }
-hamcrest = "=0.1.1"
-hex = "0.3"
-log = "0.4"
-serde_json = "1.0"
-tar = { version = "0.4", default-features = false }
-url = "1.1"
+++ /dev/null
-use std::fmt;
-use std::path::{PathBuf, Path};
-
-use hamcrest::{Matcher, MatchResult, existing_file};
-use support::paths;
-
-pub use self::InstalledExe as has_installed_exe;
-
-pub fn cargo_home() -> PathBuf {
- paths::home().join(".cargo")
-}
-
-pub struct InstalledExe(pub &'static str);
-
-pub fn exe(name: &str) -> String {
- if cfg!(windows) {format!("{}.exe", name)} else {name.to_string()}
-}
-
-impl<P: AsRef<Path>> Matcher<P> for InstalledExe {
- fn matches(&self, path: P) -> MatchResult {
- let path = path.as_ref().join("bin").join(exe(self.0));
- existing_file().matches(&path)
- }
-}
-
-impl fmt::Display for InstalledExe {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(f, "installed exe `{}`", self.0)
- }
-}
+++ /dev/null
-#![deny(warnings)]
-
-extern crate cargo;
-extern crate filetime;
-extern crate flate2;
-extern crate git2;
-extern crate hamcrest;
-extern crate hex;
-#[macro_use]
-extern crate serde_json;
-extern crate tar;
-extern crate url;
-
-use std::ffi::OsStr;
-use std::time::Duration;
-
-use cargo::util::Rustc;
-use std::path::PathBuf;
-
-pub mod support;
-pub mod install;
-
-thread_local!(pub static RUSTC: Rustc = Rustc::new(PathBuf::from("rustc"), None).unwrap());
-
-pub fn rustc_host() -> String {
- RUSTC.with(|r| r.host.clone())
-}
-
-pub fn is_nightly() -> bool {
- RUSTC.with(|r| {
- r.verbose_version.contains("-nightly") ||
- r.verbose_version.contains("-dev")
- })
-}
-
-pub fn process<T: AsRef<OsStr>>(t: T) -> cargo::util::ProcessBuilder {
- _process(t.as_ref())
-}
-
-fn _process(t: &OsStr) -> cargo::util::ProcessBuilder {
- let mut p = cargo::util::process(t);
- p.cwd(&support::paths::root())
- .env_remove("CARGO_HOME")
- .env("HOME", support::paths::home())
- .env("CARGO_HOME", support::paths::home().join(".cargo"))
- .env("__CARGO_TEST_ROOT", support::paths::root())
-
- // Force cargo to think it's on the stable channel for all tests, this
- // should hopefully not surprise us as we add cargo features over time and
- // cargo rides the trains.
- .env("__CARGO_TEST_CHANNEL_OVERRIDE_DO_NOT_USE_THIS", "stable")
-
- // For now disable incremental by default as support hasn't ridden to the
- // stable channel yet. Once incremental support hits the stable compiler we
- // can switch this to one and then fix the tests.
- .env("CARGO_INCREMENTAL", "0")
-
- // This env var can switch the git backend from libgit2 to git2-curl, which
- // can tweak error messages and cause some tests to fail, so let's forcibly
- // remove it.
- .env_remove("CARGO_HTTP_CHECK_REVOKE")
-
- .env_remove("__CARGO_DEFAULT_LIB_METADATA")
- .env_remove("RUSTC")
- .env_remove("RUSTDOC")
- .env_remove("RUSTC_WRAPPER")
- .env_remove("RUSTFLAGS")
- .env_remove("XDG_CONFIG_HOME") // see #2345
- .env("GIT_CONFIG_NOSYSTEM", "1") // keep trying to sandbox ourselves
- .env_remove("EMAIL")
- .env_remove("MFLAGS")
- .env_remove("MAKEFLAGS")
- .env_remove("CARGO_MAKEFLAGS")
- .env_remove("GIT_AUTHOR_NAME")
- .env_remove("GIT_AUTHOR_EMAIL")
- .env_remove("GIT_COMMITTER_NAME")
- .env_remove("GIT_COMMITTER_EMAIL")
- .env_remove("CARGO_TARGET_DIR") // we assume 'target'
- .env_remove("MSYSTEM"); // assume cmd.exe everywhere on windows
- return p
-}
-
-pub trait ChannelChanger: Sized {
- fn masquerade_as_nightly_cargo(&mut self) -> &mut Self;
-}
-
-impl ChannelChanger for cargo::util::ProcessBuilder {
- fn masquerade_as_nightly_cargo(&mut self) -> &mut Self {
- self.env("__CARGO_TEST_CHANNEL_OVERRIDE_DO_NOT_USE_THIS", "nightly")
- }
-}
-
-pub fn cargo_process() -> cargo::util::ProcessBuilder {
- process(&support::cargo_exe())
-}
-
-pub fn sleep_ms(ms: u64) {
- std::thread::sleep(Duration::from_millis(ms));
-}
+++ /dev/null
-use std::env;
-use std::process::Command;
-use std::sync::{Once, ONCE_INIT};
-use std::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering};
-
-use support::{project, main_file, basic_bin_manifest};
-
-pub fn disabled() -> bool {
- // First, disable if ./configure requested so
- match env::var("CFG_DISABLE_CROSS_TESTS") {
- Ok(ref s) if *s == "1" => return true,
- _ => {}
- }
-
- // Right now the windows bots cannot cross compile due to the mingw setup,
- // so we disable ourselves on all but macos/linux setups where the rustc
- // install script ensures we have both architectures
- if !(cfg!(target_os = "macos") ||
- cfg!(target_os = "linux") ||
- cfg!(target_env = "msvc")) {
- return true;
- }
-
- // It's not particularly common to have a cross-compilation setup, so
- // try to detect that before we fail a bunch of tests through no fault
- // of the user.
- static CAN_RUN_CROSS_TESTS: AtomicBool = ATOMIC_BOOL_INIT;
- static CHECK: Once = ONCE_INIT;
-
- let cross_target = alternate();
-
- CHECK.call_once(|| {
- let p = project("cross_test")
- .file("Cargo.toml", &basic_bin_manifest("cross_test"))
- .file("src/cross_test.rs", &main_file(r#""testing!""#, &[]))
- .build();
-
- let result = p.cargo("build")
- .arg("--target").arg(&cross_target)
- .exec_with_output();
-
- if result.is_ok() {
- CAN_RUN_CROSS_TESTS.store(true, Ordering::SeqCst);
- }
- });
-
- if CAN_RUN_CROSS_TESTS.load(Ordering::SeqCst) {
- // We were able to compile a simple project, so the user has the
- // necessary std:: bits installed. Therefore, tests should not
- // be disabled.
- return false;
- }
-
- // We can't compile a simple cross project. We want to warn the user
- // by failing a single test and having the remainder of the cross tests
- // pass. We don't use std::sync::Once here because panicing inside its
- // call_once method would poison the Once instance, which is not what
- // we want.
- static HAVE_WARNED: AtomicBool = ATOMIC_BOOL_INIT;
-
- if HAVE_WARNED.swap(true, Ordering::SeqCst) {
- // We are some other test and somebody else is handling the warning.
- // Just disable the current test.
- return true;
- }
-
- // We are responsible for warning the user, which we do by panicing.
- let rustup_available = Command::new("rustup").output().is_ok();
-
- let linux_help = if cfg!(target_os = "linux") {
- "
-
-You may need to install runtime libraries for your Linux distribution as well.".to_string()
- } else {
- "".to_string()
- };
-
- let rustup_help = if rustup_available {
- format!("
-
-Alternatively, you can install the necessary libraries for cross-compilation with
-
- rustup target add {}{}", cross_target, linux_help)
- } else {
- "".to_string()
- };
-
- panic!("Cannot cross compile to {}.
-
-This failure can be safely ignored. If you would prefer to not see this
-failure, you can set the environment variable CFG_DISABLE_CROSS_TESTS to \"1\".{}
-", cross_target, rustup_help);
-}
-
-pub fn alternate() -> String {
- let platform = match env::consts::OS {
- "linux" => "unknown-linux-gnu",
- "macos" => "apple-darwin",
- "windows" => "pc-windows-msvc",
- _ => unreachable!(),
- };
- let arch = match env::consts::ARCH {
- "x86" => "x86_64",
- "x86_64" => "i686",
- _ => unreachable!(),
- };
- format!("{}-{}", arch, platform)
-}
-
-pub fn alternate_arch() -> &'static str {
- match env::consts::ARCH {
- "x86" => "x86_64",
- "x86_64" => "x86",
- _ => unreachable!(),
- }
-}
-
-pub fn host() -> String {
- let platform = match env::consts::OS {
- "linux" => "unknown-linux-gnu",
- "macos" => "apple-darwin",
- "windows" => "pc-windows-msvc",
- _ => unreachable!(),
- };
- let arch = match env::consts::ARCH {
- "x86" => "i686",
- "x86_64" => "x86_64",
- _ => unreachable!(),
- };
- format!("{}-{}", arch, platform)
-}
+++ /dev/null
-use std::fs::{self, File};
-use std::io::prelude::*;
-use std::path::{Path, PathBuf};
-
-use url::Url;
-use git2;
-
-use cargo::util::ProcessError;
-use support::{ProjectBuilder, Project, project, path2url};
-
-#[must_use]
-pub struct RepoBuilder {
- repo: git2::Repository,
- files: Vec<PathBuf>,
-}
-
-pub struct Repository(git2::Repository);
-
-pub fn repo(p: &Path) -> RepoBuilder { RepoBuilder::init(p) }
-
-impl RepoBuilder {
- pub fn init(p: &Path) -> RepoBuilder {
- t!(fs::create_dir_all(p.parent().unwrap()));
- let repo = t!(git2::Repository::init(p));
- {
- let mut config = t!(repo.config());
- t!(config.set_str("user.name", "name"));
- t!(config.set_str("user.email", "email"));
- }
- RepoBuilder { repo: repo, files: Vec::new() }
- }
-
- pub fn file(self, path: &str, contents: &str) -> RepoBuilder {
- let mut me = self.nocommit_file(path, contents);
- me.files.push(PathBuf::from(path));
- me
- }
-
- pub fn nocommit_file(self, path: &str, contents: &str) -> RepoBuilder {
- let dst = self.repo.workdir().unwrap().join(path);
- t!(fs::create_dir_all(dst.parent().unwrap()));
- t!(t!(File::create(&dst)).write_all(contents.as_bytes()));
- self
- }
-
- pub fn build(self) -> Repository {
- {
- let mut index = t!(self.repo.index());
- for file in self.files.iter() {
- t!(index.add_path(file));
- }
- t!(index.write());
- let id = t!(index.write_tree());
- let tree = t!(self.repo.find_tree(id));
- let sig = t!(self.repo.signature());
- t!(self.repo.commit(Some("HEAD"), &sig, &sig,
- "Initial commit", &tree, &[]));
- }
- let RepoBuilder{ repo, .. } = self;
- Repository(repo)
- }
-}
-
-impl Repository {
- pub fn root(&self) -> &Path {
- self.0.workdir().unwrap()
- }
-
- pub fn url(&self) -> Url {
- path2url(self.0.workdir().unwrap().to_path_buf())
- }
-}
-
-pub fn new<F>(name: &str, callback: F) -> Result<Project, ProcessError>
- where F: FnOnce(ProjectBuilder) -> ProjectBuilder
-{
- let mut git_project = project(name);
- git_project = callback(git_project);
- let git_project = git_project.build();
-
- let repo = t!(git2::Repository::init(&git_project.root()));
- let mut cfg = t!(repo.config());
- t!(cfg.set_str("user.email", "foo@bar.com"));
- t!(cfg.set_str("user.name", "Foo Bar"));
- drop(cfg);
- add(&repo);
- commit(&repo);
- Ok(git_project)
-}
-
-pub fn add(repo: &git2::Repository) {
- // FIXME(libgit2/libgit2#2514): apparently add_all will add all submodules
- // as well, and then fail b/c they're a directory. As a stopgap, we just
- // ignore all submodules.
- let mut s = t!(repo.submodules());
- for submodule in s.iter_mut() {
- t!(submodule.add_to_index(false));
- }
- let mut index = t!(repo.index());
- t!(index.add_all(["*"].iter(), git2::ADD_DEFAULT,
- Some(&mut (|a, _b| {
- if s.iter().any(|s| a.starts_with(s.path())) {1} else {0}
- }))));
- t!(index.write());
-}
-
-pub fn add_submodule<'a>(repo: &'a git2::Repository, url: &str,
- path: &Path) -> git2::Submodule<'a>
-{
- let path = path.to_str().unwrap().replace(r"\", "/");
- let mut s = t!(repo.submodule(url, Path::new(&path), false));
- let subrepo = t!(s.open());
- t!(subrepo.remote_add_fetch("origin", "refs/heads/*:refs/heads/*"));
- let mut origin = t!(subrepo.find_remote("origin"));
- t!(origin.fetch(&[], None, None));
- t!(subrepo.checkout_head(None));
- t!(s.add_finalize());
- return s;
-}
-
-pub fn commit(repo: &git2::Repository) -> git2::Oid {
- let tree_id = t!(t!(repo.index()).write_tree());
- let sig = t!(repo.signature());
- let mut parents = Vec::new();
- match repo.head().ok().map(|h| h.target().unwrap()) {
- Some(parent) => parents.push(t!(repo.find_commit(parent))),
- None => {}
- }
- let parents = parents.iter().collect::<Vec<_>>();
- t!(repo.commit(Some("HEAD"), &sig, &sig, "test",
- &t!(repo.find_tree(tree_id)),
- &parents))
-}
-
-pub fn tag(repo: &git2::Repository, name: &str) {
- let head = repo.head().unwrap().target().unwrap();
- t!(repo.tag(name,
- &t!(repo.find_object(head, None)),
- &t!(repo.signature()),
- "make a new tag",
- false));
-}
+++ /dev/null
-use std::env;
-use std::ffi::OsStr;
-use std::fmt;
-use std::fs;
-use std::io::prelude::*;
-use std::os;
-use std::path::{Path, PathBuf};
-use std::process::Output;
-use std::str;
-use std::usize;
-
-use serde_json::{self, Value};
-use url::Url;
-use hamcrest as ham;
-use cargo::util::ProcessBuilder;
-use cargo::util::{ProcessError};
-
-use support::paths::CargoPathExt;
-
-#[macro_export]
-macro_rules! t {
- ($e:expr) => (match $e {
- Ok(e) => e,
- Err(e) => panic!("{} failed with {}", stringify!($e), e),
- })
-}
-
-pub mod paths;
-pub mod git;
-pub mod registry;
-pub mod cross_compile;
-pub mod publish;
-
-/*
- *
- * ===== Builders =====
- *
- */
-
-#[derive(PartialEq,Clone)]
-struct FileBuilder {
- path: PathBuf,
- body: String
-}
-
-impl FileBuilder {
- pub fn new(path: PathBuf, body: &str) -> FileBuilder {
- FileBuilder { path: path, body: body.to_string() }
- }
-
- fn mk(&self) {
- self.dirname().mkdir_p();
-
- let mut file = fs::File::create(&self.path).unwrap_or_else(|e| {
- panic!("could not create file {}: {}", self.path.display(), e)
- });
-
- t!(file.write_all(self.body.as_bytes()));
- }
-
- fn dirname(&self) -> &Path {
- self.path.parent().unwrap()
- }
-}
-
-#[derive(PartialEq,Clone)]
-struct SymlinkBuilder {
- dst: PathBuf,
- src: PathBuf,
-}
-
-impl SymlinkBuilder {
- pub fn new(dst: PathBuf, src: PathBuf) -> SymlinkBuilder {
- SymlinkBuilder { dst: dst, src: src }
- }
-
- #[cfg(unix)]
- fn mk(&self) {
- self.dirname().mkdir_p();
- t!(os::unix::fs::symlink(&self.dst, &self.src));
- }
-
- #[cfg(windows)]
- fn mk(&self) {
- self.dirname().mkdir_p();
- t!(os::windows::fs::symlink_file(&self.dst, &self.src));
- }
-
- fn dirname(&self) -> &Path {
- self.src.parent().unwrap()
- }
-}
-
-#[derive(PartialEq,Clone)]
-pub struct Project{
- root: PathBuf,
-}
-
-#[must_use]
-#[derive(PartialEq,Clone)]
-pub struct ProjectBuilder {
- name: String,
- root: Project,
- files: Vec<FileBuilder>,
- symlinks: Vec<SymlinkBuilder>,
-}
-
-impl ProjectBuilder {
- pub fn root(&self) -> PathBuf {
- self.root.root()
- }
-
- pub fn build_dir(&self) -> PathBuf {
- self.root.build_dir()
- }
-
- pub fn target_debug_dir(&self) -> PathBuf {
- self.root.target_debug_dir()
- }
-
- pub fn new(name: &str, root: PathBuf) -> ProjectBuilder {
- ProjectBuilder {
- name: name.to_string(),
- root: Project{ root },
- files: vec![],
- symlinks: vec![],
- }
- }
-
- pub fn file<B: AsRef<Path>>(mut self, path: B,
- body: &str) -> Self {
- self._file(path.as_ref(), body);
- self
- }
-
- fn _file(&mut self, path: &Path, body: &str) {
- self.files.push(FileBuilder::new(self.root.root.join(path), body));
- }
-
- pub fn symlink<T: AsRef<Path>>(mut self, dst: T,
- src: T) -> Self {
- self.symlinks.push(SymlinkBuilder::new(self.root.root.join(dst),
- self.root.root.join(src)));
- self
- }
-
- pub fn build(self) -> Project {
- // First, clean the directory if it already exists
- self.rm_root();
-
- // Create the empty directory
- self.root.root.mkdir_p();
-
- for file in self.files.iter() {
- file.mk();
- }
-
- for symlink in self.symlinks.iter() {
- symlink.mk();
- }
-
- let ProjectBuilder{ name: _, root, files: _, symlinks: _, .. } = self;
- root
- }
-
- fn rm_root(&self) {
- self.root.root.rm_rf()
- }
-}
-
-impl Project {
- pub fn root(&self) -> PathBuf {
- self.root.clone()
- }
-
- pub fn build_dir(&self) -> PathBuf {
- self.root.join("target")
- }
-
- pub fn target_debug_dir(&self) -> PathBuf {
- self.build_dir().join("debug")
- }
-
- pub fn url(&self) -> Url { path2url(self.root()) }
-
- pub fn example_lib(&self, name: &str, kind: &str) -> PathBuf {
- let prefix = Project::get_lib_prefix(kind);
-
- let extension = Project::get_lib_extension(kind);
-
- let lib_file_name = format!("{}{}.{}",
- prefix,
- name,
- extension);
-
- self.target_debug_dir()
- .join("examples")
- .join(&lib_file_name)
- }
-
- pub fn bin(&self, b: &str) -> PathBuf {
- self.build_dir().join("debug").join(&format!("{}{}", b,
- env::consts::EXE_SUFFIX))
- }
-
- pub fn release_bin(&self, b: &str) -> PathBuf {
- self.build_dir().join("release").join(&format!("{}{}", b,
- env::consts::EXE_SUFFIX))
- }
-
- pub fn target_bin(&self, target: &str, b: &str) -> PathBuf {
- self.build_dir().join(target).join("debug")
- .join(&format!("{}{}", b, env::consts::EXE_SUFFIX))
- }
-
- pub fn change_file(&self, path: &str, body: &str) {
- FileBuilder::new(self.root.join(path), body).mk()
- }
-
- pub fn process<T: AsRef<OsStr>>(&self, program: T) -> ProcessBuilder {
- let mut p = ::process(program);
- p.cwd(self.root());
- return p
- }
-
- pub fn cargo(&self, cmd: &str) -> ProcessBuilder {
- let mut p = self.process(&cargo_exe());
- p.arg(cmd);
- return p;
- }
-
- pub fn read_lockfile(&self) -> String {
- let mut buffer = String::new();
- fs::File::open(self.root().join("Cargo.lock")).unwrap()
- .read_to_string(&mut buffer).unwrap();
- buffer
- }
-
- fn get_lib_prefix(kind: &str) -> &str {
- match kind {
- "lib" | "rlib" => "lib",
- "staticlib" | "dylib" | "proc-macro" => {
- if cfg!(windows) {
- ""
- } else {
- "lib"
- }
- }
- _ => unreachable!()
- }
- }
-
- fn get_lib_extension(kind: &str) -> &str {
- match kind {
- "lib" | "rlib" => "rlib",
- "staticlib" => {
- if cfg!(windows) {
- "lib"
- } else {
- "a"
- }
- }
- "dylib" | "proc-macro" => {
- if cfg!(windows) {
- "dll"
- } else if cfg!(target_os="macos") {
- "dylib"
- } else {
- "so"
- }
- }
- _ => unreachable!()
- }
- }
-}
-
-// Generates a project layout
-pub fn project(name: &str) -> ProjectBuilder {
- ProjectBuilder::new(name, paths::root().join(name))
-}
-
-// Generates a project layout inside our fake home dir
-pub fn project_in_home(name: &str) -> ProjectBuilder {
- ProjectBuilder::new(name, paths::home().join(name))
-}
-
-// === Helpers ===
-
-pub fn main_file(println: &str, deps: &[&str]) -> String {
- let mut buf = String::new();
-
- for dep in deps.iter() {
- buf.push_str(&format!("extern crate {};\n", dep));
- }
-
- buf.push_str("fn main() { println!(");
- buf.push_str(&println);
- buf.push_str("); }\n");
-
- buf.to_string()
-}
-
-trait ErrMsg<T> {
- fn with_err_msg(self, val: String) -> Result<T, String>;
-}
-
-impl<T, E: fmt::Display> ErrMsg<T> for Result<T, E> {
- fn with_err_msg(self, val: String) -> Result<T, String> {
- match self {
- Ok(val) => Ok(val),
- Err(err) => Err(format!("{}; original={}", val, err))
- }
- }
-}
-
-// Path to cargo executables
-pub fn cargo_dir() -> PathBuf {
- env::var_os("CARGO_BIN_PATH").map(PathBuf::from).or_else(|| {
- env::current_exe().ok().map(|mut path| {
- path.pop();
- if path.ends_with("deps") {
- path.pop();
- }
- path
- })
- }).unwrap_or_else(|| {
- panic!("CARGO_BIN_PATH wasn't set. Cannot continue running test")
- })
-}
-
-pub fn cargo_exe() -> PathBuf {
- cargo_dir().join(format!("cargo{}", env::consts::EXE_SUFFIX))
-}
-
-/// Returns an absolute path in the filesystem that `path` points to. The
-/// returned path does not contain any symlinks in its hierarchy.
-/*
- *
- * ===== Matchers =====
- *
- */
-
-#[derive(Clone)]
-pub struct Execs {
- expect_stdout: Option<String>,
- expect_stdin: Option<String>,
- expect_stderr: Option<String>,
- expect_exit_code: Option<i32>,
- expect_stdout_contains: Vec<String>,
- expect_stderr_contains: Vec<String>,
- expect_either_contains: Vec<String>,
- expect_stdout_contains_n: Vec<(String, usize)>,
- expect_stdout_not_contains: Vec<String>,
- expect_stderr_not_contains: Vec<String>,
- expect_neither_contains: Vec<String>,
- expect_json: Option<Vec<Value>>,
-}
-
-impl Execs {
- pub fn with_stdout<S: ToString>(mut self, expected: S) -> Execs {
- self.expect_stdout = Some(expected.to_string());
- self
- }
-
- pub fn with_stderr<S: ToString>(mut self, expected: S) -> Execs {
- self._with_stderr(&expected);
- self
- }
-
- fn _with_stderr(&mut self, expected: &ToString) {
- self.expect_stderr = Some(expected.to_string());
- }
-
- pub fn with_status(mut self, expected: i32) -> Execs {
- self.expect_exit_code = Some(expected);
- self
- }
-
- pub fn with_stdout_contains<S: ToString>(mut self, expected: S) -> Execs {
- self.expect_stdout_contains.push(expected.to_string());
- self
- }
-
- pub fn with_stderr_contains<S: ToString>(mut self, expected: S) -> Execs {
- self.expect_stderr_contains.push(expected.to_string());
- self
- }
-
- pub fn with_either_contains<S: ToString>(mut self, expected: S) -> Execs {
- self.expect_either_contains.push(expected.to_string());
- self
- }
-
- pub fn with_stdout_contains_n<S: ToString>(mut self, expected: S, number: usize) -> Execs {
- self.expect_stdout_contains_n.push((expected.to_string(), number));
- self
- }
-
- pub fn with_stdout_does_not_contain<S: ToString>(mut self, expected: S) -> Execs {
- self.expect_stdout_not_contains.push(expected.to_string());
- self
- }
-
- pub fn with_stderr_does_not_contain<S: ToString>(mut self, expected: S) -> Execs {
- self.expect_stderr_not_contains.push(expected.to_string());
- self
- }
-
- pub fn with_neither_contains<S: ToString>(mut self, expected: S) -> Execs {
- self.expect_neither_contains.push(expected.to_string());
- self
- }
-
- pub fn with_json(mut self, expected: &str) -> Execs {
- self.expect_json = Some(expected.split("\n\n").map(|obj| {
- obj.parse().unwrap()
- }).collect());
- self
- }
-
- fn match_output(&self, actual: &Output) -> ham::MatchResult {
- self.match_status(actual)
- .and(self.match_stdout(actual))
- .and(self.match_stderr(actual))
- }
-
- fn match_status(&self, actual: &Output) -> ham::MatchResult {
- match self.expect_exit_code {
- None => ham::success(),
- Some(code) => {
- ham::expect(
- actual.status.code() == Some(code),
- format!("exited with {}\n--- stdout\n{}\n--- stderr\n{}",
- actual.status,
- String::from_utf8_lossy(&actual.stdout),
- String::from_utf8_lossy(&actual.stderr)))
- }
- }
- }
-
- fn match_stdout(&self, actual: &Output) -> ham::MatchResult {
- self.match_std(self.expect_stdout.as_ref(), &actual.stdout,
- "stdout", &actual.stderr, MatchKind::Exact)?;
- for expect in self.expect_stdout_contains.iter() {
- self.match_std(Some(expect), &actual.stdout, "stdout",
- &actual.stderr, MatchKind::Partial)?;
- }
- for expect in self.expect_stderr_contains.iter() {
- self.match_std(Some(expect), &actual.stderr, "stderr",
- &actual.stdout, MatchKind::Partial)?;
- }
- for &(ref expect, number) in self.expect_stdout_contains_n.iter() {
- self.match_std(Some(&expect), &actual.stdout, "stdout",
- &actual.stderr, MatchKind::PartialN(number))?;
- }
- for expect in self.expect_stdout_not_contains.iter() {
- self.match_std(Some(expect), &actual.stdout, "stdout",
- &actual.stderr, MatchKind::NotPresent)?;
- }
- for expect in self.expect_stderr_not_contains.iter() {
- self.match_std(Some(expect), &actual.stderr, "stderr",
- &actual.stdout, MatchKind::NotPresent)?;
- }
- for expect in self.expect_neither_contains.iter() {
- self.match_std(Some(expect), &actual.stdout, "stdout",
- &actual.stdout, MatchKind::NotPresent)?;
-
- self.match_std(Some(expect), &actual.stderr, "stderr",
- &actual.stderr, MatchKind::NotPresent)?;
- }
-
- for expect in self.expect_either_contains.iter() {
- let match_std = self.match_std(Some(expect), &actual.stdout, "stdout",
- &actual.stdout, MatchKind::Partial);
- let match_err = self.match_std(Some(expect), &actual.stderr, "stderr",
- &actual.stderr, MatchKind::Partial);
-
- if let (Err(_), Err(_)) = (match_std, match_err) {
- Err(format!("expected to find:\n\
- {}\n\n\
- did not find in either output.", expect))?;
- }
- }
-
- if let Some(ref objects) = self.expect_json {
- let stdout = str::from_utf8(&actual.stdout)
- .map_err(|_| "stdout was not utf8 encoded".to_owned())?;
- let lines = stdout.lines().collect::<Vec<_>>();
- if lines.len() != objects.len() {
- return Err(format!("expected {} json lines, got {}, stdout:\n{}",
- objects.len(), lines.len(), stdout));
- }
- for (obj, line) in objects.iter().zip(lines) {
- self.match_json(obj, line)?;
- }
- }
- Ok(())
- }
-
- fn match_stderr(&self, actual: &Output) -> ham::MatchResult {
- self.match_std(self.expect_stderr.as_ref(), &actual.stderr,
- "stderr", &actual.stdout, MatchKind::Exact)
- }
-
- fn match_std(&self, expected: Option<&String>, actual: &[u8],
- description: &str, extra: &[u8],
- kind: MatchKind) -> ham::MatchResult {
- let out = match expected {
- Some(out) => out,
- None => return ham::success(),
- };
- let actual = match str::from_utf8(actual) {
- Err(..) => return Err(format!("{} was not utf8 encoded",
- description)),
- Ok(actual) => actual,
- };
- // Let's not deal with \r\n vs \n on windows...
- let actual = actual.replace("\r", "");
- let actual = actual.replace("\t", "<tab>");
-
- match kind {
- MatchKind::Exact => {
- let a = actual.lines();
- let e = out.lines();
-
- let diffs = self.diff_lines(a, e, false);
- ham::expect(diffs.is_empty(),
- format!("differences:\n\
- {}\n\n\
- other output:\n\
- `{}`", diffs.join("\n"),
- String::from_utf8_lossy(extra)))
- }
- MatchKind::Partial => {
- let mut a = actual.lines();
- let e = out.lines();
-
- let mut diffs = self.diff_lines(a.clone(), e.clone(), true);
- while let Some(..) = a.next() {
- let a = self.diff_lines(a.clone(), e.clone(), true);
- if a.len() < diffs.len() {
- diffs = a;
- }
- }
- ham::expect(diffs.is_empty(),
- format!("expected to find:\n\
- {}\n\n\
- did not find in output:\n\
- {}", out,
- actual))
- }
- MatchKind::PartialN(number) => {
- let mut a = actual.lines();
- let e = out.lines();
-
- let mut matches = 0;
-
- while let Some(..) = {
- if self.diff_lines(a.clone(), e.clone(), true).is_empty() {
- matches += 1;
- }
- a.next()
- } {}
-
- ham::expect(matches == number,
- format!("expected to find {} occurrences:\n\
- {}\n\n\
- did not find in output:\n\
- {}", number, out,
- actual))
- }
- MatchKind::NotPresent => {
- ham::expect(!actual.contains(out),
- format!("expected not to find:\n\
- {}\n\n\
- but found in output:\n\
- {}", out,
- actual))
- }
- }
- }
-
- fn match_json(&self, expected: &Value, line: &str) -> ham::MatchResult {
- let actual = match line.parse() {
- Err(e) => return Err(format!("invalid json, {}:\n`{}`", e, line)),
- Ok(actual) => actual,
- };
-
- match find_mismatch(expected, &actual) {
- Some((expected_part, actual_part)) => Err(format!(
- "JSON mismatch\nExpected:\n{}\nWas:\n{}\nExpected part:\n{}\nActual part:\n{}\n",
- serde_json::to_string_pretty(expected).unwrap(),
- serde_json::to_string_pretty(&actual).unwrap(),
- serde_json::to_string_pretty(expected_part).unwrap(),
- serde_json::to_string_pretty(actual_part).unwrap(),
- )),
- None => Ok(()),
- }
- }
-
- fn diff_lines<'a>(&self, actual: str::Lines<'a>, expected: str::Lines<'a>,
- partial: bool) -> Vec<String> {
- let actual = actual.take(if partial {
- expected.clone().count()
- } else {
- usize::MAX
- });
- zip_all(actual, expected).enumerate().filter_map(|(i, (a,e))| {
- match (a, e) {
- (Some(a), Some(e)) => {
- if lines_match(&e, &a) {
- None
- } else {
- Some(format!("{:3} - |{}|\n + |{}|\n", i, e, a))
- }
- },
- (Some(a), None) => {
- Some(format!("{:3} -\n + |{}|\n", i, a))
- },
- (None, Some(e)) => {
- Some(format!("{:3} - |{}|\n +\n", i, e))
- },
- (None, None) => panic!("Cannot get here")
- }
- }).collect()
- }
-}
-
-#[derive(Debug, PartialEq, Eq, Clone, Copy)]
-enum MatchKind {
- Exact,
- Partial,
- PartialN(usize),
- NotPresent,
-}
-
-pub fn lines_match(expected: &str, mut actual: &str) -> bool {
- let expected = substitute_macros(expected);
- for (i, part) in expected.split("[..]").enumerate() {
- match actual.find(part) {
- Some(j) => {
- if i == 0 && j != 0 {
- return false
- }
- actual = &actual[j + part.len()..];
- }
- None => {
- return false
- }
- }
- }
- actual.is_empty() || expected.ends_with("[..]")
-}
-
-#[test]
-fn lines_match_works() {
- assert!(lines_match("a b", "a b"));
- assert!(lines_match("a[..]b", "a b"));
- assert!(lines_match("a[..]", "a b"));
- assert!(lines_match("[..]", "a b"));
- assert!(lines_match("[..]b", "a b"));
-
- assert!(!lines_match("[..]b", "c"));
- assert!(!lines_match("b", "c"));
- assert!(!lines_match("b", "cb"));
-}
-
-// Compares JSON object for approximate equality.
-// You can use `[..]` wildcard in strings (useful for OS dependent things such
-// as paths). You can use a `"{...}"` string literal as a wildcard for
-// arbitrary nested JSON (useful for parts of object emitted by other programs
-// (e.g. rustc) rather than Cargo itself). Arrays are sorted before comparison.
-fn find_mismatch<'a>(expected: &'a Value, actual: &'a Value)
- -> Option<(&'a Value, &'a Value)> {
- use serde_json::Value::*;
- match (expected, actual) {
- (&Number(ref l), &Number(ref r)) if l == r => None,
- (&Bool(l), &Bool(r)) if l == r => None,
- (&String(ref l), &String(ref r)) if lines_match(l, r) => None,
- (&Array(ref l), &Array(ref r)) => {
- if l.len() != r.len() {
- return Some((expected, actual));
- }
-
- let mut l = l.iter().collect::<Vec<_>>();
- let mut r = r.iter().collect::<Vec<_>>();
-
- l.retain(|l| {
- match r.iter().position(|r| find_mismatch(l, r).is_none()) {
- Some(i) => {
- r.remove(i);
- false
- }
- None => true
- }
- });
-
- if l.len() > 0 {
- assert!(r.len() > 0);
- Some((&l[0], &r[0]))
- } else {
- assert!(r.len() == 0);
- None
- }
- }
- (&Object(ref l), &Object(ref r)) => {
- let same_keys = l.len() == r.len() && l.keys().all(|k| r.contains_key(k));
- if !same_keys {
- return Some((expected, actual));
- }
-
- l.values().zip(r.values())
- .filter_map(|(l, r)| find_mismatch(l, r))
- .nth(0)
- }
- (&Null, &Null) => None,
- // magic string literal "{...}" acts as wildcard for any sub-JSON
- (&String(ref l), _) if l == "{...}" => None,
- _ => Some((expected, actual)),
- }
-
-}
-
-struct ZipAll<I1: Iterator, I2: Iterator> {
- first: I1,
- second: I2,
-}
-
-impl<T, I1: Iterator<Item=T>, I2: Iterator<Item=T>> Iterator for ZipAll<I1, I2> {
- type Item = (Option<T>, Option<T>);
- fn next(&mut self) -> Option<(Option<T>, Option<T>)> {
- let first = self.first.next();
- let second = self.second.next();
-
- match (first, second) {
- (None, None) => None,
- (a, b) => Some((a, b))
- }
- }
-}
-
-fn zip_all<T, I1: Iterator<Item=T>, I2: Iterator<Item=T>>(a: I1, b: I2) -> ZipAll<I1, I2> {
- ZipAll {
- first: a,
- second: b,
- }
-}
-
-impl fmt::Display for Execs {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(f, "execs")
- }
-}
-
-impl ham::Matcher<ProcessBuilder> for Execs {
- fn matches(&self, mut process: ProcessBuilder) -> ham::MatchResult {
- self.matches(&mut process)
- }
-}
-
-impl<'a> ham::Matcher<&'a mut ProcessBuilder> for Execs {
- fn matches(&self, process: &'a mut ProcessBuilder) -> ham::MatchResult {
- println!("running {}", process);
- let res = process.exec_with_output();
-
- match res {
- Ok(out) => self.match_output(&out),
- Err(e) => {
- let err = e.downcast_ref::<ProcessError>();
- if let Some(&ProcessError { output: Some(ref out), .. }) = err {
- return self.match_output(out)
- }
- let mut s = format!("could not exec process {}: {}", process, e);
- for cause in e.causes() {
- s.push_str(&format!("\ncaused by: {}", cause));
- }
- Err(s)
- }
- }
- }
-}
-
-impl ham::Matcher<Output> for Execs {
- fn matches(&self, output: Output) -> ham::MatchResult {
- self.match_output(&output)
- }
-}
-
-pub fn execs() -> Execs {
- Execs {
- expect_stdout: None,
- expect_stderr: None,
- expect_stdin: None,
- expect_exit_code: None,
- expect_stdout_contains: Vec::new(),
- expect_stderr_contains: Vec::new(),
- expect_either_contains: Vec::new(),
- expect_stdout_contains_n: Vec::new(),
- expect_stdout_not_contains: Vec::new(),
- expect_stderr_not_contains: Vec::new(),
- expect_neither_contains: Vec::new(),
- expect_json: None,
- }
-}
-
-#[derive(Clone)]
-pub struct ShellWrites {
- expected: String
-}
-
-impl fmt::Display for ShellWrites {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(f, "`{}` written to the shell", self.expected)
- }
-}
-
-impl<'a> ham::Matcher<&'a [u8]> for ShellWrites {
- fn matches(&self, actual: &[u8])
- -> ham::MatchResult
- {
- let actual = String::from_utf8_lossy(actual);
- let actual = actual.to_string();
- ham::expect(actual == self.expected, actual)
- }
-}
-
-pub fn shell_writes<T: fmt::Display>(string: T) -> ShellWrites {
- ShellWrites { expected: string.to_string() }
-}
-
-pub trait Tap {
- fn tap<F: FnOnce(&mut Self)>(self, callback: F) -> Self;
-}
-
-impl<T> Tap for T {
- fn tap<F: FnOnce(&mut Self)>(mut self, callback: F) -> T {
- callback(&mut self);
- self
- }
-}
-
-pub fn basic_bin_manifest(name: &str) -> String {
- format!(r#"
- [package]
-
- name = "{}"
- version = "0.5.0"
- authors = ["wycats@example.com"]
-
- [[bin]]
-
- name = "{}"
- "#, name, name)
-}
-
-pub fn basic_lib_manifest(name: &str) -> String {
- format!(r#"
- [package]
-
- name = "{}"
- version = "0.5.0"
- authors = ["wycats@example.com"]
-
- [lib]
-
- name = "{}"
- "#, name, name)
-}
-
-pub fn path2url(p: PathBuf) -> Url {
- Url::from_file_path(&*p).ok().unwrap()
-}
-
-fn substitute_macros(input: &str) -> String {
- let macros = [
- ("[RUNNING]", " Running"),
- ("[COMPILING]", " Compiling"),
- ("[CREATED]", " Created"),
- ("[FINISHED]", " Finished"),
- ("[ERROR]", "error:"),
- ("[WARNING]", "warning:"),
- ("[DOCUMENTING]", " Documenting"),
- ("[FRESH]", " Fresh"),
- ("[UPDATING]", " Updating"),
- ("[ADDING]", " Adding"),
- ("[REMOVING]", " Removing"),
- ("[DOCTEST]", " Doc-tests"),
- ("[PACKAGING]", " Packaging"),
- ("[DOWNLOADING]", " Downloading"),
- ("[UPLOADING]", " Uploading"),
- ("[VERIFYING]", " Verifying"),
- ("[ARCHIVING]", " Archiving"),
- ("[INSTALLING]", " Installing"),
- ("[REPLACING]", " Replacing"),
- ("[UNPACKING]", " Unpacking"),
- ("[SUMMARY]", " Summary"),
- ("[EXE]", if cfg!(windows) {".exe"} else {""}),
- ("[/]", if cfg!(windows) {"\\"} else {"/"}),
- ];
- let mut result = input.to_owned();
- for &(pat, subst) in macros.iter() {
- result = result.replace(pat, subst)
- }
- return result;
-}
+++ /dev/null
-use std::env;
-use std::cell::Cell;
-use std::fs;
-use std::io::{self, ErrorKind};
-use std::path::{Path, PathBuf};
-use std::sync::{Once, ONCE_INIT};
-use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
-
-use filetime::{self, FileTime};
-
-static CARGO_INTEGRATION_TEST_DIR : &'static str = "cit";
-static NEXT_ID: AtomicUsize = ATOMIC_USIZE_INIT;
-
-thread_local!(static TASK_ID: usize = NEXT_ID.fetch_add(1, Ordering::SeqCst));
-
-fn init() {
- static GLOBAL_INIT: Once = ONCE_INIT;
- thread_local!(static LOCAL_INIT: Cell<bool> = Cell::new(false));
- GLOBAL_INIT.call_once(|| {
- global_root().mkdir_p();
- });
- LOCAL_INIT.with(|i| {
- if i.get() {
- return
- }
- i.set(true);
- root().rm_rf();
- home().mkdir_p();
- })
-}
-
-fn global_root() -> PathBuf {
- let mut path = t!(env::current_exe());
- path.pop(); // chop off exe name
- path.pop(); // chop off 'debug'
-
- // If `cargo test` is run manually then our path looks like
- // `target/debug/foo`, in which case our `path` is already pointing at
- // `target`. If, however, `cargo test --target $target` is used then the
- // output is `target/$target/debug/foo`, so our path is pointing at
- // `target/$target`. Here we conditionally pop the `$target` name.
- if path.file_name().and_then(|s| s.to_str()) != Some("target") {
- path.pop();
- }
-
- path.join(CARGO_INTEGRATION_TEST_DIR)
-}
-
-pub fn root() -> PathBuf {
- init();
- global_root().join(&TASK_ID.with(|my_id| format!("t{}", my_id)))
-}
-
-pub fn home() -> PathBuf {
- root().join("home")
-}
-
-pub trait CargoPathExt {
- fn rm_rf(&self);
- fn mkdir_p(&self);
-
- fn move_into_the_past(&self) {
- self.move_in_time(|sec, nsec| (sec - 3600, nsec))
- }
-
- fn move_into_the_future(&self) {
- self.move_in_time(|sec, nsec| (sec + 3600, nsec))
- }
-
- fn move_in_time<F>(&self, F)
- where F: Fn(u64, u32) -> (u64, u32);
-}
-
-impl CargoPathExt for Path {
- /* Technically there is a potential race condition, but we don't
- * care all that much for our tests
- */
- fn rm_rf(&self) {
- if !self.exists() {
- return
- }
-
- for file in t!(fs::read_dir(self)) {
- let file = t!(file);
- if file.file_type().map(|m| m.is_dir()).unwrap_or(false) {
- file.path().rm_rf();
- } else {
- // On windows we can't remove a readonly file, and git will
- // often clone files as readonly. As a result, we have some
- // special logic to remove readonly files on windows.
- do_op(&file.path(), "remove file", |p| fs::remove_file(p));
- }
- }
- do_op(self, "remove dir", |p| fs::remove_dir(p));
- }
-
- fn mkdir_p(&self) {
- fs::create_dir_all(self).unwrap_or_else(|e| {
- panic!("failed to mkdir_p {}: {}", self.display(), e)
- })
- }
-
- fn move_in_time<F>(&self, travel_amount: F)
- where F: Fn(u64, u32) -> ((u64, u32)),
- {
- if self.is_file() {
- time_travel(self, &travel_amount);
- } else {
- recurse(self, &self.join("target"), &travel_amount);
- }
-
- fn recurse<F>(p: &Path, bad: &Path, travel_amount: &F)
- where F: Fn(u64, u32) -> ((u64, u32)),
- {
- if p.is_file() {
- time_travel(p, travel_amount)
- } else if !p.starts_with(bad) {
- for f in t!(fs::read_dir(p)) {
- let f = t!(f).path();
- recurse(&f, bad, travel_amount);
- }
- }
- }
-
- fn time_travel<F>(path: &Path, travel_amount: &F)
- where F: Fn(u64, u32) -> ((u64, u32)),
- {
- let stat = t!(path.metadata());
-
- let mtime = FileTime::from_last_modification_time(&stat);
-
- let (sec, nsec) = travel_amount(mtime.seconds_relative_to_1970(), mtime.nanoseconds());
- let newtime = FileTime::from_seconds_since_1970(sec, nsec);
-
- // Sadly change_file_times has a failure mode where a readonly file
- // cannot have its times changed on windows.
- do_op(path, "set file times",
- |path| filetime::set_file_times(path, newtime, newtime));
- }
- }
-}
-
-fn do_op<F>(path: &Path, desc: &str, mut f: F)
- where F: FnMut(&Path) -> io::Result<()>
-{
- match f(path) {
- Ok(()) => {}
- Err(ref e) if cfg!(windows) &&
- e.kind() == ErrorKind::PermissionDenied => {
- let mut p = t!(path.metadata()).permissions();
- p.set_readonly(false);
- t!(fs::set_permissions(path, p));
- f(path).unwrap_or_else(|e| {
- panic!("failed to {} {}: {}", desc, path.display(), e);
- })
- }
- Err(e) => {
- panic!("failed to {} {}: {}", desc, path.display(), e);
- }
- }
-}
+++ /dev/null
-use std::path::PathBuf;
-use std::io::prelude::*;
-use std::fs::{self, File};
-
-use support::paths;
-use support::git::{repo, Repository};
-
-use url::Url;
-
-pub fn setup() -> Repository {
- let config = paths::root().join(".cargo/config");
- t!(fs::create_dir_all(config.parent().unwrap()));
- t!(t!(File::create(&config)).write_all(format!(r#"
- [registry]
- token = "api-token"
-
- [registries.alternative]
- index = "{registry}"
- "#, registry = registry().to_string()).as_bytes()));
-
- let credentials = paths::root().join("home/.cargo/credentials");
- t!(fs::create_dir_all(credentials.parent().unwrap()));
- t!(t!(File::create(&credentials)).write_all(br#"
- [registries.alternative]
- token = "api-token"
- "#));
-
- t!(fs::create_dir_all(&upload_path().join("api/v1/crates")));
-
- repo(®istry_path())
- .file("config.json", &format!(r#"{{
- "dl": "{0}",
- "api": "{0}"
- }}"#, upload()))
- .build()
-}
-
-fn registry_path() -> PathBuf { paths::root().join("registry") }
-pub fn registry() -> Url { Url::from_file_path(&*registry_path()).ok().unwrap() }
-pub fn upload_path() -> PathBuf { paths::root().join("upload") }
-fn upload() -> Url { Url::from_file_path(&*upload_path()).ok().unwrap() }
+++ /dev/null
-use std::collections::HashMap;
-use std::fs::{self, File};
-use std::io::prelude::*;
-use std::path::{PathBuf, Path};
-
-use flate2::Compression;
-use flate2::write::GzEncoder;
-use git2;
-use hex;
-use tar::{Builder, Header};
-use url::Url;
-
-use support::paths;
-use support::git::repo;
-use cargo::util::Sha256;
-
-pub fn registry_path() -> PathBuf { paths::root().join("registry") }
-pub fn registry() -> Url { Url::from_file_path(&*registry_path()).ok().unwrap() }
-pub fn dl_path() -> PathBuf { paths::root().join("dl") }
-pub fn dl_url() -> Url { Url::from_file_path(&*dl_path()).ok().unwrap() }
-pub fn alt_registry_path() -> PathBuf { paths::root().join("alternative-registry") }
-pub fn alt_registry() -> Url { Url::from_file_path(&*alt_registry_path()).ok().unwrap() }
-pub fn alt_dl_path() -> PathBuf { paths::root().join("alt_dl") }
-pub fn alt_dl_url() -> String {
- let base = Url::from_file_path(&*alt_dl_path()).ok().unwrap();
- format!("{}/{{crate}}/{{version}}/{{crate}}-{{version}}.crate", base)
-}
-pub fn alt_api_path() -> PathBuf { paths::root().join("alt_api") }
-pub fn alt_api_url() -> Url { Url::from_file_path(&*alt_api_path()).ok().unwrap() }
-
-pub struct Package {
- name: String,
- vers: String,
- deps: Vec<Dependency>,
- files: Vec<(String, String)>,
- extra_files: Vec<(String, String)>,
- yanked: bool,
- features: HashMap<String, Vec<String>>,
- local: bool,
- alternative: bool,
-}
-
-struct Dependency {
- name: String,
- vers: String,
- kind: String,
- target: Option<String>,
- features: Vec<String>,
- registry: Option<String>,
-}
-
-pub fn init() {
- let config = paths::home().join(".cargo/config");
- t!(fs::create_dir_all(config.parent().unwrap()));
- if fs::metadata(&config).is_ok() {
- return
- }
- t!(t!(File::create(&config)).write_all(format!(r#"
- [registry]
- token = "api-token"
-
- [source.crates-io]
- registry = 'https://wut'
- replace-with = 'dummy-registry'
-
- [source.dummy-registry]
- registry = '{reg}'
-
- [registries.alternative]
- index = '{alt}'
- "#, reg = registry(), alt = alt_registry()).as_bytes()));
-
- // Init a new registry
- let _ = repo(®istry_path())
- .file("config.json", &format!(r#"
- {{"dl":"{0}","api":"{0}"}}
- "#, dl_url()))
- .build();
- fs::create_dir_all(dl_path().join("api/v1/crates")).unwrap();
-
- // Init an alt registry
- repo(&alt_registry_path())
- .file("config.json", &format!(r#"
- {{"dl":"{}","api":"{}"}}
- "#, alt_dl_url(), alt_api_url()))
- .build();
- fs::create_dir_all(alt_api_path().join("api/v1/crates")).unwrap();
-}
-
-impl Package {
- pub fn new(name: &str, vers: &str) -> Package {
- init();
- Package {
- name: name.to_string(),
- vers: vers.to_string(),
- deps: Vec::new(),
- files: Vec::new(),
- extra_files: Vec::new(),
- yanked: false,
- features: HashMap::new(),
- local: false,
- alternative: false,
- }
- }
-
- pub fn local(&mut self, local: bool) -> &mut Package {
- self.local = local;
- self
- }
-
- pub fn alternative(&mut self, alternative: bool) -> &mut Package {
- self.alternative = alternative;
- self
- }
-
- pub fn file(&mut self, name: &str, contents: &str) -> &mut Package {
- self.files.push((name.to_string(), contents.to_string()));
- self
- }
-
- pub fn extra_file(&mut self, name: &str, contents: &str) -> &mut Package {
- self.extra_files.push((name.to_string(), contents.to_string()));
- self
- }
-
- pub fn dep(&mut self, name: &str, vers: &str) -> &mut Package {
- self.full_dep(name, vers, None, "normal", &[], None)
- }
-
- pub fn feature_dep(&mut self,
- name: &str,
- vers: &str,
- features: &[&str]) -> &mut Package {
- self.full_dep(name, vers, None, "normal", features, None)
- }
-
- pub fn target_dep(&mut self,
- name: &str,
- vers: &str,
- target: &str) -> &mut Package {
- self.full_dep(name, vers, Some(target), "normal", &[], None)
- }
-
- pub fn registry_dep(&mut self,
- name: &str,
- vers: &str,
- registry: &str) -> &mut Package {
- self.full_dep(name, vers, None, "normal", &[], Some(registry))
- }
-
- pub fn dev_dep(&mut self, name: &str, vers: &str) -> &mut Package {
- self.full_dep(name, vers, None, "dev", &[], None)
- }
-
- fn full_dep(&mut self,
- name: &str,
- vers: &str,
- target: Option<&str>,
- kind: &str,
- features: &[&str],
- registry: Option<&str>) -> &mut Package {
- self.deps.push(Dependency {
- name: name.to_string(),
- vers: vers.to_string(),
- kind: kind.to_string(),
- target: target.map(|s| s.to_string()),
- features: features.iter().map(|s| s.to_string()).collect(),
- registry: registry.map(|s| s.to_string()),
- });
- self
- }
-
- pub fn yanked(&mut self, yanked: bool) -> &mut Package {
- self.yanked = yanked;
- self
- }
-
- pub fn publish(&self) -> String {
- self.make_archive();
-
- // Figure out what we're going to write into the index
- let deps = self.deps.iter().map(|dep| {
- json!({
- "name": dep.name,
- "req": dep.vers,
- "features": dep.features,
- "default_features": true,
- "target": dep.target,
- "optional": false,
- "kind": dep.kind,
- "registry": dep.registry,
- })
- }).collect::<Vec<_>>();
- let cksum = {
- let mut c = Vec::new();
- t!(t!(File::open(&self.archive_dst())).read_to_end(&mut c));
- cksum(&c)
- };
- let line = json!({
- "name": self.name,
- "vers": self.vers,
- "deps": deps,
- "cksum": cksum,
- "features": self.features,
- "yanked": self.yanked,
- }).to_string();
-
- let file = match self.name.len() {
- 1 => format!("1/{}", self.name),
- 2 => format!("2/{}", self.name),
- 3 => format!("3/{}/{}", &self.name[..1], self.name),
- _ => format!("{}/{}/{}", &self.name[0..2], &self.name[2..4], self.name),
- };
-
- let registry_path = if self.alternative { alt_registry_path() } else { registry_path() };
-
- // Write file/line in the index
- let dst = if self.local {
- registry_path.join("index").join(&file)
- } else {
- registry_path.join(&file)
- };
- let mut prev = String::new();
- let _ = File::open(&dst).and_then(|mut f| f.read_to_string(&mut prev));
- t!(fs::create_dir_all(dst.parent().unwrap()));
- t!(t!(File::create(&dst))
- .write_all((prev + &line[..] + "\n").as_bytes()));
-
- // Add the new file to the index
- if !self.local {
- let repo = t!(git2::Repository::open(®istry_path));
- let mut index = t!(repo.index());
- t!(index.add_path(Path::new(&file)));
- t!(index.write());
- let id = t!(index.write_tree());
-
- // Commit this change
- let tree = t!(repo.find_tree(id));
- let sig = t!(repo.signature());
- let parent = t!(repo.refname_to_id("refs/heads/master"));
- let parent = t!(repo.find_commit(parent));
- t!(repo.commit(Some("HEAD"), &sig, &sig,
- "Another commit", &tree,
- &[&parent]));
- }
-
- return cksum
- }
-
- fn make_archive(&self) {
- let mut manifest = format!(r#"
- [package]
- name = "{}"
- version = "{}"
- authors = []
- "#, self.name, self.vers);
- for dep in self.deps.iter() {
- let target = match dep.target {
- None => String::new(),
- Some(ref s) => format!("target.'{}'.", s),
- };
- let kind = match &dep.kind[..] {
- "build" => "build-",
- "dev" => "dev-",
- _ => ""
- };
- manifest.push_str(&format!(r#"
- [{}{}dependencies.{}]
- version = "{}"
- "#, target, kind, dep.name, dep.vers));
- }
-
- let dst = self.archive_dst();
- t!(fs::create_dir_all(dst.parent().unwrap()));
- let f = t!(File::create(&dst));
- let mut a =
- Builder::new(GzEncoder::new(f, Compression::default()));
- self.append(&mut a, "Cargo.toml", &manifest);
- if self.files.is_empty() {
- self.append(&mut a, "src/lib.rs", "");
- } else {
- for &(ref name, ref contents) in self.files.iter() {
- self.append(&mut a, name, contents);
- }
- }
- for &(ref name, ref contents) in self.extra_files.iter() {
- self.append_extra(&mut a, name, contents);
- }
- }
-
- fn append<W: Write>(&self, ar: &mut Builder<W>, file: &str, contents: &str) {
- self.append_extra(ar,
- &format!("{}-{}/{}", self.name, self.vers, file),
- contents);
- }
-
- fn append_extra<W: Write>(&self, ar: &mut Builder<W>, path: &str, contents: &str) {
- let mut header = Header::new_ustar();
- header.set_size(contents.len() as u64);
- t!(header.set_path(path));
- header.set_cksum();
- t!(ar.append(&header, contents.as_bytes()));
- }
-
- pub fn archive_dst(&self) -> PathBuf {
- if self.local {
- registry_path().join(format!("{}-{}.crate", self.name,
- self.vers))
- } else if self.alternative {
- alt_dl_path()
- .join(&self.name)
- .join(&self.vers)
- .join(&format!("{}-{}.crate", self.name, self.vers))
- } else {
- dl_path().join(&self.name).join(&self.vers).join("download")
- }
- }
-}
-
-pub fn cksum(s: &[u8]) -> String {
- let mut sha = Sha256::new();
- sha.update(s);
- hex::encode(&sha.finish())
-}
+++ /dev/null
-extern crate cargo;
-extern crate cargotest;
-extern crate hamcrest;
-
-use std::str::FromStr;
-use std::fmt;
-
-use cargo::util::{Cfg, CfgExpr};
-use cargotest::rustc_host;
-use cargotest::support::registry::Package;
-use cargotest::support::{project, execs};
-use hamcrest::assert_that;
-
-macro_rules! c {
- ($a:ident) => (
- Cfg::Name(stringify!($a).to_string())
- );
- ($a:ident = $e:expr) => (
- Cfg::KeyPair(stringify!($a).to_string(), $e.to_string())
- );
-}
-
-macro_rules! e {
- (any($($t:tt),*)) => (CfgExpr::Any(vec![$(e!($t)),*]));
- (all($($t:tt),*)) => (CfgExpr::All(vec![$(e!($t)),*]));
- (not($($t:tt)*)) => (CfgExpr::Not(Box::new(e!($($t)*))));
- (($($t:tt)*)) => (e!($($t)*));
- ($($t:tt)*) => (CfgExpr::Value(c!($($t)*)));
-}
-
-fn good<T>(s: &str, expected: T)
- where T: FromStr + PartialEq + fmt::Debug,
- T::Err: fmt::Display
-{
- let c = match T::from_str(s) {
- Ok(c) => c,
- Err(e) => panic!("failed to parse `{}`: {}", s, e),
- };
- assert_eq!(c, expected);
-}
-
-fn bad<T>(s: &str, err: &str)
- where T: FromStr + fmt::Display, T::Err: fmt::Display
-{
- let e = match T::from_str(s) {
- Ok(cfg) => panic!("expected `{}` to not parse but got {}", s, cfg),
- Err(e) => e.to_string(),
- };
- assert!(e.contains(err), "when parsing `{}`,\n\"{}\" not contained \
- inside: {}", s, err, e);
-}
-
-#[test]
-fn cfg_syntax() {
- good("foo", c!(foo));
- good("_bar", c!(_bar));
- good(" foo", c!(foo));
- good(" foo ", c!(foo));
- good(" foo = \"bar\"", c!(foo = "bar"));
- good("foo=\"\"", c!(foo = ""));
- good(" foo=\"3\" ", c!(foo = "3"));
- good("foo = \"3 e\"", c!(foo = "3 e"));
-}
-
-#[test]
-fn cfg_syntax_bad() {
- bad::<Cfg>("", "found nothing");
- bad::<Cfg>(" ", "found nothing");
- bad::<Cfg>("\t", "unexpected character");
- bad::<Cfg>("7", "unexpected character");
- bad::<Cfg>("=", "expected identifier");
- bad::<Cfg>(",", "expected identifier");
- bad::<Cfg>("(", "expected identifier");
- bad::<Cfg>("foo (", "malformed cfg value");
- bad::<Cfg>("bar =", "expected a string");
- bad::<Cfg>("bar = \"", "unterminated string");
- bad::<Cfg>("foo, bar", "malformed cfg value");
-}
-
-#[test]
-fn cfg_expr() {
- good("foo", e!(foo));
- good("_bar", e!(_bar));
- good(" foo", e!(foo));
- good(" foo ", e!(foo));
- good(" foo = \"bar\"", e!(foo = "bar"));
- good("foo=\"\"", e!(foo = ""));
- good(" foo=\"3\" ", e!(foo = "3"));
- good("foo = \"3 e\"", e!(foo = "3 e"));
-
- good("all()", e!(all()));
- good("all(a)", e!(all(a)));
- good("all(a, b)", e!(all(a, b)));
- good("all(a, )", e!(all(a)));
- good("not(a = \"b\")", e!(not(a = "b")));
- good("not(all(a))", e!(not(all(a))));
-}
-
-#[test]
-fn cfg_expr_bad() {
- bad::<CfgExpr>(" ", "found nothing");
- bad::<CfgExpr>(" all", "expected `(`");
- bad::<CfgExpr>("all(a", "expected `)`");
- bad::<CfgExpr>("not", "expected `(`");
- bad::<CfgExpr>("not(a", "expected `)`");
- bad::<CfgExpr>("a = ", "expected a string");
- bad::<CfgExpr>("all(not())", "expected identifier");
- bad::<CfgExpr>("foo(a)", "consider using all() or any() explicitly");
-}
-
-#[test]
-fn cfg_matches() {
- assert!(e!(foo).matches(&[c!(bar), c!(foo), c!(baz)]));
- assert!(e!(any(foo)).matches(&[c!(bar), c!(foo), c!(baz)]));
- assert!(e!(any(foo, bar)).matches(&[c!(bar)]));
- assert!(e!(any(foo, bar)).matches(&[c!(foo)]));
- assert!(e!(all(foo, bar)).matches(&[c!(foo), c!(bar)]));
- assert!(e!(all(foo, bar)).matches(&[c!(foo), c!(bar)]));
- assert!(e!(not(foo)).matches(&[c!(bar)]));
- assert!(e!(not(foo)).matches(&[]));
- assert!(e!(any((not(foo)), (all(foo, bar)))).matches(&[c!(bar)]));
- assert!(e!(any((not(foo)), (all(foo, bar)))).matches(&[c!(foo), c!(bar)]));
-
- assert!(!e!(foo).matches(&[]));
- assert!(!e!(foo).matches(&[c!(bar)]));
- assert!(!e!(foo).matches(&[c!(fo)]));
- assert!(!e!(any(foo)).matches(&[]));
- assert!(!e!(any(foo)).matches(&[c!(bar)]));
- assert!(!e!(any(foo)).matches(&[c!(bar), c!(baz)]));
- assert!(!e!(all(foo)).matches(&[c!(bar), c!(baz)]));
- assert!(!e!(all(foo, bar)).matches(&[c!(bar)]));
- assert!(!e!(all(foo, bar)).matches(&[c!(foo)]));
- assert!(!e!(all(foo, bar)).matches(&[]));
- assert!(!e!(not(bar)).matches(&[c!(bar)]));
- assert!(!e!(not(bar)).matches(&[c!(baz), c!(bar)]));
- assert!(!e!(any((not(foo)), (all(foo, bar)))).matches(&[c!(foo)]));
-}
-
-#[test]
-fn cfg_easy() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "a"
- version = "0.0.1"
- authors = []
-
- [target.'cfg(unix)'.dependencies]
- b = { path = 'b' }
- [target."cfg(windows)".dependencies]
- b = { path = 'b' }
- "#)
- .file("src/lib.rs", "extern crate b;")
- .file("b/Cargo.toml", r#"
- [package]
- name = "b"
- version = "0.0.1"
- authors = []
- "#)
- .file("b/src/lib.rs", "")
- .build();
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(0));
-}
-
-#[test]
-fn dont_include() {
- let other_family = if cfg!(unix) {"windows"} else {"unix"};
- let p = project("foo")
- .file("Cargo.toml", &format!(r#"
- [package]
- name = "a"
- version = "0.0.1"
- authors = []
-
- [target.'cfg({})'.dependencies]
- b = {{ path = 'b' }}
- "#, other_family))
- .file("src/lib.rs", "")
- .file("b/Cargo.toml", r#"
- [package]
- name = "b"
- version = "0.0.1"
- authors = []
- "#)
- .file("b/src/lib.rs", "")
- .build();
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr("\
-[COMPILING] a v0.0.1 ([..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-}
-
-#[test]
-fn works_through_the_registry() {
- Package::new("foo", "0.1.0").publish();
- Package::new("bar", "0.1.0")
- .target_dep("foo", "0.1.0", "cfg(unix)")
- .target_dep("foo", "0.1.0", "cfg(windows)")
- .publish();
-
- let p = project("a")
- .file("Cargo.toml", r#"
- [package]
- name = "a"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- bar = "0.1.0"
- "#)
- .file("src/lib.rs", "#[allow(unused_extern_crates)] extern crate bar;")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr("\
-[UPDATING] registry [..]
-[DOWNLOADING] [..]
-[DOWNLOADING] [..]
-[COMPILING] foo v0.1.0
-[COMPILING] bar v0.1.0
-[COMPILING] a v0.0.1 ([..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-}
-
-#[test]
-fn ignore_version_from_other_platform() {
- let this_family = if cfg!(unix) {"unix"} else {"windows"};
- let other_family = if cfg!(unix) {"windows"} else {"unix"};
- Package::new("foo", "0.1.0").publish();
- Package::new("foo", "0.2.0").publish();
-
- let p = project("a")
- .file("Cargo.toml", &format!(r#"
- [package]
- name = "a"
- version = "0.0.1"
- authors = []
-
- [target.'cfg({})'.dependencies]
- foo = "0.1.0"
-
- [target.'cfg({})'.dependencies]
- foo = "0.2.0"
- "#, this_family, other_family))
- .file("src/lib.rs", "#[allow(unused_extern_crates)] extern crate foo;")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr("\
-[UPDATING] registry [..]
-[DOWNLOADING] [..]
-[COMPILING] foo v0.1.0
-[COMPILING] a v0.0.1 ([..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-}
-
-#[test]
-fn bad_target_spec() {
- let p = project("a")
- .file("Cargo.toml", r#"
- [package]
- name = "a"
- version = "0.0.1"
- authors = []
-
- [target.'cfg(4)'.dependencies]
- bar = "0.1.0"
- "#)
- .file("src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(101).with_stderr("\
-[ERROR] failed to parse manifest at `[..]`
-
-Caused by:
- failed to parse `4` as a cfg expression
-
-Caused by:
- unexpected character in cfg `4`, [..]
-"));
-}
-
-#[test]
-fn bad_target_spec2() {
- let p = project("a")
- .file("Cargo.toml", r#"
- [package]
- name = "a"
- version = "0.0.1"
- authors = []
-
- [target.'cfg(foo =)'.dependencies]
- bar = "0.1.0"
- "#)
- .file("src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(101).with_stderr("\
-[ERROR] failed to parse manifest at `[..]`
-
-Caused by:
- failed to parse `foo =` as a cfg expression
-
-Caused by:
- expected a string, found nothing
-"));
-}
-
-#[test]
-fn multiple_match_ok() {
- let p = project("foo")
- .file("Cargo.toml", &format!(r#"
- [package]
- name = "a"
- version = "0.0.1"
- authors = []
-
- [target.'cfg(unix)'.dependencies]
- b = {{ path = 'b' }}
- [target.'cfg(target_family = "unix")'.dependencies]
- b = {{ path = 'b' }}
- [target."cfg(windows)".dependencies]
- b = {{ path = 'b' }}
- [target.'cfg(target_family = "windows")'.dependencies]
- b = {{ path = 'b' }}
- [target."cfg(any(windows, unix))".dependencies]
- b = {{ path = 'b' }}
-
- [target.{}.dependencies]
- b = {{ path = 'b' }}
- "#, rustc_host()))
- .file("src/lib.rs", "extern crate b;")
- .file("b/Cargo.toml", r#"
- [package]
- name = "b"
- version = "0.0.1"
- authors = []
- "#)
- .file("b/src/lib.rs", "")
- .build();
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(0));
-}
-
-#[test]
-fn any_ok() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "a"
- version = "0.0.1"
- authors = []
-
- [target."cfg(any(windows, unix))".dependencies]
- b = { path = 'b' }
- "#)
- .file("src/lib.rs", "extern crate b;")
- .file("b/Cargo.toml", r#"
- [package]
- name = "b"
- version = "0.0.1"
- authors = []
- "#)
- .file("b/src/lib.rs", "")
- .build();
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(0));
-}
+++ /dev/null
-echo "checking for lines over 100 characters..."
-find src tests -name '*.rs' | xargs grep '.\{101,\}' && exit 1
-echo "ok"
+++ /dev/null
-extern crate cargotest;
-extern crate hamcrest;
-extern crate glob;
-
-use cargotest::is_nightly;
-use cargotest::support::{execs, project};
-use cargotest::support::registry::Package;
-use hamcrest::prelude::*;
-use cargotest::support::paths::CargoPathExt;
-use cargotest::install::exe;
-use glob::glob;
-
-const SIMPLE_MANIFEST: &str = r#"
-[package]
-name = "foo"
-version = "0.0.1"
-authors = []
-"#;
-
-#[test]
-fn check_success() {
- let foo = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies.bar]
- path = "../bar"
- "#)
- .file("src/main.rs", r#"
- extern crate bar;
- fn main() {
- ::bar::baz();
- }
- "#)
- .build();
- let _bar = project("bar")
- .file("Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.1.0"
- authors = []
- "#)
- .file("src/lib.rs", r#"
- pub fn baz() {}
- "#)
- .build();
-
- assert_that(foo.cargo("check"),
- execs().with_status(0));
-}
-
-#[test]
-fn check_fail() {
- let foo = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies.bar]
- path = "../bar"
- "#)
- .file("src/main.rs", r#"
- extern crate bar;
- fn main() {
- ::bar::baz(42);
- }
- "#)
- .build();
- let _bar = project("bar")
- .file("Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.1.0"
- authors = []
- "#)
- .file("src/lib.rs", r#"
- pub fn baz() {}
- "#)
- .build();
-
- assert_that(foo.cargo("check"),
- execs().with_status(101));
-}
-
-#[test]
-fn custom_derive() {
- if !is_nightly() {
- return
- }
- let foo = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies.bar]
- path = "../bar"
- "#)
- .file("src/main.rs", r#"
-#![feature(proc_macro)]
-
-#[macro_use]
-extern crate bar;
-
-trait B {
- fn b(&self);
-}
-
-#[derive(B)]
-struct A;
-
-fn main() {
- let a = A;
- a.b();
-}
-"#)
- .build();
- let _bar = project("bar")
- .file("Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.1.0"
- authors = []
- [lib]
- proc-macro = true
- "#)
- .file("src/lib.rs", r#"
-#![feature(proc_macro, proc_macro_lib)]
-#![crate_type = "proc-macro"]
-
-extern crate proc_macro;
-
-use proc_macro::TokenStream;
-
-#[proc_macro_derive(B)]
-pub fn derive(_input: TokenStream) -> TokenStream {
- format!("impl B for A {{ fn b(&self) {{}} }}").parse().unwrap()
-}
-"#)
- .build();
-
- assert_that(foo.cargo("check"),
- execs().with_status(0));
-}
-
-#[test]
-fn check_build() {
- let foo = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies.bar]
- path = "../bar"
- "#)
- .file("src/main.rs", r#"
- extern crate bar;
- fn main() {
- ::bar::baz();
- }
- "#)
- .build();
-
- let _bar = project("bar")
- .file("Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.1.0"
- authors = []
- "#)
- .file("src/lib.rs", r#"
- pub fn baz() {}
- "#)
- .build();
-
- assert_that(foo.cargo("check"),
- execs().with_status(0));
- assert_that(foo.cargo("build"),
- execs().with_status(0));
-}
-
-#[test]
-fn build_check() {
- let foo = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies.bar]
- path = "../bar"
- "#)
- .file("src/main.rs", r#"
- extern crate bar;
- fn main() {
- ::bar::baz();
- }
- "#)
- .build();
-
- let _bar = project("bar")
- .file("Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.1.0"
- authors = []
- "#)
- .file("src/lib.rs", r#"
- pub fn baz() {}
- "#)
- .build();
-
- assert_that(foo.cargo("build"),
- execs().with_status(0));
- assert_that(foo.cargo("check"),
- execs().with_status(0));
-}
-
-// Checks that where a project has both a lib and a bin, the lib is only checked
-// not built.
-#[test]
-fn issue_3418() {
- let foo = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
-
- [dependencies]
- "#)
- .file("src/lib.rs", "")
- .file("src/main.rs", "fn main() {}")
- .build();
-
- assert_that(foo.cargo("check").arg("-v"),
- execs().with_status(0)
- .with_stderr_contains("[..] --emit=dep-info,metadata [..]"));
-}
-
-// Some weirdness that seems to be caused by a crate being built as well as
-// checked, but in this case with a proc macro too.
-#[test]
-fn issue_3419() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- rustc-serialize = "*"
- "#)
- .file("src/lib.rs", r#"
- extern crate rustc_serialize;
-
- use rustc_serialize::Decodable;
-
- pub fn take<T: Decodable>() {}
- "#)
- .file("src/main.rs", r#"
- extern crate rustc_serialize;
-
- extern crate foo;
-
- #[derive(RustcDecodable)]
- pub struct Foo;
-
- fn main() {
- foo::take::<Foo>();
- }
- "#)
- .build();
-
- Package::new("rustc-serialize", "1.0.0")
- .file("src/lib.rs",
- r#"pub trait Decodable: Sized {
- fn decode<D: Decoder>(d: &mut D) -> Result<Self, D::Error>;
- }
- pub trait Decoder {
- type Error;
- fn read_struct<T, F>(&mut self, s_name: &str, len: usize, f: F)
- -> Result<T, Self::Error>
- where F: FnOnce(&mut Self) -> Result<T, Self::Error>;
- } "#).publish();
-
- assert_that(p.cargo("check"),
- execs().with_status(0));
-}
-
-// Check on a dylib should have a different metadata hash than build.
-#[test]
-fn dylib_check_preserves_build_cache() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
-
- [lib]
- crate-type = ["dylib"]
-
- [dependencies]
- "#)
- .file("src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0)
- .with_stderr("\
-[..]Compiling foo v0.1.0 ([..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-
- assert_that(p.cargo("check"),
- execs().with_status(0));
-
- assert_that(p.cargo("build"),
- execs().with_status(0)
- .with_stderr("\
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-}
-
-// test `cargo rustc --profile check`
-#[test]
-fn rustc_check() {
- let foo = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies.bar]
- path = "../bar"
- "#)
- .file("src/main.rs", r#"
- extern crate bar;
- fn main() {
- ::bar::baz();
- }
- "#)
- .build();
- let _bar = project("bar")
- .file("Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.1.0"
- authors = []
- "#)
- .file("src/lib.rs", r#"
- pub fn baz() {}
- "#)
- .build();
-
- assert_that(foo.cargo("rustc")
- .arg("--profile")
- .arg("check")
- .arg("--")
- .arg("--emit=metadata"),
- execs().with_status(0));
-}
-
-#[test]
-fn rustc_check_err() {
- let foo = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies.bar]
- path = "../bar"
- "#)
- .file("src/main.rs", r#"
- extern crate bar;
- fn main() {
- ::bar::qux();
- }
- "#)
- .build();
- let _bar = project("bar")
- .file("Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.1.0"
- authors = []
- "#)
- .file("src/lib.rs", r#"
- pub fn baz() {}
- "#)
- .build();
-
- assert_that(foo.cargo("rustc")
- .arg("--profile")
- .arg("check")
- .arg("--")
- .arg("--emit=metadata"),
- execs().with_status(101));
-}
-
-#[test]
-fn check_all() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [workspace]
- [dependencies]
- b = { path = "b" }
- "#)
- .file("src/main.rs", "fn main() {}")
- .file("examples/a.rs", "fn main() {}")
- .file("tests/a.rs", "")
- .file("src/lib.rs", "")
- .file("b/Cargo.toml", r#"
- [package]
- name = "b"
- version = "0.0.1"
- authors = []
- "#)
- .file("b/src/main.rs", "fn main() {}")
- .file("b/src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("check").arg("--all").arg("-v"),
- execs().with_status(0)
- .with_stderr_contains("[..] --crate-name foo src[/]lib.rs [..]")
- .with_stderr_contains("[..] --crate-name foo src[/]main.rs [..]")
- .with_stderr_contains("[..] --crate-name b b[/]src[/]lib.rs [..]")
- .with_stderr_contains("[..] --crate-name b b[/]src[/]main.rs [..]")
- );
-}
-
-#[test]
-fn check_virtual_all_implied() {
- let p = project("workspace")
- .file("Cargo.toml", r#"
- [workspace]
- members = ["foo", "bar"]
- "#)
- .file("foo/Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.1.0"
- "#)
- .file("foo/src/lib.rs", r#"
- pub fn foo() {}
- "#)
- .file("bar/Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.1.0"
- "#)
- .file("bar/src/lib.rs", r#"
- pub fn bar() {}
- "#)
- .build();
-
- assert_that(p.cargo("check").arg("-v"),
- execs().with_status(0)
- .with_stderr_contains("[..] --crate-name foo foo[/]src[/]lib.rs [..]")
- .with_stderr_contains("[..] --crate-name bar bar[/]src[/]lib.rs [..]")
- );
-}
-
-#[test]
-fn check_all_targets() {
- let foo = project("foo")
- .file("Cargo.toml", SIMPLE_MANIFEST)
- .file("src/main.rs", "fn main() {}")
- .file("src/lib.rs", "pub fn smth() {}")
- .file("examples/example1.rs", "fn main() {}")
- .file("tests/test2.rs", "#[test] fn t() {}")
- .file("benches/bench3.rs", "")
- .build();
-
- assert_that(foo.cargo("check").arg("--all-targets").arg("-v"),
- execs().with_status(0)
- .with_stderr_contains("[..] --crate-name foo src[/]lib.rs [..]")
- .with_stderr_contains("[..] --crate-name foo src[/]main.rs [..]")
- .with_stderr_contains("[..] --crate-name example1 examples[/]example1.rs [..]")
- .with_stderr_contains("[..] --crate-name test2 tests[/]test2.rs [..]")
- .with_stderr_contains("[..] --crate-name bench3 benches[/]bench3.rs [..]")
- );
-}
-
-#[test]
-fn check_unit_test_profile() {
- let foo = project("foo")
- .file("Cargo.toml", SIMPLE_MANIFEST)
- .file("src/lib.rs", r#"
- #[cfg(test)]
- mod tests {
- #[test]
- fn it_works() {
- badtext
- }
- }
- "#)
- .build();
-
- assert_that(foo.cargo("check"),
- execs().with_status(0));
- assert_that(foo.cargo("check").arg("--profile").arg("test"),
- execs().with_status(101)
- .with_stderr_contains("[..]badtext[..]"));
-}
-
-// Verify what is checked with various command-line filters.
-#[test]
-fn check_filters() {
- let p = project("foo")
- .file("Cargo.toml", SIMPLE_MANIFEST)
- .file("src/lib.rs", r#"
- fn unused_normal_lib() {}
- #[cfg(test)]
- mod tests {
- fn unused_unit_lib() {}
- }
- "#)
- .file("src/main.rs", r#"
- fn main() {}
- fn unused_normal_bin() {}
- #[cfg(test)]
- mod tests {
- fn unused_unit_bin() {}
- }
- "#)
- .file("tests/t1.rs", r#"
- fn unused_normal_t1() {}
- #[cfg(test)]
- mod tests {
- fn unused_unit_t1() {}
- }
- "#)
- .file("examples/ex1.rs", r#"
- fn main() {}
- fn unused_normal_ex1() {}
- #[cfg(test)]
- mod tests {
- fn unused_unit_ex1() {}
- }
- "#)
- .file("benches/b1.rs", r#"
- fn unused_normal_b1() {}
- #[cfg(test)]
- mod tests {
- fn unused_unit_b1() {}
- }
- "#)
- .build();
-
- assert_that(p.cargo("check"),
- execs().with_status(0)
- .with_stderr_contains("[..]unused_normal_lib[..]")
- .with_stderr_contains("[..]unused_normal_bin[..]")
- .with_stderr_does_not_contain("unused_normal_t1")
- .with_stderr_does_not_contain("unused_normal_ex1")
- .with_stderr_does_not_contain("unused_normal_b1")
- .with_stderr_does_not_contain("unused_unit_"));
- p.root().join("target").rm_rf();
- assert_that(p.cargo("check").arg("--tests").arg("-v"),
- execs().with_status(0)
- .with_stderr_contains("[..] --crate-name foo src[/]lib.rs [..] --test [..]")
- .with_stderr_contains("[..] --crate-name foo src[/]lib.rs --crate-type lib [..]")
- .with_stderr_contains("[..] --crate-name foo src[/]main.rs [..] --test [..]")
- .with_stderr_contains("[..] --crate-name foo src[/]main.rs --crate-type bin [..]")
- .with_stderr_contains("[..]unused_unit_lib[..]")
- .with_stderr_contains("[..]unused_unit_bin[..]")
- .with_stderr_contains("[..]unused_normal_lib[..]")
- .with_stderr_contains("[..]unused_normal_bin[..]")
- .with_stderr_contains("[..]unused_unit_t1[..]")
- .with_stderr_contains("[..]unused_normal_ex1[..]")
- .with_stderr_contains("[..]unused_unit_ex1[..]")
- .with_stderr_does_not_contain("unused_normal_b1")
- .with_stderr_does_not_contain("unused_unit_b1"));
- p.root().join("target").rm_rf();
- assert_that(p.cargo("check").arg("--test").arg("t1").arg("-v"),
- execs().with_status(0)
- .with_stderr_contains("[..]unused_normal_lib[..]")
- .with_stderr_contains("[..]unused_normal_bin[..]")
- .with_stderr_contains("[..]unused_unit_t1[..]")
- .with_stderr_does_not_contain("unused_unit_lib")
- .with_stderr_does_not_contain("unused_unit_bin")
- .with_stderr_does_not_contain("unused_normal_ex1")
- .with_stderr_does_not_contain("unused_normal_b1")
- .with_stderr_does_not_contain("unused_unit_ex1")
- .with_stderr_does_not_contain("unused_unit_b1"));
- p.root().join("target").rm_rf();
- assert_that(p.cargo("check").arg("--all-targets").arg("-v"),
- execs().with_status(0)
- .with_stderr_contains("[..]unused_normal_lib[..]")
- .with_stderr_contains("[..]unused_normal_bin[..]")
- .with_stderr_contains("[..]unused_normal_t1[..]")
- .with_stderr_contains("[..]unused_normal_ex1[..]")
- .with_stderr_contains("[..]unused_normal_b1[..]")
- .with_stderr_contains("[..]unused_unit_b1[..]")
- .with_stderr_contains("[..]unused_unit_t1[..]")
- .with_stderr_contains("[..]unused_unit_lib[..]")
- .with_stderr_contains("[..]unused_unit_bin[..]")
- .with_stderr_contains("[..]unused_unit_ex1[..]"));
-}
-
-#[test]
-fn check_artifacts()
-{
- // Verify which artifacts are created when running check (#4059).
- let p = project("foo")
- .file("Cargo.toml", SIMPLE_MANIFEST)
- .file("src/lib.rs", "")
- .file("src/main.rs", "fn main() {}")
- .file("tests/t1.rs", "")
- .file("examples/ex1.rs", "fn main() {}")
- .file("benches/b1.rs", "")
- .build();
- assert_that(p.cargo("check"), execs().with_status(0));
- assert_that(&p.root().join("target/debug/libfoo.rmeta"),
- existing_file());
- assert_that(&p.root().join("target/debug/libfoo.rlib"),
- is_not(existing_file()));
- assert_that(&p.root().join("target/debug").join(exe("foo")),
- is_not(existing_file()));
-
- p.root().join("target").rm_rf();
- assert_that(p.cargo("check").arg("--lib"), execs().with_status(0));
- assert_that(&p.root().join("target/debug/libfoo.rmeta"),
- existing_file());
- assert_that(&p.root().join("target/debug/libfoo.rlib"),
- is_not(existing_file()));
- assert_that(&p.root().join("target/debug").join(exe("foo")),
- is_not(existing_file()));
-
- p.root().join("target").rm_rf();
- assert_that(p.cargo("check").arg("--bin").arg("foo"),
- execs().with_status(0));
- assert_that(&p.root().join("target/debug/libfoo.rmeta"),
- existing_file());
- assert_that(&p.root().join("target/debug/libfoo.rlib"),
- is_not(existing_file()));
- assert_that(&p.root().join("target/debug").join(exe("foo")),
- is_not(existing_file()));
-
- p.root().join("target").rm_rf();
- assert_that(p.cargo("check").arg("--test").arg("t1"),
- execs().with_status(0));
- assert_that(&p.root().join("target/debug/libfoo.rmeta"),
- existing_file());
- assert_that(&p.root().join("target/debug/libfoo.rlib"),
- is_not(existing_file()));
- assert_that(&p.root().join("target/debug").join(exe("foo")),
- is_not(existing_file()));
- assert_that(glob(&p.root().join("target/debug/t1-*").to_str().unwrap())
- .unwrap().count(),
- is(equal_to(0)));
-
- p.root().join("target").rm_rf();
- assert_that(p.cargo("check").arg("--example").arg("ex1"),
- execs().with_status(0));
- assert_that(&p.root().join("target/debug/libfoo.rmeta"),
- existing_file());
- assert_that(&p.root().join("target/debug/libfoo.rlib"),
- is_not(existing_file()));
- assert_that(&p.root().join("target/debug/examples").join(exe("ex1")),
- is_not(existing_file()));
-
- p.root().join("target").rm_rf();
- assert_that(p.cargo("check").arg("--bench").arg("b1"),
- execs().with_status(0));
- assert_that(&p.root().join("target/debug/libfoo.rmeta"),
- existing_file());
- assert_that(&p.root().join("target/debug/libfoo.rlib"),
- is_not(existing_file()));
- assert_that(&p.root().join("target/debug").join(exe("foo")),
- is_not(existing_file()));
- assert_that(glob(&p.root().join("target/debug/b1-*").to_str().unwrap())
- .unwrap().count(),
- is(equal_to(0)));
-}
+++ /dev/null
-extern crate hamcrest;
-extern crate cargotest;
-
-use std::env;
-
-use cargotest::support::{git, project, execs, main_file, basic_bin_manifest};
-use cargotest::support::registry::Package;
-use hamcrest::{assert_that, existing_dir, existing_file, is_not};
-
-#[test]
-fn cargo_clean_simple() {
- let p = project("foo")
- .file("Cargo.toml", &basic_bin_manifest("foo"))
- .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
- .build();
-
- assert_that(p.cargo("build"), execs().with_status(0));
- assert_that(&p.build_dir(), existing_dir());
-
- assert_that(p.cargo("clean"),
- execs().with_status(0));
- assert_that(&p.build_dir(), is_not(existing_dir()));
-}
-
-#[test]
-fn different_dir() {
- let p = project("foo")
- .file("Cargo.toml", &basic_bin_manifest("foo"))
- .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
- .file("src/bar/a.rs", "")
- .build();
-
- assert_that(p.cargo("build"), execs().with_status(0));
- assert_that(&p.build_dir(), existing_dir());
-
- assert_that(p.cargo("clean").cwd(&p.root().join("src")),
- execs().with_status(0).with_stdout(""));
- assert_that(&p.build_dir(), is_not(existing_dir()));
-}
-
-#[test]
-fn clean_multiple_packages() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies.d1]
- path = "d1"
- [dependencies.d2]
- path = "d2"
-
- [[bin]]
- name = "foo"
- "#)
- .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
- .file("d1/Cargo.toml", r#"
- [package]
- name = "d1"
- version = "0.0.1"
- authors = []
-
- [[bin]]
- name = "d1"
- "#)
- .file("d1/src/main.rs", "fn main() { println!(\"d1\"); }")
- .file("d2/Cargo.toml", r#"
- [package]
- name = "d2"
- version = "0.0.1"
- authors = []
-
- [[bin]]
- name = "d2"
- "#)
- .file("d2/src/main.rs", "fn main() { println!(\"d2\"); }")
- .build();
-
- assert_that(p.cargo("build").arg("-p").arg("d1").arg("-p").arg("d2")
- .arg("-p").arg("foo"),
- execs().with_status(0));
-
- let d1_path = &p.build_dir().join("debug")
- .join(format!("d1{}", env::consts::EXE_SUFFIX));
- let d2_path = &p.build_dir().join("debug")
- .join(format!("d2{}", env::consts::EXE_SUFFIX));
-
-
- assert_that(&p.bin("foo"), existing_file());
- assert_that(d1_path, existing_file());
- assert_that(d2_path, existing_file());
-
- assert_that(p.cargo("clean").arg("-p").arg("d1").arg("-p").arg("d2")
- .cwd(&p.root().join("src")),
- execs().with_status(0).with_stdout(""));
- assert_that(&p.bin("foo"), existing_file());
- assert_that(d1_path, is_not(existing_file()));
- assert_that(d2_path, is_not(existing_file()));
-}
-
-#[test]
-fn clean_release() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- a = { path = "a" }
- "#)
- .file("src/main.rs", "fn main() {}")
- .file("a/Cargo.toml", r#"
- [package]
- name = "a"
- version = "0.0.1"
- authors = []
- "#)
- .file("a/src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build").arg("--release"),
- execs().with_status(0));
-
- assert_that(p.cargo("clean").arg("-p").arg("foo"),
- execs().with_status(0));
- assert_that(p.cargo("build").arg("--release"),
- execs().with_status(0).with_stdout(""));
-
- assert_that(p.cargo("clean").arg("-p").arg("foo").arg("--release"),
- execs().with_status(0));
- assert_that(p.cargo("build").arg("--release"),
- execs().with_status(0).with_stderr("\
-[COMPILING] foo v0.0.1 ([..])
-[FINISHED] release [optimized] target(s) in [..]
-"));
-}
-
-#[test]
-fn build_script() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- build = "build.rs"
- "#)
- .file("src/main.rs", "fn main() {}")
- .file("build.rs", r#"
- use std::path::PathBuf;
- use std::env;
-
- fn main() {
- let out = PathBuf::from(env::var_os("OUT_DIR").unwrap());
- if env::var("FIRST").is_ok() {
- std::fs::File::create(out.join("out")).unwrap();
- } else {
- assert!(!std::fs::metadata(out.join("out")).is_ok());
- }
- }
- "#)
- .file("a/src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build").env("FIRST", "1"),
- execs().with_status(0));
- assert_that(p.cargo("clean").arg("-p").arg("foo"),
- execs().with_status(0));
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(0).with_stderr("\
-[COMPILING] foo v0.0.1 ([..])
-[RUNNING] `rustc [..] build.rs [..]`
-[RUNNING] `[..]build-script-build`
-[RUNNING] `rustc [..] src[/]main.rs [..]`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-}
-
-#[test]
-fn clean_git() {
- let git = git::new("dep", |project| {
- project.file("Cargo.toml", r#"
- [project]
- name = "dep"
- version = "0.5.0"
- authors = []
- "#)
- .file("src/lib.rs", "")
- }).unwrap();
-
- let p = project("foo")
- .file("Cargo.toml", &format!(r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- dep = {{ git = '{}' }}
- "#, git.url()))
- .file("src/main.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0));
- assert_that(p.cargo("clean").arg("-p").arg("dep"),
- execs().with_status(0).with_stdout(""));
- assert_that(p.cargo("build"),
- execs().with_status(0));
-}
-
-#[test]
-fn registry() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- bar = "0.1"
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- Package::new("bar", "0.1.0").publish();
-
- assert_that(p.cargo("build"),
- execs().with_status(0));
- assert_that(p.cargo("clean").arg("-p").arg("bar"),
- execs().with_status(0).with_stdout(""));
- assert_that(p.cargo("build"),
- execs().with_status(0));
-}
+++ /dev/null
-extern crate cargotest;
-extern crate git2;
-extern crate hamcrest;
-
-use std::{env, str};
-use std::fs::{self, File};
-use std::io::Write;
-use std::net::TcpListener;
-use std::process::Stdio;
-use std::thread;
-use std::sync::mpsc::channel;
-use std::time::Duration;
-
-use cargotest::install::{has_installed_exe, cargo_home};
-use cargotest::support::git;
-use cargotest::support::registry::Package;
-use cargotest::support::{execs, project};
-use hamcrest::{assert_that, existing_file};
-
-fn pkg(name: &str, vers: &str) {
- Package::new(name, vers)
- .file("src/main.rs", "fn main() {{}}")
- .publish();
-}
-
-#[test]
-fn multiple_installs() {
- let p = project("foo")
- .file("a/Cargo.toml", r#"
- [package]
- name = "foo"
- authors = []
- version = "0.0.0"
- "#)
- .file("a/src/main.rs", "fn main() {}")
- .file("b/Cargo.toml", r#"
- [package]
- name = "bar"
- authors = []
- version = "0.0.0"
- "#)
- .file("b/src/main.rs", "fn main() {}");
- let p = p.build();
-
- let mut a = p.cargo("install").cwd(p.root().join("a")).build_command();
- let mut b = p.cargo("install").cwd(p.root().join("b")).build_command();
-
- a.stdout(Stdio::piped()).stderr(Stdio::piped());
- b.stdout(Stdio::piped()).stderr(Stdio::piped());
-
- let a = a.spawn().unwrap();
- let b = b.spawn().unwrap();
- let a = thread::spawn(move || a.wait_with_output().unwrap());
- let b = b.wait_with_output().unwrap();
- let a = a.join().unwrap();
-
- assert_that(a, execs().with_status(0));
- assert_that(b, execs().with_status(0));
-
- assert_that(cargo_home(), has_installed_exe("foo"));
- assert_that(cargo_home(), has_installed_exe("bar"));
-}
-
-#[test]
-fn concurrent_installs() {
- const LOCKED_BUILD: &'static str = "waiting for file lock on build directory";
-
- pkg("foo", "0.0.1");
- pkg("bar", "0.0.1");
-
- let mut a = cargotest::cargo_process().arg("install").arg("foo").build_command();
- let mut b = cargotest::cargo_process().arg("install").arg("bar").build_command();
-
- a.stdout(Stdio::piped()).stderr(Stdio::piped());
- b.stdout(Stdio::piped()).stderr(Stdio::piped());
-
- let a = a.spawn().unwrap();
- let b = b.spawn().unwrap();
- let a = thread::spawn(move || a.wait_with_output().unwrap());
- let b = b.wait_with_output().unwrap();
- let a = a.join().unwrap();
-
- assert!(!str::from_utf8(&a.stderr).unwrap().contains(LOCKED_BUILD));
- assert!(!str::from_utf8(&b.stderr).unwrap().contains(LOCKED_BUILD));
-
- assert_that(a, execs().with_status(0));
- assert_that(b, execs().with_status(0));
-
- assert_that(cargo_home(), has_installed_exe("foo"));
- assert_that(cargo_home(), has_installed_exe("bar"));
-}
-
-#[test]
-fn one_install_should_be_bad() {
- let p = project("foo")
- .file("a/Cargo.toml", r#"
- [package]
- name = "foo"
- authors = []
- version = "0.0.0"
- "#)
- .file("a/src/main.rs", "fn main() {}")
- .file("b/Cargo.toml", r#"
- [package]
- name = "foo"
- authors = []
- version = "0.0.0"
- "#)
- .file("b/src/main.rs", "fn main() {}");
- let p = p.build();
-
- let mut a = p.cargo("install").cwd(p.root().join("a")).build_command();
- let mut b = p.cargo("install").cwd(p.root().join("b")).build_command();
-
- a.stdout(Stdio::piped()).stderr(Stdio::piped());
- b.stdout(Stdio::piped()).stderr(Stdio::piped());
-
- let a = a.spawn().unwrap();
- let b = b.spawn().unwrap();
- let a = thread::spawn(move || a.wait_with_output().unwrap());
- let b = b.wait_with_output().unwrap();
- let a = a.join().unwrap();
-
- let (bad, good) = if a.status.code() == Some(101) {(a, b)} else {(b, a)};
- assert_that(bad, execs().with_status(101).with_stderr_contains("\
-[ERROR] binary `foo[..]` already exists in destination as part of `[..]`
-"));
- assert_that(good, execs().with_status(0).with_stderr_contains("\
-warning: be sure to add `[..]` to your PATH [..]
-"));
-
- assert_that(cargo_home(), has_installed_exe("foo"));
-}
-
-#[test]
-fn multiple_registry_fetches() {
- let mut pkg = Package::new("bar", "1.0.2");
- for i in 0..10 {
- let name = format!("foo{}", i);
- Package::new(&name, "1.0.0").publish();
- pkg.dep(&name, "*");
- }
- pkg.publish();
-
- let p = project("foo")
- .file("a/Cargo.toml", r#"
- [package]
- name = "foo"
- authors = []
- version = "0.0.0"
-
- [dependencies]
- bar = "*"
- "#)
- .file("a/src/main.rs", "fn main() {}")
- .file("b/Cargo.toml", r#"
- [package]
- name = "bar"
- authors = []
- version = "0.0.0"
-
- [dependencies]
- bar = "*"
- "#)
- .file("b/src/main.rs", "fn main() {}");
- let p = p.build();
-
- let mut a = p.cargo("build").cwd(p.root().join("a")).build_command();
- let mut b = p.cargo("build").cwd(p.root().join("b")).build_command();
-
- a.stdout(Stdio::piped()).stderr(Stdio::piped());
- b.stdout(Stdio::piped()).stderr(Stdio::piped());
-
- let a = a.spawn().unwrap();
- let b = b.spawn().unwrap();
- let a = thread::spawn(move || a.wait_with_output().unwrap());
- let b = b.wait_with_output().unwrap();
- let a = a.join().unwrap();
-
- assert_that(a, execs().with_status(0));
- assert_that(b, execs().with_status(0));
-
- let suffix = env::consts::EXE_SUFFIX;
- assert_that(&p.root().join("a/target/debug").join(format!("foo{}", suffix)),
- existing_file());
- assert_that(&p.root().join("b/target/debug").join(format!("bar{}", suffix)),
- existing_file());
-}
-
-#[test]
-fn git_same_repo_different_tags() {
- let a = git::new("dep", |project| {
- project.file("Cargo.toml", r#"
- [project]
- name = "dep"
- version = "0.5.0"
- authors = []
- "#).file("src/lib.rs", "pub fn tag1() {}")
- }).unwrap();
-
- let repo = git2::Repository::open(&a.root()).unwrap();
- git::tag(&repo, "tag1");
-
- File::create(a.root().join("src/lib.rs")).unwrap()
- .write_all(b"pub fn tag2() {}").unwrap();
- git::add(&repo);
- git::commit(&repo);
- git::tag(&repo, "tag2");
-
- let p = project("foo")
- .file("a/Cargo.toml", &format!(r#"
- [package]
- name = "foo"
- authors = []
- version = "0.0.0"
-
- [dependencies]
- dep = {{ git = '{}', tag = 'tag1' }}
- "#, a.url()))
- .file("a/src/main.rs", "extern crate dep; fn main() { dep::tag1(); }")
- .file("b/Cargo.toml", &format!(r#"
- [package]
- name = "bar"
- authors = []
- version = "0.0.0"
-
- [dependencies]
- dep = {{ git = '{}', tag = 'tag2' }}
- "#, a.url()))
- .file("b/src/main.rs", "extern crate dep; fn main() { dep::tag2(); }");
- let p = p.build();
-
- let mut a = p.cargo("build").arg("-v").cwd(p.root().join("a")).build_command();
- let mut b = p.cargo("build").arg("-v").cwd(p.root().join("b")).build_command();
-
- a.stdout(Stdio::piped()).stderr(Stdio::piped());
- b.stdout(Stdio::piped()).stderr(Stdio::piped());
-
- let a = a.spawn().unwrap();
- let b = b.spawn().unwrap();
- let a = thread::spawn(move || a.wait_with_output().unwrap());
- let b = b.wait_with_output().unwrap();
- let a = a.join().unwrap();
-
- assert_that(a, execs().with_status(0));
- assert_that(b, execs().with_status(0));
-}
-
-#[test]
-fn git_same_branch_different_revs() {
- let a = git::new("dep", |project| {
- project.file("Cargo.toml", r#"
- [project]
- name = "dep"
- version = "0.5.0"
- authors = []
- "#).file("src/lib.rs", "pub fn f1() {}")
- }).unwrap();
-
- let p = project("foo")
- .file("a/Cargo.toml", &format!(r#"
- [package]
- name = "foo"
- authors = []
- version = "0.0.0"
-
- [dependencies]
- dep = {{ git = '{}' }}
- "#, a.url()))
- .file("a/src/main.rs", "extern crate dep; fn main() { dep::f1(); }")
- .file("b/Cargo.toml", &format!(r#"
- [package]
- name = "bar"
- authors = []
- version = "0.0.0"
-
- [dependencies]
- dep = {{ git = '{}' }}
- "#, a.url()))
- .file("b/src/main.rs", "extern crate dep; fn main() { dep::f2(); }");
- let p = p.build();
-
- // Generate a Cargo.lock pointing at the current rev, then clear out the
- // target directory
- assert_that(p.cargo("build").cwd(p.root().join("a")),
- execs().with_status(0));
- fs::remove_dir_all(p.root().join("a/target")).unwrap();
-
- // Make a new commit on the master branch
- let repo = git2::Repository::open(&a.root()).unwrap();
- File::create(a.root().join("src/lib.rs")).unwrap()
- .write_all(b"pub fn f2() {}").unwrap();
- git::add(&repo);
- git::commit(&repo);
-
- // Now run both builds in parallel. The build of `b` should pick up the
- // newest commit while the build of `a` should use the locked old commit.
- let mut a = p.cargo("build").cwd(p.root().join("a")).build_command();
- let mut b = p.cargo("build").cwd(p.root().join("b")).build_command();
-
- a.stdout(Stdio::piped()).stderr(Stdio::piped());
- b.stdout(Stdio::piped()).stderr(Stdio::piped());
-
- let a = a.spawn().unwrap();
- let b = b.spawn().unwrap();
- let a = thread::spawn(move || a.wait_with_output().unwrap());
- let b = b.wait_with_output().unwrap();
- let a = a.join().unwrap();
-
- assert_that(a, execs().with_status(0));
- assert_that(b, execs().with_status(0));
-}
-
-#[test]
-fn same_project() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- authors = []
- version = "0.0.0"
- "#)
- .file("src/main.rs", "fn main() {}")
- .file("src/lib.rs", "");
- let p = p.build();
-
- let mut a = p.cargo("build").build_command();
- let mut b = p.cargo("build").build_command();
-
- a.stdout(Stdio::piped()).stderr(Stdio::piped());
- b.stdout(Stdio::piped()).stderr(Stdio::piped());
-
- let a = a.spawn().unwrap();
- let b = b.spawn().unwrap();
- let a = thread::spawn(move || a.wait_with_output().unwrap());
- let b = b.wait_with_output().unwrap();
- let a = a.join().unwrap();
-
- assert_that(a, execs().with_status(0));
- assert_that(b, execs().with_status(0));
-}
-
-// Make sure that if Cargo dies while holding a lock that it's released and the
-// next Cargo to come in will take over cleanly.
-// older win versions don't support job objects, so skip test there
-#[test]
-#[cfg_attr(target_os = "windows", ignore)]
-fn killing_cargo_releases_the_lock() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- authors = []
- version = "0.0.0"
- build = "build.rs"
- "#)
- .file("src/main.rs", "fn main() {}")
- .file("build.rs", r#"
- use std::net::TcpStream;
-
- fn main() {
- if std::env::var("A").is_ok() {
- TcpStream::connect(&std::env::var("ADDR").unwrap()[..])
- .unwrap();
- std::thread::sleep(std::time::Duration::new(10, 0));
- }
- }
- "#);
- let p = p.build();
-
- // Our build script will connect to our local TCP socket to inform us that
- // it's started and that's how we know that `a` will have the lock
- // when we kill it.
- let l = TcpListener::bind("127.0.0.1:0").unwrap();
- let mut a = p.cargo("build").build_command();
- let mut b = p.cargo("build").build_command();
- a.stdout(Stdio::piped()).stderr(Stdio::piped());
- b.stdout(Stdio::piped()).stderr(Stdio::piped());
- a.env("ADDR", l.local_addr().unwrap().to_string()).env("A", "a");
- b.env("ADDR", l.local_addr().unwrap().to_string()).env_remove("A");
-
- // Spawn `a`, wait for it to get to the build script (at which point the
- // lock is held), then kill it.
- let mut a = a.spawn().unwrap();
- l.accept().unwrap();
- a.kill().unwrap();
-
- // Spawn `b`, then just finish the output of a/b the same way the above
- // tests does.
- let b = b.spawn().unwrap();
- let a = thread::spawn(move || a.wait_with_output().unwrap());
- let b = b.wait_with_output().unwrap();
- let a = a.join().unwrap();
-
- // We killed `a`, so it shouldn't succeed, but `b` should have succeeded.
- assert!(!a.status.success());
- assert_that(b, execs().with_status(0));
-}
-
-#[test]
-fn debug_release_ok() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- authors = []
- version = "0.0.0"
- "#)
- .file("src/main.rs", "fn main() {}");
- let p = p.build();
-
- assert_that(p.cargo("build"), execs().with_status(0));
- fs::remove_dir_all(p.root().join("target")).unwrap();
-
- let mut a = p.cargo("build").build_command();
- let mut b = p.cargo("build").arg("--release").build_command();
- a.stdout(Stdio::piped()).stderr(Stdio::piped());
- b.stdout(Stdio::piped()).stderr(Stdio::piped());
- let a = a.spawn().unwrap();
- let b = b.spawn().unwrap();
- let a = thread::spawn(move || a.wait_with_output().unwrap());
- let b = b.wait_with_output().unwrap();
- let a = a.join().unwrap();
-
- assert_that(a, execs().with_status(0).with_stderr("\
-[COMPILING] foo v0.0.0 [..]
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
- assert_that(b, execs().with_status(0).with_stderr("\
-[COMPILING] foo v0.0.0 [..]
-[FINISHED] release [optimized] target(s) in [..]
-"));
-}
-
-#[test]
-fn no_deadlock_with_git_dependencies() {
- let dep1 = git::new("dep1", |project| {
- project.file("Cargo.toml", r#"
- [project]
- name = "dep1"
- version = "0.5.0"
- authors = []
- "#).file("src/lib.rs", "")
- }).unwrap();
-
- let dep2 = git::new("dep2", |project| {
- project.file("Cargo.toml", r#"
- [project]
- name = "dep2"
- version = "0.5.0"
- authors = []
- "#).file("src/lib.rs", "")
- }).unwrap();
-
- let p = project("foo")
- .file("Cargo.toml", &format!(r#"
- [package]
- name = "foo"
- authors = []
- version = "0.0.0"
-
- [dependencies]
- dep1 = {{ git = '{}' }}
- dep2 = {{ git = '{}' }}
- "#, dep1.url(), dep2.url()))
- .file("src/main.rs", "fn main() { }");
- let p = p.build();
-
- let n_concurrent_builds = 5;
-
- let (tx, rx) = channel();
- for _ in 0..n_concurrent_builds {
- let cmd = p.cargo("build").build_command()
- .stdout(Stdio::piped())
- .stderr(Stdio::piped())
- .spawn();
- let tx = tx.clone();
- thread::spawn(move || {
- let result = cmd.unwrap().wait_with_output().unwrap();
- tx.send(result).unwrap()
- });
- }
-
- //TODO: use `Receiver::recv_timeout` once it is stable.
- let recv_timeout = |chan: &::std::sync::mpsc::Receiver<_>| {
- for _ in 0..3000 {
- if let Ok(x) = chan.try_recv() {
- return x
- }
- thread::sleep(Duration::from_millis(10));
- }
- chan.try_recv().expect("Deadlock!")
- };
-
- for _ in 0..n_concurrent_builds {
- let result = recv_timeout(&rx);
- assert_that(result, execs().with_status(0))
- }
-
-}
+++ /dev/null
-extern crate hamcrest;
-extern crate cargotest;
-
-use cargotest::support::{project, execs};
-use hamcrest::assert_that;
-
-#[test]
-fn read_env_vars_for_config() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- authors = []
- version = "0.0.0"
- build = "build.rs"
- "#)
- .file("src/lib.rs", "")
- .file("build.rs", r#"
- use std::env;
- fn main() {
- assert_eq!(env::var("NUM_JOBS").unwrap(), "100");
- }
- "#)
- .build();
-
- assert_that(p.cargo("build").env("CARGO_BUILD_JOBS", "100"),
- execs().with_status(0));
-}
+++ /dev/null
-extern crate cargo;
-extern crate cargotest;
-extern crate hamcrest;
-
-use cargo::util::process;
-use cargotest::{is_nightly, rustc_host};
-use cargotest::support::{project, execs, basic_bin_manifest, cross_compile};
-use hamcrest::{assert_that, existing_file};
-
-#[test]
-fn simple_cross() {
- if cross_compile::disabled() { return }
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.0"
- authors = []
- build = "build.rs"
- "#)
- .file("build.rs", &format!(r#"
- fn main() {{
- assert_eq!(std::env::var("TARGET").unwrap(), "{}");
- }}
- "#, cross_compile::alternate()))
- .file("src/main.rs", &format!(r#"
- use std::env;
- fn main() {{
- assert_eq!(env::consts::ARCH, "{}");
- }}
- "#, cross_compile::alternate_arch()))
- .build();
-
- let target = cross_compile::alternate();
- assert_that(p.cargo("build").arg("--target").arg(&target).arg("-v"),
- execs().with_status(0));
- assert_that(&p.target_bin(&target, "foo"), existing_file());
-
- assert_that(process(&p.target_bin(&target, "foo")),
- execs().with_status(0));
-}
-
-#[test]
-fn simple_cross_config() {
- if cross_compile::disabled() { return }
-
- let p = project("foo")
- .file(".cargo/config", &format!(r#"
- [build]
- target = "{}"
- "#, cross_compile::alternate()))
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.0"
- authors = []
- build = "build.rs"
- "#)
- .file("build.rs", &format!(r#"
- fn main() {{
- assert_eq!(std::env::var("TARGET").unwrap(), "{}");
- }}
- "#, cross_compile::alternate()))
- .file("src/main.rs", &format!(r#"
- use std::env;
- fn main() {{
- assert_eq!(env::consts::ARCH, "{}");
- }}
- "#, cross_compile::alternate_arch()))
- .build();
-
- let target = cross_compile::alternate();
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(0));
- assert_that(&p.target_bin(&target, "foo"), existing_file());
-
- assert_that(process(&p.target_bin(&target, "foo")),
- execs().with_status(0));
-}
-
-#[test]
-fn simple_deps() {
- if cross_compile::disabled() { return }
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies.bar]
- path = "../bar"
- "#)
- .file("src/main.rs", r#"
- extern crate bar;
- fn main() { bar::bar(); }
- "#)
- .build();
- let _p2 = project("bar")
- .file("Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/lib.rs", "pub fn bar() {}")
- .build();
-
- let target = cross_compile::alternate();
- assert_that(p.cargo("build").arg("--target").arg(&target),
- execs().with_status(0));
- assert_that(&p.target_bin(&target, "foo"), existing_file());
-
- assert_that(process(&p.target_bin(&target, "foo")),
- execs().with_status(0));
-}
-
-#[test]
-fn plugin_deps() {
- if cross_compile::disabled() { return }
- if !is_nightly() { return }
-
- let foo = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies.bar]
- path = "../bar"
-
- [dependencies.baz]
- path = "../baz"
- "#)
- .file("src/main.rs", r#"
- #![feature(plugin)]
- #![plugin(bar)]
- extern crate baz;
- fn main() {
- assert_eq!(bar!(), baz::baz());
- }
- "#)
- .build();
- let _bar = project("bar")
- .file("Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
-
- [lib]
- name = "bar"
- plugin = true
- "#)
- .file("src/lib.rs", r#"
- #![feature(plugin_registrar, quote, rustc_private)]
-
- extern crate rustc_plugin;
- extern crate syntax;
-
- use rustc_plugin::Registry;
- use syntax::tokenstream::TokenTree;
- use syntax::codemap::Span;
- use syntax::ast::*;
- use syntax::ext::base::{ExtCtxt, MacEager, MacResult};
- use syntax::ext::build::AstBuilder;
-
- #[plugin_registrar]
- pub fn foo(reg: &mut Registry) {
- reg.register_macro("bar", expand_bar);
- }
-
- fn expand_bar(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree])
- -> Box<MacResult + 'static> {
- MacEager::expr(cx.expr_lit(sp, LitKind::Int(1, LitIntType::Unsuffixed)))
- }
- "#)
- .build();
- let _baz = project("baz")
- .file("Cargo.toml", r#"
- [package]
- name = "baz"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/lib.rs", "pub fn baz() -> i32 { 1 }")
- .build();
-
- let target = cross_compile::alternate();
- assert_that(foo.cargo("build").arg("--target").arg(&target),
- execs().with_status(0));
- assert_that(&foo.target_bin(&target, "foo"), existing_file());
-
- assert_that(process(&foo.target_bin(&target, "foo")),
- execs().with_status(0));
-}
-
-#[test]
-fn plugin_to_the_max() {
- if cross_compile::disabled() { return }
- if !is_nightly() { return }
-
- let foo = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies.bar]
- path = "../bar"
-
- [dependencies.baz]
- path = "../baz"
- "#)
- .file("src/main.rs", r#"
- #![feature(plugin)]
- #![plugin(bar)]
- extern crate baz;
- fn main() {
- assert_eq!(bar!(), baz::baz());
- }
- "#)
- .build();
- let _bar = project("bar")
- .file("Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
-
- [lib]
- name = "bar"
- plugin = true
-
- [dependencies.baz]
- path = "../baz"
- "#)
- .file("src/lib.rs", r#"
- #![feature(plugin_registrar, quote, rustc_private)]
-
- extern crate rustc_plugin;
- extern crate syntax;
- extern crate baz;
-
- use rustc_plugin::Registry;
- use syntax::tokenstream::TokenTree;
- use syntax::codemap::Span;
- use syntax::ast::*;
- use syntax::ext::base::{ExtCtxt, MacEager, MacResult};
- use syntax::ext::build::AstBuilder;
- use syntax::ptr::P;
-
- #[plugin_registrar]
- pub fn foo(reg: &mut Registry) {
- reg.register_macro("bar", expand_bar);
- }
-
- fn expand_bar(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree])
- -> Box<MacResult + 'static> {
- let bar = Ident::from_str("baz");
- let path = cx.path(sp, vec![bar.clone(), bar]);
- MacEager::expr(cx.expr_call(sp, cx.expr_path(path), vec![]))
- }
- "#)
- .build();
- let _baz = project("baz")
- .file("Cargo.toml", r#"
- [package]
- name = "baz"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/lib.rs", "pub fn baz() -> i32 { 1 }")
- .build();
-
- let target = cross_compile::alternate();
- assert_that(foo.cargo("build").arg("--target").arg(&target).arg("-v"),
- execs().with_status(0));
- println!("second");
- assert_that(foo.cargo("build").arg("-v")
- .arg("--target").arg(&target),
- execs().with_status(0));
- assert_that(&foo.target_bin(&target, "foo"), existing_file());
-
- assert_that(process(&foo.target_bin(&target, "foo")),
- execs().with_status(0));
-}
-
-#[test]
-fn linker_and_ar() {
- if cross_compile::disabled() { return }
-
- let target = cross_compile::alternate();
- let p = project("foo")
- .file(".cargo/config", &format!(r#"
- [target.{}]
- ar = "my-ar-tool"
- linker = "my-linker-tool"
- "#, target))
- .file("Cargo.toml", &basic_bin_manifest("foo"))
- .file("src/foo.rs", &format!(r#"
- use std::env;
- fn main() {{
- assert_eq!(env::consts::ARCH, "{}");
- }}
- "#, cross_compile::alternate_arch()))
- .build();
-
- assert_that(p.cargo("build").arg("--target").arg(&target)
- .arg("-v"),
- execs().with_status(101)
- .with_stderr_contains(&format!("\
-[COMPILING] foo v0.5.0 ({url})
-[RUNNING] `rustc --crate-name foo src[/]foo.rs --crate-type bin \
- --emit=dep-info,link -C debuginfo=2 \
- -C metadata=[..] \
- --out-dir {dir}[/]target[/]{target}[/]debug[/]deps \
- --target {target} \
- -C ar=my-ar-tool -C linker=my-linker-tool \
- -L dependency={dir}[/]target[/]{target}[/]debug[/]deps \
- -L dependency={dir}[/]target[/]debug[/]deps`
-",
- dir = p.root().display(),
- url = p.url(),
- target = target,
- )));
-}
-
-#[test]
-fn plugin_with_extra_dylib_dep() {
- if cross_compile::disabled() { return }
- if !is_nightly() { return }
-
- let foo = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies.bar]
- path = "../bar"
- "#)
- .file("src/main.rs", r#"
- #![feature(plugin)]
- #![plugin(bar)]
-
- fn main() {}
- "#)
- .build();
- let _bar = project("bar")
- .file("Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
-
- [lib]
- name = "bar"
- plugin = true
-
- [dependencies.baz]
- path = "../baz"
- "#)
- .file("src/lib.rs", r#"
- #![feature(plugin_registrar, rustc_private)]
-
- extern crate rustc_plugin;
- extern crate baz;
-
- use rustc_plugin::Registry;
-
- #[plugin_registrar]
- pub fn foo(reg: &mut Registry) {
- println!("{}", baz::baz());
- }
- "#)
- .build();
- let _baz = project("baz")
- .file("Cargo.toml", r#"
- [package]
- name = "baz"
- version = "0.0.1"
- authors = []
-
- [lib]
- name = "baz"
- crate_type = ["dylib"]
- "#)
- .file("src/lib.rs", "pub fn baz() -> i32 { 1 }")
- .build();
-
- let target = cross_compile::alternate();
- assert_that(foo.cargo("build").arg("--target").arg(&target),
- execs().with_status(0));
-}
-
-#[test]
-fn cross_tests() {
- if cross_compile::disabled() { return }
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- authors = []
- version = "0.0.0"
-
- [[bin]]
- name = "bar"
- "#)
- .file("src/bin/bar.rs", &format!(r#"
- #[allow(unused_extern_crates)]
- extern crate foo;
- use std::env;
- fn main() {{
- assert_eq!(env::consts::ARCH, "{}");
- }}
- #[test] fn test() {{ main() }}
- "#, cross_compile::alternate_arch()))
- .file("src/lib.rs", &format!(r#"
- use std::env;
- pub fn foo() {{ assert_eq!(env::consts::ARCH, "{}"); }}
- #[test] fn test_foo() {{ foo() }}
- "#, cross_compile::alternate_arch()))
- .build();
-
- let target = cross_compile::alternate();
- assert_that(p.cargo("test").arg("--target").arg(&target),
- execs().with_status(0)
- .with_stderr(&format!("\
-[COMPILING] foo v0.0.0 ({foo})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] target[/]{triple}[/]debug[/]deps[/]foo-[..][EXE]
-[RUNNING] target[/]{triple}[/]debug[/]deps[/]bar-[..][EXE]", foo = p.url(), triple = target))
- .with_stdout_contains("test test_foo ... ok")
- .with_stdout_contains("test test ... ok"));
-}
-
-#[test]
-fn no_cross_doctests() {
- if cross_compile::disabled() { return }
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- authors = []
- version = "0.0.0"
- "#)
- .file("src/lib.rs", r#"
- //! ```
- //! extern crate foo;
- //! assert!(true);
- //! ```
- "#)
- .build();
-
- let host_output = format!("\
-[COMPILING] foo v0.0.0 ({foo})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] target[/]debug[/]deps[/]foo-[..][EXE]
-[DOCTEST] foo
-", foo = p.url());
-
- println!("a");
- assert_that(p.cargo("test"),
- execs().with_status(0)
- .with_stderr(&host_output));
-
- println!("b");
- let target = cross_compile::host();
- assert_that(p.cargo("test").arg("--target").arg(&target),
- execs().with_status(0)
- .with_stderr(&format!("\
-[COMPILING] foo v0.0.0 ({foo})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] target[/]{triple}[/]debug[/]deps[/]foo-[..][EXE]
-[DOCTEST] foo
-", foo = p.url(), triple = target)));
-
- println!("c");
- let target = cross_compile::alternate();
- assert_that(p.cargo("test").arg("--target").arg(&target),
- execs().with_status(0)
- .with_stderr(&format!("\
-[COMPILING] foo v0.0.0 ({foo})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] target[/]{triple}[/]debug[/]deps[/]foo-[..][EXE]
-", foo = p.url(), triple = target)));
-}
-
-#[test]
-fn simple_cargo_run() {
- if cross_compile::disabled() { return }
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.0"
- authors = []
- "#)
- .file("src/main.rs", &format!(r#"
- use std::env;
- fn main() {{
- assert_eq!(env::consts::ARCH, "{}");
- }}
- "#, cross_compile::alternate_arch()))
- .build();
-
- let target = cross_compile::alternate();
- assert_that(p.cargo("run").arg("--target").arg(&target),
- execs().with_status(0));
-}
-
-#[test]
-fn cross_with_a_build_script() {
- if cross_compile::disabled() { return }
-
- let target = cross_compile::alternate();
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.0"
- authors = []
- build = 'build.rs'
- "#)
- .file("build.rs", &format!(r#"
- use std::env;
- use std::path::PathBuf;
- fn main() {{
- assert_eq!(env::var("TARGET").unwrap(), "{0}");
- let mut path = PathBuf::from(env::var_os("OUT_DIR").unwrap());
- assert_eq!(path.file_name().unwrap().to_str().unwrap(), "out");
- path.pop();
- assert!(path.file_name().unwrap().to_str().unwrap()
- .starts_with("foo-"));
- path.pop();
- assert_eq!(path.file_name().unwrap().to_str().unwrap(), "build");
- path.pop();
- assert_eq!(path.file_name().unwrap().to_str().unwrap(), "debug");
- path.pop();
- assert_eq!(path.file_name().unwrap().to_str().unwrap(), "{0}");
- path.pop();
- assert_eq!(path.file_name().unwrap().to_str().unwrap(), "target");
- }}
- "#, target))
- .file("src/main.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("build").arg("--target").arg(&target).arg("-v"),
- execs().with_status(0)
- .with_stderr(&format!("\
-[COMPILING] foo v0.0.0 (file://[..])
-[RUNNING] `rustc [..] build.rs [..] --out-dir {dir}[/]target[/]debug[/]build[/]foo-[..]`
-[RUNNING] `{dir}[/]target[/]debug[/]build[/]foo-[..][/]build-script-build`
-[RUNNING] `rustc [..] src[/]main.rs [..] --target {target} [..]`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-", target = target,
- dir = p.root().display())));
-}
-
-#[test]
-fn build_script_needed_for_host_and_target() {
- if cross_compile::disabled() { return }
-
- let target = cross_compile::alternate();
- let host = rustc_host();
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.0"
- authors = []
- build = 'build.rs'
-
- [dependencies.d1]
- path = "d1"
- [build-dependencies.d2]
- path = "d2"
- "#)
-
- .file("build.rs", r#"
- #[allow(unused_extern_crates)]
- extern crate d2;
- fn main() { d2::d2(); }
- "#)
- .file("src/main.rs", "
- #[allow(unused_extern_crates)]
- extern crate d1;
- fn main() { d1::d1(); }
- ")
- .file("d1/Cargo.toml", r#"
- [package]
- name = "d1"
- version = "0.0.0"
- authors = []
- build = 'build.rs'
- "#)
- .file("d1/src/lib.rs", "
- pub fn d1() {}
- ")
- .file("d1/build.rs", r#"
- use std::env;
- fn main() {
- let target = env::var("TARGET").unwrap();
- println!("cargo:rustc-flags=-L /path/to/{}", target);
- }
- "#)
- .file("d2/Cargo.toml", r#"
- [package]
- name = "d2"
- version = "0.0.0"
- authors = []
-
- [dependencies.d1]
- path = "../d1"
- "#)
- .file("d2/src/lib.rs", "
- #[allow(unused_extern_crates)]
- extern crate d1;
- pub fn d2() { d1::d1(); }
- ")
- .build();
-
- assert_that(p.cargo("build").arg("--target").arg(&target).arg("-v"),
- execs().with_status(0)
- .with_stderr_contains(&format!("\
-[COMPILING] d1 v0.0.0 ({url}/d1)", url = p.url()))
- .with_stderr_contains(&format!("\
-[RUNNING] `rustc [..] d1[/]build.rs [..] --out-dir {dir}[/]target[/]debug[/]build[/]d1-[..]`",
- dir = p.root().display()))
- .with_stderr_contains(&format!("\
-[RUNNING] `{dir}[/]target[/]debug[/]build[/]d1-[..][/]build-script-build`",
- dir = p.root().display()))
- .with_stderr_contains("\
-[RUNNING] `rustc [..] d1[/]src[/]lib.rs [..]`")
- .with_stderr_contains(&format!("\
-[COMPILING] d2 v0.0.0 ({url}/d2)", url = p.url()))
- .with_stderr_contains(&format!("\
-[RUNNING] `rustc [..] d2[/]src[/]lib.rs [..] \
- -L /path/to/{host}`", host = host))
- .with_stderr_contains(&format!("\
-[COMPILING] foo v0.0.0 ({url})", url = p.url()))
- .with_stderr_contains(&format!("\
-[RUNNING] `rustc [..] build.rs [..] --out-dir {dir}[/]target[/]debug[/]build[/]foo-[..] \
- -L /path/to/{host}`", dir = p.root().display(), host = host))
- .with_stderr_contains(&format!("\
-[RUNNING] `rustc [..] src[/]main.rs [..] --target {target} [..] \
- -L /path/to/{target}`", target = target)));
-}
-
-#[test]
-fn build_deps_for_the_right_arch() {
- if cross_compile::disabled() { return }
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.0"
- authors = []
-
- [dependencies.d2]
- path = "d2"
- "#)
- .file("src/main.rs", "extern crate d2; fn main() {}")
- .file("d1/Cargo.toml", r#"
- [package]
- name = "d1"
- version = "0.0.0"
- authors = []
- "#)
- .file("d1/src/lib.rs", "
- pub fn d1() {}
- ")
- .file("d2/Cargo.toml", r#"
- [package]
- name = "d2"
- version = "0.0.0"
- authors = []
- build = "build.rs"
-
- [build-dependencies.d1]
- path = "../d1"
- "#)
- .file("d2/build.rs", "extern crate d1; fn main() {}")
- .file("d2/src/lib.rs", "")
- .build();
-
- let target = cross_compile::alternate();
- assert_that(p.cargo("build").arg("--target").arg(&target).arg("-v"),
- execs().with_status(0));
-}
-
-#[test]
-fn build_script_only_host() {
- if cross_compile::disabled() { return }
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.0"
- authors = []
- build = "build.rs"
-
- [build-dependencies.d1]
- path = "d1"
- "#)
- .file("src/main.rs", "fn main() {}")
- .file("build.rs", "extern crate d1; fn main() {}")
- .file("d1/Cargo.toml", r#"
- [package]
- name = "d1"
- version = "0.0.0"
- authors = []
- build = "build.rs"
- "#)
- .file("d1/src/lib.rs", "
- pub fn d1() {}
- ")
- .file("d1/build.rs", r#"
- use std::env;
-
- fn main() {
- assert!(env::var("OUT_DIR").unwrap().replace("\\", "/")
- .contains("target/debug/build/d1-"),
- "bad: {:?}", env::var("OUT_DIR"));
- }
- "#)
- .build();
-
- let target = cross_compile::alternate();
- assert_that(p.cargo("build").arg("--target").arg(&target).arg("-v"),
- execs().with_status(0));
-}
-
-#[test]
-fn plugin_build_script_right_arch() {
- if cross_compile::disabled() { return }
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- build = "build.rs"
-
- [lib]
- name = "foo"
- plugin = true
- "#)
- .file("build.rs", "fn main() {}")
- .file("src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build").arg("-v").arg("--target").arg(cross_compile::alternate()),
- execs().with_status(0)
- .with_stderr("\
-[COMPILING] foo v0.0.1 ([..])
-[RUNNING] `rustc [..] build.rs [..]`
-[RUNNING] `[..][/]build-script-build`
-[RUNNING] `rustc [..] src[/]lib.rs [..]`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-}
-
-#[test]
-fn build_script_with_platform_specific_dependencies() {
- if cross_compile::disabled() { return }
-
- let target = cross_compile::alternate();
- let host = rustc_host();
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- build = "build.rs"
-
- [build-dependencies.d1]
- path = "d1"
- "#)
- .file("build.rs", "
- #[allow(unused_extern_crates)]
- extern crate d1;
- fn main() {}
- ")
- .file("src/lib.rs", "")
- .file("d1/Cargo.toml", &format!(r#"
- [package]
- name = "d1"
- version = "0.0.0"
- authors = []
-
- [target.{}.dependencies]
- d2 = {{ path = "../d2" }}
- "#, host))
- .file("d1/src/lib.rs", "
- #[allow(unused_extern_crates)]
- extern crate d2;
- ")
- .file("d2/Cargo.toml", r#"
- [package]
- name = "d2"
- version = "0.0.0"
- authors = []
- "#)
- .file("d2/src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build").arg("-v").arg("--target").arg(&target),
- execs().with_status(0)
- .with_stderr(&format!("\
-[COMPILING] d2 v0.0.0 ([..])
-[RUNNING] `rustc [..] d2[/]src[/]lib.rs [..]`
-[COMPILING] d1 v0.0.0 ([..])
-[RUNNING] `rustc [..] d1[/]src[/]lib.rs [..]`
-[COMPILING] foo v0.0.1 ([..])
-[RUNNING] `rustc [..] build.rs [..]`
-[RUNNING] `{dir}[/]target[/]debug[/]build[/]foo-[..][/]build-script-build`
-[RUNNING] `rustc [..] src[/]lib.rs [..] --target {target} [..]`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-", dir = p.root().display(), target = target)));
-}
-
-#[test]
-fn platform_specific_dependencies_do_not_leak() {
- if cross_compile::disabled() { return }
-
- let target = cross_compile::alternate();
- let host = rustc_host();
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- build = "build.rs"
-
- [dependencies.d1]
- path = "d1"
-
- [build-dependencies.d1]
- path = "d1"
- "#)
- .file("build.rs", "extern crate d1; fn main() {}")
- .file("src/lib.rs", "")
- .file("d1/Cargo.toml", &format!(r#"
- [package]
- name = "d1"
- version = "0.0.0"
- authors = []
-
- [target.{}.dependencies]
- d2 = {{ path = "../d2" }}
- "#, host))
- .file("d1/src/lib.rs", "extern crate d2;")
- .file("d2/Cargo.toml", r#"
- [package]
- name = "d2"
- version = "0.0.0"
- authors = []
- "#)
- .file("d2/src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build").arg("-v").arg("--target").arg(&target),
- execs().with_status(101)
- .with_stderr_contains("\
-[..] can't find crate for `d2`[..]"));
-}
-
-#[test]
-fn platform_specific_variables_reflected_in_build_scripts() {
- if cross_compile::disabled() { return }
-
- let target = cross_compile::alternate();
- let host = rustc_host();
- let p = project("foo")
- .file("Cargo.toml", &format!(r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- build = "build.rs"
-
- [target.{host}.dependencies]
- d1 = {{ path = "d1" }}
-
- [target.{target}.dependencies]
- d2 = {{ path = "d2" }}
- "#, host = host, target = target))
- .file("build.rs", &format!(r#"
- use std::env;
-
- fn main() {{
- let platform = env::var("TARGET").unwrap();
- let (expected, not_expected) = match &platform[..] {{
- "{host}" => ("DEP_D1_VAL", "DEP_D2_VAL"),
- "{target}" => ("DEP_D2_VAL", "DEP_D1_VAL"),
- _ => panic!("unknown platform")
- }};
-
- env::var(expected).ok()
- .expect(&format!("missing {{}}", expected));
- env::var(not_expected).err()
- .expect(&format!("found {{}}", not_expected));
- }}
- "#, host = host, target = target))
- .file("src/lib.rs", "")
- .file("d1/Cargo.toml", r#"
- [package]
- name = "d1"
- version = "0.0.0"
- authors = []
- links = "d1"
- build = "build.rs"
- "#)
- .file("d1/build.rs", r#"
- fn main() { println!("cargo:val=1") }
- "#)
- .file("d1/src/lib.rs", "")
- .file("d2/Cargo.toml", r#"
- [package]
- name = "d2"
- version = "0.0.0"
- authors = []
- links = "d2"
- build = "build.rs"
- "#)
- .file("d2/build.rs", r#"
- fn main() { println!("cargo:val=1") }
- "#)
- .file("d2/src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build").arg("-v"), execs().with_status(0));
- assert_that(p.cargo("build").arg("-v").arg("--target").arg(&target),
- execs().with_status(0));
-}
-
-#[test]
-fn cross_test_dylib() {
- if cross_compile::disabled() { return }
-
- let target = cross_compile::alternate();
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [lib]
- name = "foo"
- crate_type = ["dylib"]
-
- [dependencies.bar]
- path = "bar"
- "#)
- .file("src/lib.rs", r#"
- extern crate bar as the_bar;
-
- pub fn bar() { the_bar::baz(); }
-
- #[test]
- fn foo() { bar(); }
- "#)
- .file("tests/test.rs", r#"
- extern crate foo as the_foo;
-
- #[test]
- fn foo() { the_foo::bar(); }
- "#)
- .file("bar/Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
-
- [lib]
- name = "bar"
- crate_type = ["dylib"]
- "#)
- .file("bar/src/lib.rs", &format!(r#"
- use std::env;
- pub fn baz() {{
- assert_eq!(env::consts::ARCH, "{}");
- }}
- "#, cross_compile::alternate_arch()))
- .build();
-
- assert_that(p.cargo("test").arg("--target").arg(&target),
- execs().with_status(0)
- .with_stderr(&format!("\
-[COMPILING] bar v0.0.1 ({dir}/bar)
-[COMPILING] foo v0.0.1 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] target[/]{arch}[/]debug[/]deps[/]foo-[..][EXE]
-[RUNNING] target[/]{arch}[/]debug[/]deps[/]test-[..][EXE]",
- dir = p.url(), arch = cross_compile::alternate()))
- .with_stdout_contains_n("test foo ... ok", 2));
-
-}
+++ /dev/null
-extern crate cargo;
-extern crate cargotest;
-extern crate hamcrest;
-extern crate flate2;
-extern crate tar;
-
-use std::fs::File;
-use std::path::PathBuf;
-use std::io::prelude::*;
-
-use cargotest::support::{project, execs, cross_compile, publish};
-use hamcrest::{assert_that, contains};
-use flate2::read::GzDecoder;
-use tar::Archive;
-
-#[test]
-fn simple_cross_package() {
- if cross_compile::disabled() { return }
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.0"
- authors = []
- license = "MIT"
- description = "foo"
- repository = "bar"
- "#)
- .file("src/main.rs", &format!(r#"
- use std::env;
- fn main() {{
- assert_eq!(env::consts::ARCH, "{}");
- }}
- "#, cross_compile::alternate_arch()))
- .build();
-
- let target = cross_compile::alternate();
-
- assert_that(p.cargo("package").arg("--target").arg(&target),
- execs().with_status(0).with_status(0).with_stderr(&format!(
-" Packaging foo v0.0.0 ({dir})
- Verifying foo v0.0.0 ({dir})
- Compiling foo v0.0.0 ({dir}/target/package/foo-0.0.0)
- Finished dev [unoptimized + debuginfo] target(s) in [..]
-", dir = p.url())));
-
- // Check that the tarball contains the files
- let f = File::open(&p.root().join("target/package/foo-0.0.0.crate")).unwrap();
- let mut rdr = GzDecoder::new(f);
- let mut contents = Vec::new();
- rdr.read_to_end(&mut contents).unwrap();
- let mut ar = Archive::new(&contents[..]);
- let entries = ar.entries().unwrap();
- let entry_paths = entries.map(|entry| {
- entry.unwrap().path().unwrap().into_owned()
- }).collect::<Vec<PathBuf>>();
- assert_that(&entry_paths, contains(vec![PathBuf::from("foo-0.0.0/Cargo.toml")]));
- assert_that(&entry_paths, contains(vec![PathBuf::from("foo-0.0.0/Cargo.toml.orig")]));
- assert_that(&entry_paths, contains(vec![PathBuf::from("foo-0.0.0/src/main.rs")]));
-}
-
-#[test]
-fn publish_with_target() {
- if cross_compile::disabled() { return }
-
- publish::setup();
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.0"
- authors = []
- license = "MIT"
- description = "foo"
- repository = "bar"
- "#)
- .file("src/main.rs", &format!(r#"
- use std::env;
- fn main() {{
- assert_eq!(env::consts::ARCH, "{}");
- }}
- "#, cross_compile::alternate_arch()))
- .build();
-
- let target = cross_compile::alternate();
-
- assert_that(p.cargo("publish")
- .arg("--index").arg(publish::registry().to_string())
- .arg("--target").arg(&target),
- execs().with_status(0).with_stderr(&format!(
-" Updating registry `{registry}`
- Packaging foo v0.0.0 ({dir})
- Verifying foo v0.0.0 ({dir})
- Compiling foo v0.0.0 ({dir}/target/package/foo-0.0.0)
- Finished dev [unoptimized + debuginfo] target(s) in [..]
- Uploading foo v0.0.0 ({dir})
-", dir = p.url(), registry = publish::registry())));
-}
+++ /dev/null
-extern crate cargotest;
-extern crate libc;
-#[cfg(windows)]
-extern crate winapi;
-
-use std::fs;
-use std::io::{self, Read};
-use std::net::TcpListener;
-use std::process::{Stdio, Child};
-use std::thread;
-use std::time::Duration;
-
-use cargotest::support::project;
-
-#[cfg(unix)]
-fn enabled() -> bool {
- true
-}
-
-// On Windows support for these tests is only enabled through the usage of job
-// objects. Support for nested job objects, however, was added in recent-ish
-// versions of Windows, so this test may not always be able to succeed.
-//
-// As a result, we try to add ourselves to a job object here
-// can succeed or not.
-#[cfg(windows)]
-fn enabled() -> bool {
- use winapi::um::{handleapi, jobapi, jobapi2, processthreadsapi};
-
- unsafe {
- // If we're not currently in a job, then we can definitely run these
- // tests.
- let me = processthreadsapi::GetCurrentProcess();
- let mut ret = 0;
- let r = jobapi::IsProcessInJob(me, 0 as *mut _, &mut ret);
- assert!(r != 0);
- if ret == winapi::shared::minwindef::FALSE {
- return true
- }
-
- // If we are in a job, then we can run these tests if we can be added to
- // a nested job (as we're going to create a nested job no matter what as
- // part of these tests.
- //
- // If we can't be added to a nested job, then these tests will
- // definitely fail, and there's not much we can do about that.
- let job = jobapi2::CreateJobObjectW(0 as *mut _, 0 as *const _);
- assert!(!job.is_null());
- let r = jobapi2::AssignProcessToJobObject(job, me);
- handleapi::CloseHandle(job);
- r != 0
- }
-}
-
-#[test]
-fn ctrl_c_kills_everyone() {
- if !enabled() {
- return
- }
-
- let listener = TcpListener::bind("127.0.0.1:0").unwrap();
- let addr = listener.local_addr().unwrap();
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- build = "build.rs"
- "#)
- .file("src/lib.rs", "")
- .file("build.rs", &format!(r#"
- use std::net::TcpStream;
- use std::io::Read;
-
- fn main() {{
- let mut socket = TcpStream::connect("{}").unwrap();
- let _ = socket.read(&mut [0; 10]);
- panic!("that read should never return");
- }}
- "#, addr))
- .build();
-
- let mut cargo = p.cargo("build").build_command();
- cargo.stdin(Stdio::piped())
- .stdout(Stdio::piped())
- .stderr(Stdio::piped())
- .env("__CARGO_TEST_SETSID_PLEASE_DONT_USE_ELSEWHERE", "1");
- let mut child = cargo.spawn().unwrap();
-
- let mut sock = listener.accept().unwrap().0;
- ctrl_c(&mut child);
-
- assert!(!child.wait().unwrap().success());
- match sock.read(&mut [0; 10]) {
- Ok(n) => assert_eq!(n, 0),
- Err(e) => assert_eq!(e.kind(), io::ErrorKind::ConnectionReset),
- }
-
- // Ok so what we just did was spawn cargo that spawned a build script, then
- // we killed cargo in hopes of it killing the build script as well. If all
- // went well the build script is now dead. On Windows, however, this is
- // enforced with job objects which means that it may actually be in the
- // *process* of being torn down at this point.
- //
- // Now on Windows we can't completely remove a file until all handles to it
- // have been closed. Including those that represent running processes. So if
- // we were to return here then there may still be an open reference to some
- // file in the build directory. What we want to actually do is wait for the
- // build script to *complete* exit. Take care of that by blowing away the
- // build directory here, and panicking if we eventually spin too long
- // without being able to.
- for i in 0..10 {
- match fs::remove_dir_all(&p.root().join("target")) {
- Ok(()) => return,
- Err(e) => println!("attempt {}: {}", i, e),
- }
- thread::sleep(Duration::from_millis(100));
- }
-
- panic!("couldn't remove build directory after a few tries, seems like \
- we won't be able to!");
-}
-
-#[cfg(unix)]
-fn ctrl_c(child: &mut Child) {
- use libc;
-
- let r = unsafe { libc::kill(-(child.id() as i32), libc::SIGINT) };
- if r < 0 {
- panic!("failed to kill: {}", io::Error::last_os_error());
- }
-}
-
-#[cfg(windows)]
-fn ctrl_c(child: &mut Child) {
- child.kill().unwrap();
-}
+++ /dev/null
-extern crate cargotest;
-extern crate hamcrest;
-
-use cargotest::support::{basic_bin_manifest, main_file, execs, project};
-use hamcrest::{assert_that, existing_file};
-
-#[test]
-fn build_dep_info() {
- let p = project("foo")
- .file("Cargo.toml", &basic_bin_manifest("foo"))
- .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
- .build();
-
- assert_that(p.cargo("build"), execs().with_status(0));
-
- let depinfo_bin_path = &p.bin("foo").with_extension("d");
-
- assert_that(depinfo_bin_path, existing_file());
-}
-
-#[test]
-fn build_dep_info_lib() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [[example]]
- name = "ex"
- crate-type = ["lib"]
- "#)
- .file("build.rs", "fn main() {}")
- .file("src/lib.rs", "")
- .file("examples/ex.rs", "")
- .build();
-
- assert_that(p.cargo("build").arg("--example=ex"), execs().with_status(0));
- assert_that(&p.example_lib("ex", "lib").with_extension("d"), existing_file());
-}
-
-
-#[test]
-fn build_dep_info_rlib() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [[example]]
- name = "ex"
- crate-type = ["rlib"]
- "#)
- .file("src/lib.rs", "")
- .file("examples/ex.rs", "")
- .build();
-
- assert_that(p.cargo("build").arg("--example=ex"), execs().with_status(0));
- assert_that(&p.example_lib("ex", "rlib").with_extension("d"), existing_file());
-}
-
-#[test]
-fn build_dep_info_dylib() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [[example]]
- name = "ex"
- crate-type = ["dylib"]
- "#)
- .file("src/lib.rs", "")
- .file("examples/ex.rs", "")
- .build();
-
- assert_that(p.cargo("build").arg("--example=ex"), execs().with_status(0));
- assert_that(&p.example_lib("ex", "dylib").with_extension("d"), existing_file());
-}
+++ /dev/null
-#[macro_use]
-extern crate cargotest;
-extern crate hamcrest;
-#[macro_use]
-extern crate serde_derive;
-extern crate serde_json;
-
-use std::collections::HashMap;
-use std::fs::{self, File};
-use std::io::prelude::*;
-use std::str;
-
-use cargotest::cargo_process;
-use cargotest::support::git;
-use cargotest::support::paths;
-use cargotest::support::registry::{Package, cksum};
-use cargotest::support::{project, execs, ProjectBuilder};
-use hamcrest::assert_that;
-
-fn setup() {
- let root = paths::root();
- t!(fs::create_dir(&root.join(".cargo")));
- t!(t!(File::create(root.join(".cargo/config"))).write_all(br#"
- [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(&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 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();
- }
-}
-
-#[test]
-fn simple() {
- setup();
-
- VendorPackage::new("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
- "#)
- .file("src/lib.rs", "pub fn foo() {}")
- .build();
-
- let p = project("bar")
- .file("Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.1.0"
- authors = []
-
- [dependencies]
- foo = "0.1.0"
- "#)
- .file("src/lib.rs", r#"
- extern crate foo;
-
- pub fn bar() {
- foo::foo();
- }
- "#)
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr("\
-[COMPILING] foo v0.1.0
-[COMPILING] bar v0.1.0 ([..]bar)
-[FINISHED] [..]
-"));
-}
-
-#[test]
-fn simple_install() {
- setup();
-
- VendorPackage::new("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
- "#)
- .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"
- "#)
- .file("src/main.rs", r#"
- extern crate foo;
-
- pub fn main() {
- foo::foo();
- }
- "#)
- .build();
-
- assert_that(cargo_process().arg("install").arg("bar"),
- execs().with_status(0).with_stderr(
-" Installing bar v0.1.0
- Compiling foo v0.1.0
- Compiling bar v0.1.0
- Finished release [optimized] target(s) in [..] secs
- Installing [..]bar[..]
-warning: be sure to add `[..]` to your PATH to be able to run the installed binaries
-"));
-}
-
-#[test]
-fn simple_install_fail() {
- setup();
-
- VendorPackage::new("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
- "#)
- .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", r#"
- extern crate foo;
-
- pub fn main() {
- foo::foo();
- }
- "#)
- .build();
-
- assert_that(cargo_process().arg("install").arg("bar"),
- execs().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 named `baz` found
-location searched: registry `https://github.com/rust-lang/crates.io-index`
-required by package `bar v0.1.0`
-"));
-}
-
-#[test]
-fn install_without_feature_dep() {
- setup();
-
- VendorPackage::new("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
- "#)
- .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 = { version = "9.8.7", optional = true }
-
- [features]
- wantbaz = ["baz"]
- "#)
- .file("src/main.rs", r#"
- extern crate foo;
-
- pub fn main() {
- foo::foo();
- }
- "#)
- .build();
-
- assert_that(cargo_process().arg("install").arg("bar"),
- execs().with_status(0).with_stderr(
-" Installing bar v0.1.0
- Compiling foo v0.1.0
- Compiling bar v0.1.0
- Finished release [optimized] target(s) in [..] secs
- Installing [..]bar[..]
-warning: be sure to add `[..]` to your PATH to be able to run the installed binaries
-"));
-}
-
-#[test]
-fn not_there() {
- setup();
-
- let _ = project("index").build();
-
- let p = project("bar")
- .file("Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.1.0"
- authors = []
-
- [dependencies]
- foo = "0.1.0"
- "#)
- .file("src/lib.rs", r#"
- extern crate foo;
-
- pub fn bar() {
- foo::foo();
- }
- "#)
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(101).with_stderr("\
-error: no matching package named `foo` found
-location searched: [..]
-required by package `bar v0.1.0 ([..])`
-"));
-}
-
-#[test]
-fn multiple() {
- setup();
-
- VendorPackage::new("foo-0.1.0")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
- "#)
- .file("src/lib.rs", "pub fn foo() {}")
- .file(".cargo-checksum", "")
- .build();
-
- VendorPackage::new("foo-0.2.0")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.2.0"
- authors = []
- "#)
- .file("src/lib.rs", "pub fn foo() {}")
- .file(".cargo-checksum", "")
- .build();
-
- let p = project("bar")
- .file("Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.1.0"
- authors = []
-
- [dependencies]
- foo = "0.1.0"
- "#)
- .file("src/lib.rs", r#"
- extern crate foo;
-
- pub fn bar() {
- foo::foo();
- }
- "#)
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr("\
-[COMPILING] foo v0.1.0
-[COMPILING] bar v0.1.0 ([..]bar)
-[FINISHED] [..]
-"));
-}
-
-#[test]
-fn crates_io_then_directory() {
- let p = project("bar")
- .file("Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.1.0"
- authors = []
-
- [dependencies]
- foo = "0.1.0"
- "#)
- .file("src/lib.rs", r#"
- extern crate foo;
-
- pub fn bar() {
- foo::foo();
- }
- "#)
- .build();
-
- let cksum = Package::new("foo", "0.1.0")
- .file("src/lib.rs", "pub fn foo() -> u32 { 0 }")
- .publish();
-
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr("\
-[UPDATING] registry `[..]`
-[DOWNLOADING] foo v0.1.0 ([..])
-[COMPILING] foo v0.1.0
-[COMPILING] bar v0.1.0 ([..]bar)
-[FINISHED] [..]
-"));
-
- setup();
-
- let mut v = VendorPackage::new("foo");
- v.file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
- "#);
- v.file("src/lib.rs", "pub fn foo() -> u32 { 1 }");
- v.cksum.package = Some(cksum);
- v.build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr("\
-[COMPILING] foo v0.1.0
-[COMPILING] bar v0.1.0 ([..]bar)
-[FINISHED] [..]
-"));
-}
-
-#[test]
-fn crates_io_then_bad_checksum() {
- let p = project("bar")
- .file("Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.1.0"
- authors = []
-
- [dependencies]
- foo = "0.1.0"
- "#)
- .file("src/lib.rs", "")
- .build();
-
- Package::new("foo", "0.1.0").publish();
-
- assert_that(p.cargo("build"),
- execs().with_status(0));
- setup();
-
- VendorPackage::new("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
- "#)
- .file("src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(101).with_stderr("\
-error: checksum for `foo 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 `foo v0.1.0` is the same as when the lockfile was generated
-
-"));
-}
-
-#[test]
-fn bad_file_checksum() {
- setup();
-
- VendorPackage::new("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
- "#)
- .file("src/lib.rs", "")
- .build();
-
- let mut f = t!(File::create(paths::root().join("index/foo/src/lib.rs")));
- t!(f.write_all(b"fn foo() -> u32 { 0 }"));
-
- let p = project("bar")
- .file("Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.1.0"
- authors = []
-
- [dependencies]
- foo = "0.1.0"
- "#)
- .file("src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build"),
- execs().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 [replace] is used with a forked copy of \
-the source
-"));
-}
-
-#[test]
-fn only_dot_files_ok() {
- setup();
-
- VendorPackage::new("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
- "#)
- .file("src/lib.rs", "")
- .build();
- VendorPackage::new("bar")
- .file(".foo", "")
- .build();
-
- let p = project("bar")
- .file("Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.1.0"
- authors = []
-
- [dependencies]
- foo = "0.1.0"
- "#)
- .file("src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build"), execs().with_status(0));
-}
-
-#[test]
-fn random_files_ok() {
- setup();
-
- VendorPackage::new("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
- "#)
- .file("src/lib.rs", "")
- .build();
- VendorPackage::new("bar")
- .file("foo", "")
- .file("../test", "")
- .build();
-
- let p = project("bar")
- .file("Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.1.0"
- authors = []
-
- [dependencies]
- foo = "0.1.0"
- "#)
- .file("src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build"), execs().with_status(0));
-}
-
-#[test]
-fn git_lock_file_doesnt_change() {
-
- let git = git::new("git", |p| {
- p.file("Cargo.toml", r#"
- [project]
- name = "git"
- version = "0.5.0"
- authors = []
- "#)
- .file("src/lib.rs", "")
- }).unwrap();
-
- VendorPackage::new("git")
- .file("Cargo.toml", r#"
- [package]
- name = "git"
- version = "0.5.0"
- authors = []
- "#)
- .file("src/lib.rs", "")
- .disable_checksum()
- .build();
-
- let p = project("bar")
- .file("Cargo.toml", &format!(r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- git = {{ git = '{0}' }}
- "#, git.url()))
- .file("src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build"), execs().with_status(0));
-
- let mut lock1 = String::new();
- t!(t!(File::open(p.root().join("Cargo.lock"))).read_to_string(&mut lock1));
-
- let root = paths::root();
- t!(fs::create_dir(&root.join(".cargo")));
- t!(t!(File::create(root.join(".cargo/config"))).write_all(&format!(r#"
- [source.my-git-repo]
- git = '{}'
- replace-with = 'my-awesome-local-registry'
-
- [source.my-awesome-local-registry]
- directory = 'index'
- "#, git.url()).as_bytes()));
-
- assert_that(p.cargo("build"),
- execs().with_status(0)
- .with_stderr("\
-[COMPILING] [..]
-[COMPILING] [..]
-[FINISHED] [..]
-"));
-
- let mut lock2 = String::new();
- t!(t!(File::open(p.root().join("Cargo.lock"))).read_to_string(&mut lock2));
- assert!(lock1 == lock2, "lock files changed");
-}
-
-#[test]
-fn git_override_requires_lockfile() {
- VendorPackage::new("git")
- .file("Cargo.toml", r#"
- [package]
- name = "git"
- version = "0.5.0"
- authors = []
- "#)
- .file("src/lib.rs", "")
- .disable_checksum()
- .build();
-
- let p = project("bar")
- .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!(t!(File::create(root.join(".cargo/config"))).write_all(br#"
- [source.my-git-repo]
- git = 'https://example.com/'
- replace-with = 'my-awesome-local-registry'
-
- [source.my-awesome-local-registry]
- directory = 'index'
- "#));
-
- assert_that(p.cargo("build"),
- execs().with_status(101)
- .with_stderr("\
-error: failed to load source for a dependency on `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
-
-"));
-}
+++ /dev/null
-extern crate cargotest;
-extern crate hamcrest;
-extern crate cargo;
-
-use std::str;
-use std::fs::{self, File};
-use std::io::Read;
-
-use cargotest::rustc_host;
-use cargotest::support::{project, execs, path2url};
-use cargotest::support::registry::Package;
-use hamcrest::{assert_that, existing_file, existing_dir, is_not};
-use cargo::util::ProcessError;
-
-#[test]
-fn simple() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- build = "build.rs"
- "#)
- .file("build.rs", "fn main() {}")
- .file("src/lib.rs", r#"
- pub fn foo() {}
- "#)
- .build();
-
- assert_that(p.cargo("doc"),
- execs().with_status(0).with_stderr(&format!("\
-[..] foo v0.0.1 ({dir})
-[..] foo v0.0.1 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-",
- dir = path2url(p.root()))));
- assert_that(&p.root().join("target/doc"), existing_dir());
- assert_that(&p.root().join("target/doc/foo/index.html"), existing_file());
-}
-
-#[test]
-fn doc_no_libs() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [[bin]]
- name = "foo"
- doc = false
- "#)
- .file("src/main.rs", r#"
- bad code
- "#)
- .build();
-
- assert_that(p.cargo("doc"),
- execs().with_status(0));
-}
-
-#[test]
-fn doc_twice() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/lib.rs", r#"
- pub fn foo() {}
- "#)
- .build();
-
- assert_that(p.cargo("doc"),
- execs().with_status(0).with_stderr(&format!("\
-[DOCUMENTING] foo v0.0.1 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-",
- dir = path2url(p.root()))));
-
- assert_that(p.cargo("doc"),
- execs().with_status(0).with_stdout(""))
-}
-
-#[test]
-fn doc_deps() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies.bar]
- path = "bar"
- "#)
- .file("src/lib.rs", r#"
- extern crate bar;
- pub fn foo() {}
- "#)
- .file("bar/Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
- "#)
- .file("bar/src/lib.rs", r#"
- pub fn bar() {}
- "#)
- .build();
-
- assert_that(p.cargo("doc"),
- execs().with_status(0).with_stderr(&format!("\
-[..] bar v0.0.1 ({dir}/bar)
-[..] bar v0.0.1 ({dir}/bar)
-[DOCUMENTING] foo v0.0.1 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-",
- dir = path2url(p.root()))));
-
- assert_that(&p.root().join("target/doc"), existing_dir());
- assert_that(&p.root().join("target/doc/foo/index.html"), existing_file());
- assert_that(&p.root().join("target/doc/bar/index.html"), existing_file());
-
- assert_that(p.cargo("doc")
- .env("RUST_LOG", "cargo::ops::cargo_rustc::fingerprint"),
- execs().with_status(0).with_stdout(""));
-
- assert_that(&p.root().join("target/doc"), existing_dir());
- assert_that(&p.root().join("target/doc/foo/index.html"), existing_file());
- assert_that(&p.root().join("target/doc/bar/index.html"), existing_file());
-}
-
-#[test]
-fn doc_no_deps() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies.bar]
- path = "bar"
- "#)
- .file("src/lib.rs", r#"
- extern crate bar;
- pub fn foo() {}
- "#)
- .file("bar/Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
- "#)
- .file("bar/src/lib.rs", r#"
- pub fn bar() {}
- "#)
- .build();
-
- assert_that(p.cargo("doc").arg("--no-deps"),
- execs().with_status(0).with_stderr(&format!("\
-[COMPILING] bar v0.0.1 ({dir}/bar)
-[DOCUMENTING] foo v0.0.1 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-",
- dir = path2url(p.root()))));
-
- assert_that(&p.root().join("target/doc"), existing_dir());
- assert_that(&p.root().join("target/doc/foo/index.html"), existing_file());
- assert_that(&p.root().join("target/doc/bar/index.html"), is_not(existing_file()));
-}
-
-#[test]
-fn doc_only_bin() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies.bar]
- path = "bar"
- "#)
- .file("src/main.rs", r#"
- extern crate bar;
- pub fn foo() {}
- "#)
- .file("bar/Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
- "#)
- .file("bar/src/lib.rs", r#"
- pub fn bar() {}
- "#)
- .build();
-
- assert_that(p.cargo("doc").arg("-v"),
- execs().with_status(0));
-
- assert_that(&p.root().join("target/doc"), existing_dir());
- assert_that(&p.root().join("target/doc/bar/index.html"), existing_file());
- assert_that(&p.root().join("target/doc/foo/index.html"), existing_file());
-}
-
-#[test]
-fn doc_multiple_targets_same_name_lib() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [workspace]
- members = ["foo", "bar"]
- "#)
- .file("foo/Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- [lib]
- name = "foo_lib"
- "#)
- .file("foo/src/lib.rs", "")
- .file("bar/Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.1.0"
- [lib]
- name = "foo_lib"
- "#)
- .file("bar/src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("doc").arg("--all"),
- execs()
- .with_status(101)
- .with_stderr_contains("[..] library `foo_lib` is specified [..]")
- .with_stderr_contains("[..] `foo v0.1.0[..]` [..]")
- .with_stderr_contains("[..] `bar v0.1.0[..]` [..]"));
-}
-
-#[test]
-fn doc_multiple_targets_same_name() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [workspace]
- members = ["foo", "bar"]
- "#)
- .file("foo/Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- [[bin]]
- name = "foo_lib"
- path = "src/foo_lib.rs"
- "#)
- .file("foo/src/foo_lib.rs", "")
- .file("bar/Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.1.0"
- [lib]
- name = "foo_lib"
- "#)
- .file("bar/src/lib.rs", "")
- .build();
-
- let root = path2url(p.root());
-
- assert_that(p.cargo("doc").arg("--all"),
- execs()
- .with_status(0)
- .with_stderr_contains(&format!("[DOCUMENTING] foo v0.1.0 ({}/foo)", root))
- .with_stderr_contains(&format!("[DOCUMENTING] bar v0.1.0 ({}/bar)", root))
- .with_stderr_contains("[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]"));
- assert_that(&p.root().join("target/doc"), existing_dir());
- let doc_file = p.root().join("target/doc/foo_lib/index.html");
- assert_that(&doc_file, existing_file());
-}
-
-#[test]
-fn doc_multiple_targets_same_name_bin() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [workspace]
- members = ["foo", "bar"]
- "#)
- .file("foo/Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- [[bin]]
- name = "foo-cli"
- "#)
- .file("foo/src/foo-cli.rs", "")
- .file("bar/Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.1.0"
- [[bin]]
- name = "foo-cli"
- "#)
- .file("bar/src/foo-cli.rs", "")
- .build();
-
- assert_that(p.cargo("doc").arg("--all"),
- execs()
- .with_status(101)
- .with_stderr_contains("[..] binary `foo_cli` is specified [..]")
- .with_stderr_contains("[..] `foo v0.1.0[..]` [..]")
- .with_stderr_contains("[..] `bar v0.1.0[..]` [..]"));
-}
-
-#[test]
-fn doc_multiple_targets_same_name_undoced() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [workspace]
- members = ["foo", "bar"]
- "#)
- .file("foo/Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- [[bin]]
- name = "foo-cli"
- "#)
- .file("foo/src/foo-cli.rs", "")
- .file("bar/Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.1.0"
- [[bin]]
- name = "foo-cli"
- doc = false
- "#)
- .file("bar/src/foo-cli.rs", "")
- .build();
-
- assert_that(p.cargo("doc").arg("--all"),
- execs().with_status(0));
-}
-
-#[test]
-fn doc_lib_bin_same_name_documents_lib() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/main.rs", r#"
- //! Binary documentation
- extern crate foo;
- fn main() {
- foo::foo();
- }
- "#)
- .file("src/lib.rs", r#"
- //! Library documentation
- pub fn foo() {}
- "#)
- .build();
-
- assert_that(p.cargo("doc"),
- execs().with_status(0).with_stderr(&format!("\
-[DOCUMENTING] foo v0.0.1 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-", dir = path2url(p.root()))));
- assert_that(&p.root().join("target/doc"), existing_dir());
- let doc_file = p.root().join("target/doc/foo/index.html");
- assert_that(&doc_file, existing_file());
- let mut doc_html = String::new();
- File::open(&doc_file).unwrap().read_to_string(&mut doc_html).unwrap();
- assert!(doc_html.contains("Library"));
- assert!(!doc_html.contains("Binary"));
-}
-
-#[test]
-fn doc_lib_bin_same_name_documents_lib_when_requested() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/main.rs", r#"
- //! Binary documentation
- extern crate foo;
- fn main() {
- foo::foo();
- }
- "#)
- .file("src/lib.rs", r#"
- //! Library documentation
- pub fn foo() {}
- "#)
- .build();
-
- assert_that(p.cargo("doc").arg("--lib"),
- execs().with_status(0).with_stderr(&format!("\
-[DOCUMENTING] foo v0.0.1 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-", dir = path2url(p.root()))));
- assert_that(&p.root().join("target/doc"), existing_dir());
- let doc_file = p.root().join("target/doc/foo/index.html");
- assert_that(&doc_file, existing_file());
- let mut doc_html = String::new();
- File::open(&doc_file).unwrap().read_to_string(&mut doc_html).unwrap();
- assert!(doc_html.contains("Library"));
- assert!(!doc_html.contains("Binary"));
-}
-
-#[test]
-fn doc_lib_bin_same_name_documents_named_bin_when_requested() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/main.rs", r#"
- //! Binary documentation
- extern crate foo;
- fn main() {
- foo::foo();
- }
- "#)
- .file("src/lib.rs", r#"
- //! Library documentation
- pub fn foo() {}
- "#)
- .build();
-
- assert_that(p.cargo("doc").arg("--bin").arg("foo"),
- execs().with_status(0).with_stderr(&format!("\
-[COMPILING] foo v0.0.1 ({dir})
-[DOCUMENTING] foo v0.0.1 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-", dir = path2url(p.root()))));
- assert_that(&p.root().join("target/doc"), existing_dir());
- let doc_file = p.root().join("target/doc/foo/index.html");
- assert_that(&doc_file, existing_file());
- let mut doc_html = String::new();
- File::open(&doc_file).unwrap().read_to_string(&mut doc_html).unwrap();
- assert!(!doc_html.contains("Library"));
- assert!(doc_html.contains("Binary"));
-}
-
-#[test]
-fn doc_lib_bin_same_name_documents_bins_when_requested() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/main.rs", r#"
- //! Binary documentation
- extern crate foo;
- fn main() {
- foo::foo();
- }
- "#)
- .file("src/lib.rs", r#"
- //! Library documentation
- pub fn foo() {}
- "#)
- .build();
-
- assert_that(p.cargo("doc").arg("--bins"),
- execs().with_status(0).with_stderr(&format!("\
-[COMPILING] foo v0.0.1 ({dir})
-[DOCUMENTING] foo v0.0.1 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-", dir = path2url(p.root()))));
- assert_that(&p.root().join("target/doc"), existing_dir());
- let doc_file = p.root().join("target/doc/foo/index.html");
- assert_that(&doc_file, existing_file());
- let mut doc_html = String::new();
- File::open(&doc_file).unwrap().read_to_string(&mut doc_html).unwrap();
- assert!(!doc_html.contains("Library"));
- assert!(doc_html.contains("Binary"));
-}
-
-#[test]
-fn doc_dash_p() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies.a]
- path = "a"
- "#)
- .file("src/lib.rs", "extern crate a;")
- .file("a/Cargo.toml", r#"
- [package]
- name = "a"
- version = "0.0.1"
- authors = []
-
- [dependencies.b]
- path = "../b"
- "#)
- .file("a/src/lib.rs", "extern crate b;")
- .file("b/Cargo.toml", r#"
- [package]
- name = "b"
- version = "0.0.1"
- authors = []
- "#)
- .file("b/src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("doc").arg("-p").arg("a"),
- execs().with_status(0)
- .with_stderr("\
-[..] b v0.0.1 (file://[..])
-[..] b v0.0.1 (file://[..])
-[DOCUMENTING] a v0.0.1 (file://[..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-}
-
-#[test]
-fn doc_same_name() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/lib.rs", "")
- .file("src/bin/main.rs", "fn main() {}")
- .file("examples/main.rs", "fn main() {}")
- .file("tests/main.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("doc"),
- execs().with_status(0));
-}
-
-#[test]
-fn doc_target() {
- const TARGET: &'static str = "arm-unknown-linux-gnueabihf";
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/lib.rs", r#"
- #![feature(no_core)]
- #![no_core]
-
- extern {
- pub static A: u32;
- }
- "#)
- .build();
-
- assert_that(p.cargo("doc").arg("--target").arg(TARGET).arg("--verbose"),
- execs().with_status(0));
- assert_that(&p.root().join(&format!("target/{}/doc", TARGET)), existing_dir());
- assert_that(&p.root().join(&format!("target/{}/doc/foo/index.html", TARGET)), existing_file());
-}
-
-#[test]
-fn target_specific_not_documented() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [target.foo.dependencies]
- a = { path = "a" }
- "#)
- .file("src/lib.rs", "")
- .file("a/Cargo.toml", r#"
- [package]
- name = "a"
- version = "0.0.1"
- authors = []
- "#)
- .file("a/src/lib.rs", "not rust")
- .build();
-
- assert_that(p.cargo("doc"),
- execs().with_status(0));
-}
-
-#[test]
-fn output_not_captured() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- a = { path = "a" }
- "#)
- .file("src/lib.rs", "")
- .file("a/Cargo.toml", r#"
- [package]
- name = "a"
- version = "0.0.1"
- authors = []
- "#)
- .file("a/src/lib.rs", "
- /// ```
- /// ☃
- /// ```
- pub fn foo() {}
- ")
- .build();
-
- let error = p.cargo("doc").exec_with_output().err().unwrap();
- if let Ok(perr) = error.downcast::<ProcessError>() {
- let output = perr.output.unwrap();
- let stderr = str::from_utf8(&output.stderr).unwrap();
-
- assert!(stderr.contains("☃"), "no snowman\n{}", stderr);
- assert!(stderr.contains("unknown start of token"), "no message{}", stderr);
- } else {
- assert!(false, "an error kind other than ProcessErrorKind was encountered");
- }
-}
-
-#[test]
-fn target_specific_documented() {
- let p = project("foo")
- .file("Cargo.toml", &format!(r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [target.foo.dependencies]
- a = {{ path = "a" }}
- [target.{}.dependencies]
- a = {{ path = "a" }}
- "#, rustc_host()))
- .file("src/lib.rs", "
- extern crate a;
-
- /// test
- pub fn foo() {}
- ")
- .file("a/Cargo.toml", r#"
- [package]
- name = "a"
- version = "0.0.1"
- authors = []
- "#)
- .file("a/src/lib.rs", "
- /// test
- pub fn foo() {}
- ")
- .build();
-
- assert_that(p.cargo("doc"),
- execs().with_status(0));
-}
-
-#[test]
-fn no_document_build_deps() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [build-dependencies]
- a = { path = "a" }
- "#)
- .file("src/lib.rs", "
- pub fn foo() {}
- ")
- .file("a/Cargo.toml", r#"
- [package]
- name = "a"
- version = "0.0.1"
- authors = []
- "#)
- .file("a/src/lib.rs", "
- /// ```
- /// ☃
- /// ```
- pub fn foo() {}
- ")
- .build();
-
- assert_that(p.cargo("doc"),
- execs().with_status(0));
-}
-
-#[test]
-fn doc_release() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build").arg("--release"),
- execs().with_status(0));
- assert_that(p.cargo("doc").arg("--release").arg("-v"),
- execs().with_status(0)
- .with_stderr("\
-[DOCUMENTING] foo v0.0.1 ([..])
-[RUNNING] `rustdoc [..] src[/]lib.rs [..]`
-[FINISHED] release [optimized] target(s) in [..]
-"));
-}
-
-#[test]
-fn doc_multiple_deps() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies.bar]
- path = "bar"
-
- [dependencies.baz]
- path = "baz"
- "#)
- .file("src/lib.rs", r#"
- extern crate bar;
- pub fn foo() {}
- "#)
- .file("bar/Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
- "#)
- .file("bar/src/lib.rs", r#"
- pub fn bar() {}
- "#)
- .file("baz/Cargo.toml", r#"
- [package]
- name = "baz"
- version = "0.0.1"
- authors = []
- "#)
- .file("baz/src/lib.rs", r#"
- pub fn baz() {}
- "#)
- .build();
-
- assert_that(p.cargo("doc")
- .arg("-p").arg("bar")
- .arg("-p").arg("baz")
- .arg("-v"),
- execs().with_status(0));
-
- assert_that(&p.root().join("target/doc"), existing_dir());
- assert_that(&p.root().join("target/doc/bar/index.html"), existing_file());
- assert_that(&p.root().join("target/doc/baz/index.html"), existing_file());
-}
-
-#[test]
-fn features() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies.bar]
- path = "bar"
-
- [features]
- foo = ["bar/bar"]
- "#)
- .file("src/lib.rs", r#"
- #[cfg(feature = "foo")]
- pub fn foo() {}
- "#)
- .file("bar/Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
-
- [features]
- bar = []
- "#)
- .file("bar/build.rs", r#"
- fn main() {
- println!("cargo:rustc-cfg=bar");
- }
- "#)
- .file("bar/src/lib.rs", r#"
- #[cfg(feature = "bar")]
- pub fn bar() {}
- "#)
- .build();
- assert_that(p.cargo("doc").arg("--features").arg("foo"),
- execs().with_status(0));
- assert_that(&p.root().join("target/doc"), existing_dir());
- assert_that(&p.root().join("target/doc/foo/fn.foo.html"), existing_file());
- assert_that(&p.root().join("target/doc/bar/fn.bar.html"), existing_file());
-}
-
-#[test]
-fn rerun_when_dir_removed() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/lib.rs", r#"
- /// dox
- pub fn foo() {}
- "#)
- .build();
-
- assert_that(p.cargo("doc"),
- execs().with_status(0));
- assert_that(&p.root().join("target/doc/foo/index.html"), existing_file());
-
- fs::remove_dir_all(p.root().join("target/doc/foo")).unwrap();
-
- assert_that(p.cargo("doc"),
- execs().with_status(0));
- assert_that(&p.root().join("target/doc/foo/index.html"), existing_file());
-}
-
-#[test]
-fn document_only_lib() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/lib.rs", r#"
- /// dox
- pub fn foo() {}
- "#)
- .file("src/bin/bar.rs", r#"
- /// ```
- /// ☃
- /// ```
- pub fn foo() {}
- fn main() { foo(); }
- "#)
- .build();
- assert_that(p.cargo("doc").arg("--lib"),
- execs().with_status(0));
- assert_that(&p.root().join("target/doc/foo/index.html"), existing_file());
-}
-
-#[test]
-fn plugins_no_use_target() {
- if !cargotest::is_nightly() {
- return
- }
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [lib]
- proc-macro = true
- "#)
- .file("src/lib.rs", "")
- .build();
- assert_that(p.cargo("doc")
- .arg("--target=x86_64-unknown-openbsd")
- .arg("-v"),
- execs().with_status(0));
-}
-
-#[test]
-fn doc_all_workspace() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.1.0"
-
- [dependencies]
- bar = { path = "bar" }
-
- [workspace]
- "#)
- .file("src/main.rs", r#"
- fn main() {}
- "#)
- .file("bar/Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.1.0"
- "#)
- .file("bar/src/lib.rs", r#"
- pub fn bar() {}
- "#)
- .build();
-
- // The order in which bar is compiled or documented is not deterministic
- assert_that(p.cargo("doc")
- .arg("--all"),
- execs().with_status(0)
- .with_stderr_contains("[..] Documenting bar v0.1.0 ([..])")
- .with_stderr_contains("[..] Compiling bar v0.1.0 ([..])")
- .with_stderr_contains("[..] Documenting foo v0.1.0 ([..])"));
-}
-
-#[test]
-fn doc_all_virtual_manifest() {
- let p = project("workspace")
- .file("Cargo.toml", r#"
- [workspace]
- members = ["foo", "bar"]
- "#)
- .file("foo/Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.1.0"
- "#)
- .file("foo/src/lib.rs", r#"
- pub fn foo() {}
- "#)
- .file("bar/Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.1.0"
- "#)
- .file("bar/src/lib.rs", r#"
- pub fn bar() {}
- "#)
- .build();
-
- // The order in which foo and bar are documented is not guaranteed
- assert_that(p.cargo("doc")
- .arg("--all"),
- execs().with_status(0)
- .with_stderr_contains("[..] Documenting bar v0.1.0 ([..])")
- .with_stderr_contains("[..] Documenting foo v0.1.0 ([..])"));
-}
-
-#[test]
-fn doc_virtual_manifest_all_implied() {
- let p = project("workspace")
- .file("Cargo.toml", r#"
- [workspace]
- members = ["foo", "bar"]
- "#)
- .file("foo/Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.1.0"
- "#)
- .file("foo/src/lib.rs", r#"
- pub fn foo() {}
- "#)
- .file("bar/Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.1.0"
- "#)
- .file("bar/src/lib.rs", r#"
- pub fn bar() {}
- "#)
- .build();
-
- // The order in which foo and bar are documented is not guaranteed
- assert_that(p.cargo("doc"),
- execs().with_status(0)
- .with_stderr_contains("[..] Documenting bar v0.1.0 ([..])")
- .with_stderr_contains("[..] Documenting foo v0.1.0 ([..])"));
-}
-
-#[test]
-fn doc_all_member_dependency_same_name() {
- let p = project("workspace")
- .file("Cargo.toml", r#"
- [workspace]
- members = ["a"]
- "#)
- .file("a/Cargo.toml", r#"
- [project]
- name = "a"
- version = "0.1.0"
-
- [dependencies]
- a = "0.1.0"
- "#)
- .file("a/src/lib.rs", r#"
- pub fn a() {}
- "#)
- .build();
-
- Package::new("a", "0.1.0").publish();
-
- assert_that(p.cargo("doc")
- .arg("--all"),
- execs().with_status(0)
- .with_stderr_contains("[..] Updating registry `[..]`")
- .with_stderr_contains("[..] Documenting a v0.1.0 ([..])"));
-}
-
-#[test]
-fn doc_workspace_open_help_message() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [workspace]
- members = ["foo", "bar"]
- "#)
- .file("foo/Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- "#)
- .file("foo/src/lib.rs", "")
- .file("bar/Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.1.0"
- "#)
- .file("bar/src/lib.rs", "")
- .build();
-
- // The order in which bar is compiled or documented is not deterministic
- assert_that(p.cargo("doc")
- .arg("--all")
- .arg("--open"),
- execs().with_status(101)
- .with_stderr_contains("[..] Documenting bar v0.1.0 ([..])")
- .with_stderr_contains("[..] Documenting foo v0.1.0 ([..])")
- .with_stderr_contains("error: Passing multiple packages and `open` is not supported.")
- .with_stderr_contains("Please re-run this command with `-p <spec>` where `<spec>` is one of the following:")
- .with_stderr_contains(" foo")
- .with_stderr_contains(" bar"));
-}
+++ /dev/null
-#[macro_use]
-extern crate cargotest;
-extern crate hamcrest;
-
-use std::fs::File;
-use std::io::prelude::*;
-
-use cargotest::support::paths::CargoPathExt;
-use cargotest::support::{project, execs};
-use hamcrest::assert_that;
-
-#[test]
-fn invalid1() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [features]
- bar = ["baz"]
- "#)
- .file("src/main.rs", "")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(101).with_stderr("\
-[ERROR] failed to parse manifest at `[..]`
-
-Caused by:
- Feature `bar` includes `baz` which is neither a dependency nor another feature
-"));
-}
-
-#[test]
-fn invalid2() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [features]
- bar = ["baz"]
-
- [dependencies.bar]
- path = "foo"
- "#)
- .file("src/main.rs", "")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(101).with_stderr("\
-[ERROR] failed to parse manifest at `[..]`
-
-Caused by:
- Features and dependencies cannot have the same name: `bar`
-"));
-}
-
-#[test]
-fn invalid3() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [features]
- bar = ["baz"]
-
- [dependencies.baz]
- path = "foo"
- "#)
- .file("src/main.rs", "")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(101).with_stderr("\
-[ERROR] failed to parse manifest at `[..]`
-
-Caused by:
- Feature `bar` depends on `baz` which is not an optional dependency.
-Consider adding `optional = true` to the dependency
-"));
-}
-
-#[test]
-fn invalid4() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies.bar]
- path = "bar"
- features = ["bar"]
- "#)
- .file("src/main.rs", "")
- .file("bar/Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.0.1"
- authors = []
- "#)
- .file("bar/src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(101).with_stderr("\
-[ERROR] Package `bar v0.0.1 ([..])` does not have these features: `bar`
-"));
-
- p.change_file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#);
-
- assert_that(p.cargo("build").arg("--features").arg("test"),
- execs().with_status(101).with_stderr("\
-[ERROR] Package `foo v0.0.1 ([..])` does not have these features: `test`
-"));
-}
-
-#[test]
-fn invalid5() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dev-dependencies.bar]
- path = "bar"
- optional = true
- "#)
- .file("src/main.rs", "")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(101).with_stderr("\
-[ERROR] failed to parse manifest at `[..]`
-
-Caused by:
- Dev-dependencies are not allowed to be optional: `bar`
-"));
-}
-
-#[test]
-fn invalid6() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [features]
- foo = ["bar/baz"]
- "#)
- .file("src/main.rs", "")
- .build();
-
- assert_that(p.cargo("build").arg("--features").arg("foo"),
- execs().with_status(101).with_stderr("\
-[ERROR] failed to parse manifest at `[..]`
-
-Caused by:
- Feature `foo` requires a feature of `bar` which is not a dependency
-"));
-}
-
-#[test]
-fn invalid7() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [features]
- foo = ["bar/baz"]
- bar = []
- "#)
- .file("src/main.rs", "")
- .build();
-
- assert_that(p.cargo("build").arg("--features").arg("foo"),
- execs().with_status(101).with_stderr("\
-[ERROR] failed to parse manifest at `[..]`
-
-Caused by:
- Feature `foo` requires a feature of `bar` which is not a dependency
-"));
-}
-
-#[test]
-fn invalid8() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies.bar]
- path = "bar"
- features = ["foo/bar"]
- "#)
- .file("src/main.rs", "")
- .file("bar/Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
- "#)
- .file("bar/src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build").arg("--features").arg("foo"),
- execs().with_status(101).with_stderr("\
-[ERROR] feature names may not contain slashes: `foo/bar`
-"));
-}
-
-#[test]
-fn invalid9() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies.bar]
- path = "bar"
- "#)
- .file("src/main.rs", "fn main() {}")
- .file("bar/Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
- "#)
- .file("bar/src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build").arg("--features").arg("bar"),
- execs().with_status(0).with_stderr("\
-warning: Package `foo v0.0.1 ([..])` does not have feature `bar`. It has a required dependency with \
-that name, but only optional dependencies can be used as features. [..]
- Compiling bar v0.0.1 ([..])
- Compiling foo v0.0.1 ([..])
- Finished dev [unoptimized + debuginfo] target(s) in [..] secs
-"));
-}
-
-#[test]
-fn invalid10() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies.bar]
- path = "bar"
- features = ["baz"]
- "#)
- .file("src/main.rs", "fn main() {}")
- .file("bar/Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
-
- [dependencies.baz]
- path = "baz"
- "#)
- .file("bar/src/lib.rs", "")
- .file("bar/baz/Cargo.toml", r#"
- [package]
- name = "baz"
- version = "0.0.1"
- authors = []
- "#)
- .file("bar/baz/src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr("\
-warning: Package `bar v0.0.1 ([..])` does not have feature `baz`. It has a required dependency with \
-that name, but only optional dependencies can be used as features. [..]
- Compiling baz v0.0.1 ([..])
- Compiling bar v0.0.1 ([..])
- Compiling foo v0.0.1 ([..])
- Finished dev [unoptimized + debuginfo] target(s) in [..] secs
-"));
-}
-
-#[test]
-fn no_transitive_dep_feature_requirement() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies.derived]
- path = "derived"
-
- [features]
- default = ["derived/bar/qux"]
- "#)
- .file("src/main.rs", r#"
- extern crate derived;
- fn main() { derived::test(); }
- "#)
- .file("derived/Cargo.toml", r#"
- [package]
- name = "derived"
- version = "0.0.1"
- authors = []
-
- [dependencies.bar]
- path = "../bar"
- "#)
- .file("derived/src/lib.rs", r#"
- extern crate bar;
- pub use bar::test;
- "#)
- .file("bar/Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
-
- [features]
- qux = []
- "#)
- .file("bar/src/lib.rs", r#"
- #[cfg(feature = "qux")]
- pub fn test() { print!("test"); }
- "#)
- .build();
- assert_that(p.cargo("build"),
- execs().with_status(101).with_stderr("\
-[ERROR] feature names may not contain slashes: `bar/qux`
-"));
-}
-
-#[test]
-fn no_feature_doesnt_build() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies.bar]
- path = "bar"
- optional = true
- "#)
- .file("src/main.rs", r#"
- #[cfg(feature = "bar")]
- extern crate bar;
- #[cfg(feature = "bar")]
- fn main() { bar::bar(); println!("bar") }
- #[cfg(not(feature = "bar"))]
- fn main() {}
- "#)
- .file("bar/Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
- "#)
- .file("bar/src/lib.rs", "pub fn bar() {}")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr(format!("\
-[COMPILING] foo v0.0.1 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-", dir = p.url())));
- assert_that(p.process(&p.bin("foo")),
- execs().with_status(0).with_stdout(""));
-
- assert_that(p.cargo("build").arg("--features").arg("bar"),
- execs().with_status(0).with_stderr(format!("\
-[COMPILING] bar v0.0.1 ({dir}/bar)
-[COMPILING] foo v0.0.1 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-", dir = p.url())));
- assert_that(p.process(&p.bin("foo")),
- execs().with_status(0).with_stdout("bar\n"));
-}
-
-#[test]
-fn default_feature_pulled_in() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [features]
- default = ["bar"]
-
- [dependencies.bar]
- path = "bar"
- optional = true
- "#)
- .file("src/main.rs", r#"
- #[cfg(feature = "bar")]
- extern crate bar;
- #[cfg(feature = "bar")]
- fn main() { bar::bar(); println!("bar") }
- #[cfg(not(feature = "bar"))]
- fn main() {}
- "#)
- .file("bar/Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
- "#)
- .file("bar/src/lib.rs", "pub fn bar() {}")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr(format!("\
-[COMPILING] bar v0.0.1 ({dir}/bar)
-[COMPILING] foo v0.0.1 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-", dir = p.url())));
- assert_that(p.process(&p.bin("foo")),
- execs().with_status(0).with_stdout("bar\n"));
-
- assert_that(p.cargo("build").arg("--no-default-features"),
- execs().with_status(0).with_stderr(format!("\
-[COMPILING] foo v0.0.1 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-", dir = p.url())));
- assert_that(p.process(&p.bin("foo")),
- execs().with_status(0).with_stdout(""));
-}
-
-#[test]
-fn cyclic_feature() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [features]
- default = ["default"]
- "#)
- .file("src/main.rs", "")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(101).with_stderr("\
-[ERROR] Cyclic feature dependency: feature `default` depends on itself
-"));
-}
-
-#[test]
-fn cyclic_feature2() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [features]
- foo = ["bar"]
- bar = ["foo"]
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stdout(""));
-}
-
-#[test]
-fn groups_on_groups_on_groups() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [features]
- default = ["f1"]
- f1 = ["f2", "bar"]
- f2 = ["f3", "f4"]
- f3 = ["f5", "f6", "baz"]
- f4 = ["f5", "f7"]
- f5 = ["f6"]
- f6 = ["f7"]
- f7 = ["bar"]
-
- [dependencies.bar]
- path = "bar"
- optional = true
-
- [dependencies.baz]
- path = "baz"
- optional = true
- "#)
- .file("src/main.rs", r#"
- #[allow(unused_extern_crates)]
- extern crate bar;
- #[allow(unused_extern_crates)]
- extern crate baz;
- fn main() {}
- "#)
- .file("bar/Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
- "#)
- .file("bar/src/lib.rs", "pub fn bar() {}")
- .file("baz/Cargo.toml", r#"
- [package]
- name = "baz"
- version = "0.0.1"
- authors = []
- "#)
- .file("baz/src/lib.rs", "pub fn baz() {}")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr(format!("\
-[COMPILING] ba[..] v0.0.1 ({dir}/ba[..])
-[COMPILING] ba[..] v0.0.1 ({dir}/ba[..])
-[COMPILING] foo v0.0.1 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-", dir = p.url())));
-}
-
-#[test]
-fn many_cli_features() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies.bar]
- path = "bar"
- optional = true
-
- [dependencies.baz]
- path = "baz"
- optional = true
- "#)
- .file("src/main.rs", r#"
- #[allow(unused_extern_crates)]
- extern crate bar;
- #[allow(unused_extern_crates)]
- extern crate baz;
- fn main() {}
- "#)
- .file("bar/Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
- "#)
- .file("bar/src/lib.rs", "pub fn bar() {}")
- .file("baz/Cargo.toml", r#"
- [package]
- name = "baz"
- version = "0.0.1"
- authors = []
- "#)
- .file("baz/src/lib.rs", "pub fn baz() {}")
- .build();
-
- assert_that(p.cargo("build").arg("--features").arg("bar baz"),
- execs().with_status(0).with_stderr(format!("\
-[COMPILING] ba[..] v0.0.1 ({dir}/ba[..])
-[COMPILING] ba[..] v0.0.1 ({dir}/ba[..])
-[COMPILING] foo v0.0.1 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-", dir = p.url())));
-}
-
-#[test]
-fn union_features() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies.d1]
- path = "d1"
- features = ["f1"]
- [dependencies.d2]
- path = "d2"
- features = ["f2"]
- "#)
- .file("src/main.rs", r#"
- #[allow(unused_extern_crates)]
- extern crate d1;
- extern crate d2;
- fn main() {
- d2::f1();
- d2::f2();
- }
- "#)
- .file("d1/Cargo.toml", r#"
- [package]
- name = "d1"
- version = "0.0.1"
- authors = []
-
- [features]
- f1 = ["d2"]
-
- [dependencies.d2]
- path = "../d2"
- features = ["f1"]
- optional = true
- "#)
- .file("d1/src/lib.rs", "")
- .file("d2/Cargo.toml", r#"
- [package]
- name = "d2"
- version = "0.0.1"
- authors = []
-
- [features]
- f1 = []
- f2 = []
- "#)
- .file("d2/src/lib.rs", r#"
- #[cfg(feature = "f1")] pub fn f1() {}
- #[cfg(feature = "f2")] pub fn f2() {}
- "#)
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr(format!("\
-[COMPILING] d2 v0.0.1 ({dir}/d2)
-[COMPILING] d1 v0.0.1 ({dir}/d1)
-[COMPILING] foo v0.0.1 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-", dir = p.url())));
-}
-
-#[test]
-fn many_features_no_rebuilds() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "b"
- version = "0.1.0"
- authors = []
-
- [dependencies.a]
- path = "a"
- features = ["fall"]
- "#)
- .file("src/main.rs", "fn main() {}")
- .file("a/Cargo.toml", r#"
- [package]
- name = "a"
- version = "0.1.0"
- authors = []
-
- [features]
- ftest = []
- ftest2 = []
- fall = ["ftest", "ftest2"]
- "#)
- .file("a/src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr(format!("\
-[COMPILING] a v0.1.0 ({dir}/a)
-[COMPILING] b v0.1.0 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-", dir = p.url())));
- p.root().move_into_the_past();
-
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(0).with_stderr("\
-[FRESH] a v0.1.0 ([..]/a)
-[FRESH] b v0.1.0 ([..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-}
-
-// Tests that all cmd lines work with `--features ""`
-#[test]
-fn empty_features() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("build").arg("--features").arg(""),
- execs().with_status(0));
-}
-
-// Tests that all cmd lines work with `--features ""`
-#[test]
-fn transitive_features() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [features]
- foo = ["bar/baz"]
-
- [dependencies.bar]
- path = "bar"
- "#)
- .file("src/main.rs", "
- extern crate bar;
- fn main() { bar::baz(); }
- ")
- .file("bar/Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
-
- [features]
- baz = []
- "#)
- .file("bar/src/lib.rs", r#"
- #[cfg(feature = "baz")]
- pub fn baz() {}
- "#)
- .build();
-
- assert_that(p.cargo("build").arg("--features").arg("foo"),
- execs().with_status(0));
-}
-
-#[test]
-fn everything_in_the_lockfile() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [features]
- f1 = ["d1/f1"]
- f2 = ["d2"]
-
- [dependencies.d1]
- path = "d1"
- [dependencies.d2]
- path = "d2"
- optional = true
- [dependencies.d3]
- path = "d3"
- optional = true
- "#)
- .file("src/main.rs", "fn main() {}")
- .file("d1/Cargo.toml", r#"
- [package]
- name = "d1"
- version = "0.0.1"
- authors = []
-
- [features]
- f1 = []
- "#)
- .file("d1/src/lib.rs", "")
- .file("d2/Cargo.toml", r#"
- [package]
- name = "d2"
- version = "0.0.2"
- authors = []
- "#)
- .file("d2/src/lib.rs", "")
- .file("d3/Cargo.toml", r#"
- [package]
- name = "d3"
- version = "0.0.3"
- authors = []
-
- [features]
- f3 = []
- "#)
- .file("d3/src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("fetch"), execs().with_status(0));
- let loc = p.root().join("Cargo.lock");
- let mut lockfile = String::new();
- t!(t!(File::open(&loc)).read_to_string(&mut lockfile));
- assert!(lockfile.contains(r#"name = "d1""#), "d1 not found\n{}", lockfile);
- assert!(lockfile.contains(r#"name = "d2""#), "d2 not found\n{}", lockfile);
- assert!(lockfile.contains(r#"name = "d3""#), "d3 not found\n{}", lockfile);
-}
-
-#[test]
-fn no_rebuild_when_frobbing_default_feature() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
-
- [dependencies]
- a = { path = "a" }
- b = { path = "b" }
- "#)
- .file("src/lib.rs", "")
- .file("b/Cargo.toml", r#"
- [package]
- name = "b"
- version = "0.1.0"
- authors = []
-
- [dependencies]
- a = { path = "../a", features = ["f1"], default-features = false }
- "#)
- .file("b/src/lib.rs", "")
- .file("a/Cargo.toml", r#"
- [package]
- name = "a"
- version = "0.1.0"
- authors = []
-
- [features]
- default = ["f1"]
- f1 = []
- "#)
- .file("a/src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build"), execs().with_status(0));
- assert_that(p.cargo("build"), execs().with_status(0).with_stdout(""));
- assert_that(p.cargo("build"), execs().with_status(0).with_stdout(""));
-}
-
-#[test]
-fn unions_work_with_no_default_features() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
-
- [dependencies]
- a = { path = "a" }
- b = { path = "b" }
- "#)
- .file("src/lib.rs", r#"
- extern crate a;
- pub fn foo() { a::a(); }
- "#)
- .file("b/Cargo.toml", r#"
- [package]
- name = "b"
- version = "0.1.0"
- authors = []
-
- [dependencies]
- a = { path = "../a", features = [], default-features = false }
- "#)
- .file("b/src/lib.rs", "")
- .file("a/Cargo.toml", r#"
- [package]
- name = "a"
- version = "0.1.0"
- authors = []
-
- [features]
- default = ["f1"]
- f1 = []
- "#)
- .file("a/src/lib.rs", r#"
- #[cfg(feature = "f1")]
- pub fn a() {}
- "#)
- .build();
-
- assert_that(p.cargo("build"), execs().with_status(0));
- assert_that(p.cargo("build"), execs().with_status(0).with_stdout(""));
- assert_that(p.cargo("build"), execs().with_status(0).with_stdout(""));
-}
-
-#[test]
-fn optional_and_dev_dep() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "test"
- version = "0.1.0"
- authors = []
-
- [dependencies]
- foo = { path = "foo", optional = true }
- [dev-dependencies]
- foo = { path = "foo" }
- "#)
- .file("src/lib.rs", "")
- .file("foo/Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
- "#)
- .file("foo/src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr("\
-[COMPILING] test v0.1.0 ([..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-}
-
-#[test]
-fn activating_feature_activates_dep() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "test"
- version = "0.1.0"
- authors = []
-
- [dependencies]
- foo = { path = "foo", optional = true }
-
- [features]
- a = ["foo/a"]
- "#)
- .file("src/lib.rs", "
- extern crate foo;
- pub fn bar() {
- foo::bar();
- }
- ")
- .file("foo/Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
-
- [features]
- a = []
- "#)
- .file("foo/src/lib.rs", r#"
- #[cfg(feature = "a")]
- pub fn bar() {}
- "#)
- .build();
-
- assert_that(p.cargo("build").arg("--features").arg("a").arg("-v"),
- execs().with_status(0));
-}
-
-#[test]
-fn dep_feature_in_cmd_line() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies.derived]
- path = "derived"
- "#)
- .file("src/main.rs", r#"
- extern crate derived;
- fn main() { derived::test(); }
- "#)
- .file("derived/Cargo.toml", r#"
- [package]
- name = "derived"
- version = "0.0.1"
- authors = []
-
- [dependencies.bar]
- path = "../bar"
-
- [features]
- default = []
- derived-feat = ["bar/some-feat"]
- "#)
- .file("derived/src/lib.rs", r#"
- extern crate bar;
- pub use bar::test;
- "#)
- .file("bar/Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
-
- [features]
- some-feat = []
- "#)
- .file("bar/src/lib.rs", r#"
- #[cfg(feature = "some-feat")]
- pub fn test() { print!("test"); }
- "#)
- .build();
-
- // The foo project requires that feature "some-feat" in "bar" is enabled.
- // Building without any features enabled should fail:
- assert_that(p.cargo("build"),
- execs().with_status(101));
-
- // We should be able to enable the feature "derived-feat", which enables "some-feat",
- // on the command line. The feature is enabled, thus building should be successful:
- assert_that(p.cargo("build").arg("--features").arg("derived/derived-feat"),
- execs().with_status(0));
-
- // Trying to enable features of transitive dependencies is an error
- assert_that(p.cargo("build").arg("--features").arg("bar/some-feat"),
- execs().with_status(101).with_stderr("\
-[ERROR] Package `foo v0.0.1 ([..])` does not have these features: `bar`
-"));
-
- // Hierarchical feature specification should still be disallowed
- assert_that(p.cargo("build").arg("--features").arg("derived/bar/some-feat"),
- execs().with_status(101).with_stderr("\
-[ERROR] feature names may not contain slashes: `bar/some-feat`
-"));
-}
-
-#[test]
-fn all_features_flag_enables_all_features() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [features]
- foo = []
- bar = []
-
- [dependencies.baz]
- path = "baz"
- optional = true
- "#)
- .file("src/main.rs", r#"
- #[cfg(feature = "foo")]
- pub fn foo() {}
-
- #[cfg(feature = "bar")]
- pub fn bar() {
- extern crate baz;
- baz::baz();
- }
-
- fn main() {
- foo();
- bar();
- }
- "#)
- .file("baz/Cargo.toml", r#"
- [package]
- name = "baz"
- version = "0.0.1"
- authors = []
- "#)
- .file("baz/src/lib.rs", "pub fn baz() {}")
- .build();
-
- assert_that(p.cargo("build").arg("--all-features"),
- execs().with_status(0));
-}
-
-#[test]
-fn many_cli_features_comma_delimited() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies.bar]
- path = "bar"
- optional = true
-
- [dependencies.baz]
- path = "baz"
- optional = true
- "#)
- .file("src/main.rs", r#"
- #[allow(unused_extern_crates)]
- extern crate bar;
- #[allow(unused_extern_crates)]
- extern crate baz;
- fn main() {}
- "#)
- .file("bar/Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
- "#)
- .file("bar/src/lib.rs", "pub fn bar() {}")
- .file("baz/Cargo.toml", r#"
- [package]
- name = "baz"
- version = "0.0.1"
- authors = []
- "#)
- .file("baz/src/lib.rs", "pub fn baz() {}")
- .build();
-
- assert_that(p.cargo("build").arg("--features").arg("bar,baz"),
- execs().with_status(0).with_stderr(format!("\
-[COMPILING] ba[..] v0.0.1 ({dir}/ba[..])
-[COMPILING] ba[..] v0.0.1 ({dir}/ba[..])
-[COMPILING] foo v0.0.1 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-", dir = p.url())));
-}
-
-#[test]
-fn many_cli_features_comma_and_space_delimited() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies.bar]
- path = "bar"
- optional = true
-
- [dependencies.baz]
- path = "baz"
- optional = true
-
- [dependencies.bam]
- path = "bam"
- optional = true
-
- [dependencies.bap]
- path = "bap"
- optional = true
- "#)
- .file("src/main.rs", r#"
- #[allow(unused_extern_crates)]
- extern crate bar;
- #[allow(unused_extern_crates)]
- extern crate baz;
- #[allow(unused_extern_crates)]
- extern crate bam;
- #[allow(unused_extern_crates)]
- extern crate bap;
- fn main() {}
- "#)
- .file("bar/Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
- "#)
- .file("bar/src/lib.rs", "pub fn bar() {}")
- .file("baz/Cargo.toml", r#"
- [package]
- name = "baz"
- version = "0.0.1"
- authors = []
- "#)
- .file("baz/src/lib.rs", "pub fn baz() {}")
- .file("bam/Cargo.toml", r#"
- [package]
- name = "bam"
- version = "0.0.1"
- authors = []
- "#)
- .file("bam/src/lib.rs", "pub fn bam() {}")
- .file("bap/Cargo.toml", r#"
- [package]
- name = "bap"
- version = "0.0.1"
- authors = []
- "#)
- .file("bap/src/lib.rs", "pub fn bap() {}")
- .build();
-
- assert_that(p.cargo("build").arg("--features").arg("bar,baz bam bap"),
- execs().with_status(0).with_stderr(format!("\
-[COMPILING] ba[..] v0.0.1 ({dir}/ba[..])
-[COMPILING] ba[..] v0.0.1 ({dir}/ba[..])
-[COMPILING] ba[..] v0.0.1 ({dir}/ba[..])
-[COMPILING] ba[..] v0.0.1 ({dir}/ba[..])
-[COMPILING] foo v0.0.1 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-", dir = p.url())));
-}
+++ /dev/null
-extern crate cargotest;
-extern crate hamcrest;
-
-use cargotest::support::{project, execs};
-use hamcrest::assert_that;
-
-#[test]
-fn no_deps() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- authors = []
- version = "0.0.1"
- "#)
- .file("src/main.rs", r#"
- mod a; fn main() {}
- "#)
- .file("src/a.rs", "")
- .build();
-
- assert_that(p.cargo("fetch"),
- execs().with_status(0).with_stdout(""));
-}
+++ /dev/null
-extern crate cargotest;
-extern crate hamcrest;
-
-use std::fs::{self, File};
-use std::io::prelude::*;
-
-use cargotest::sleep_ms;
-use cargotest::support::{project, execs, path2url};
-use cargotest::support::paths::CargoPathExt;
-use hamcrest::{assert_that, existing_file};
-
-#[test]
-fn modifying_and_moving() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- authors = []
- version = "0.0.1"
- "#)
- .file("src/main.rs", r#"
- mod a; fn main() {}
- "#)
- .file("src/a.rs", "")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr(format!("\
-[COMPILING] foo v0.0.1 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-", dir = path2url(p.root()))));
-
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stdout(""));
- p.root().move_into_the_past();
- p.root().join("target").move_into_the_past();
-
- File::create(&p.root().join("src/a.rs")).unwrap()
- .write_all(b"#[allow(unused)]fn main() {}").unwrap();
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr(format!("\
-[COMPILING] foo v0.0.1 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-", dir = path2url(p.root()))));
-
- fs::rename(&p.root().join("src/a.rs"), &p.root().join("src/b.rs")).unwrap();
- assert_that(p.cargo("build"),
- execs().with_status(101));
-}
-
-#[test]
-fn modify_only_some_files() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- authors = []
- version = "0.0.1"
- "#)
- .file("src/lib.rs", "mod a;")
- .file("src/a.rs", "")
- .file("src/main.rs", r#"
- mod b;
- fn main() {}
- "#)
- .file("src/b.rs", "")
- .file("tests/test.rs", "")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr(format!("\
-[COMPILING] foo v0.0.1 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-", dir = path2url(p.root()))));
- assert_that(p.cargo("test"),
- execs().with_status(0));
- sleep_ms(1000);
-
- assert_that(&p.bin("foo"), existing_file());
-
- let lib = p.root().join("src/lib.rs");
- let bin = p.root().join("src/b.rs");
-
- File::create(&lib).unwrap().write_all(b"invalid rust code").unwrap();
- File::create(&bin).unwrap().write_all(b"#[allow(unused)]fn foo() {}").unwrap();
- lib.move_into_the_past();
-
- // Make sure the binary is rebuilt, not the lib
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr(format!("\
-[COMPILING] foo v0.0.1 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-", dir = path2url(p.root()))));
- assert_that(&p.bin("foo"), existing_file());
-}
-
-#[test]
-fn rebuild_sub_package_then_while_package() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- authors = []
- version = "0.0.1"
-
- [dependencies.a]
- path = "a"
- [dependencies.b]
- path = "b"
- "#)
- .file("src/lib.rs", "extern crate a; extern crate b;")
- .file("a/Cargo.toml", r#"
- [package]
- name = "a"
- authors = []
- version = "0.0.1"
- [dependencies.b]
- path = "../b"
- "#)
- .file("a/src/lib.rs", "extern crate b;")
- .file("b/Cargo.toml", r#"
- [package]
- name = "b"
- authors = []
- version = "0.0.1"
- "#)
- .file("b/src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0));
-
- File::create(&p.root().join("b/src/lib.rs")).unwrap().write_all(br#"
- pub fn b() {}
- "#).unwrap();
-
- assert_that(p.cargo("build").arg("-pb"),
- execs().with_status(0));
-
- File::create(&p.root().join("src/lib.rs")).unwrap().write_all(br#"
- extern crate a;
- extern crate b;
- pub fn toplevel() {}
- "#).unwrap();
-
- assert_that(p.cargo("build"),
- execs().with_status(0));
-}
-
-#[test]
-fn changing_lib_features_caches_targets() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- authors = []
- version = "0.0.1"
-
- [features]
- foo = []
- "#)
- .file("src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0)
- .with_stderr("\
-[..]Compiling foo v0.0.1 ([..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-
- assert_that(p.cargo("build").arg("--features").arg("foo"),
- execs().with_status(0)
- .with_stderr("\
-[..]Compiling foo v0.0.1 ([..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-
- /* Targets should be cached from the first build */
-
- assert_that(p.cargo("build"),
- execs().with_status(0)
- .with_stderr("\
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-
- assert_that(p.cargo("build"),
- execs().with_status(0)
- .with_stdout(""));
-
- assert_that(p.cargo("build").arg("--features").arg("foo"),
- execs().with_status(0)
- .with_stderr("\
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-}
-
-#[test]
-fn changing_profiles_caches_targets() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- authors = []
- version = "0.0.1"
-
- [profile.dev]
- panic = "abort"
-
- [profile.test]
- panic = "unwind"
- "#)
- .file("src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0)
- .with_stderr("\
-[..]Compiling foo v0.0.1 ([..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-
- assert_that(p.cargo("test"),
- execs().with_status(0)
- .with_stderr("\
-[..]Compiling foo v0.0.1 ([..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] target[..]debug[..]deps[..]foo-[..][EXE]
-[DOCTEST] foo
-"));
-
- /* Targets should be cached from the first build */
-
- assert_that(p.cargo("build"),
- execs().with_status(0)
- .with_stderr("\
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-
- assert_that(p.cargo("test").arg("foo"),
- execs().with_status(0)
- .with_stderr("\
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] target[..]debug[..]deps[..]foo-[..][EXE]
-[DOCTEST] foo
-"));
-}
-
-#[test]
-fn changing_bin_paths_common_target_features_caches_targets() {
- // Make sure dep_cache crate is built once per feature
- let p = project("foo")
- .file(".cargo/config", r#"
- [build]
- target-dir = "./target"
- "#)
- .file("dep_crate/Cargo.toml", r#"
- [package]
- name = "dep_crate"
- version = "0.0.1"
- authors = []
-
- [features]
- ftest = []
- "#)
- .file("dep_crate/src/lib.rs", r#"
- #[cfg(feature = "ftest")]
- pub fn yo() {
- println!("ftest on")
- }
- #[cfg(not(feature = "ftest"))]
- pub fn yo() {
- println!("ftest off")
- }
- "#)
- .file("a/Cargo.toml", r#"
- [package]
- name = "a"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- dep_crate = {path = "../dep_crate", features = []}
- "#)
- .file("a/src/lib.rs", "")
- .file("a/src/main.rs", r#"
- extern crate dep_crate;
- use dep_crate::yo;
- fn main() {
- yo();
- }
- "#)
- .file("b/Cargo.toml", r#"
- [package]
- name = "b"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- dep_crate = {path = "../dep_crate", features = ["ftest"]}
- "#)
- .file("b/src/lib.rs", "")
- .file("b/src/main.rs", r#"
- extern crate dep_crate;
- use dep_crate::yo;
- fn main() {
- yo();
- }
- "#)
- .build();
-
- /* Build and rebuild a/. Ensure dep_crate only builds once */
- assert_that(p.cargo("run").cwd(p.root().join("a")),
- execs().with_status(0)
- .with_stdout("ftest off")
- .with_stderr("\
-[..]Compiling dep_crate v0.0.1 ([..])
-[..]Compiling a v0.0.1 ([..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] `[..]target[/]debug[/]a[EXE]`
-"));
- assert_that(p.cargo("clean").arg("-p").arg("a").cwd(p.root().join("a")),
- execs().with_status(0));
- assert_that(p.cargo("run").cwd(p.root().join("a")),
- execs().with_status(0)
- .with_stdout("ftest off")
- .with_stderr("\
-[..]Compiling a v0.0.1 ([..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] `[..]target[/]debug[/]a[EXE]`
-"));
-
- /* Build and rebuild b/. Ensure dep_crate only builds once */
- assert_that(p.cargo("run").cwd(p.root().join("b")),
- execs().with_status(0)
- .with_stdout("ftest on")
- .with_stderr("\
-[..]Compiling dep_crate v0.0.1 ([..])
-[..]Compiling b v0.0.1 ([..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] `[..]target[/]debug[/]b[EXE]`
-"));
- assert_that(p.cargo("clean").arg("-p").arg("b").cwd(p.root().join("b")),
- execs().with_status(0));
- assert_that(p.cargo("run").cwd(p.root().join("b")),
- execs().with_status(0)
- .with_stdout("ftest on")
- .with_stderr("\
-[..]Compiling b v0.0.1 ([..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] `[..]target[/]debug[/]b[EXE]`
-"));
-
- /* Build a/ package again. If we cache different feature dep builds correctly,
- * this should not cause a rebuild of dep_crate */
- assert_that(p.cargo("clean").arg("-p").arg("a").cwd(p.root().join("a")),
- execs().with_status(0));
- assert_that(p.cargo("run").cwd(p.root().join("a")),
- execs().with_status(0)
- .with_stdout("ftest off")
- .with_stderr("\
-[..]Compiling a v0.0.1 ([..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] `[..]target[/]debug[/]a[EXE]`
-"));
-
- /* Build b/ package again. If we cache different feature dep builds correctly,
- * this should not cause a rebuild */
- assert_that(p.cargo("clean").arg("-p").arg("b").cwd(p.root().join("b")),
- execs().with_status(0));
- assert_that(p.cargo("run").cwd(p.root().join("b")),
- execs().with_status(0)
- .with_stdout("ftest on")
- .with_stderr("\
-[..]Compiling b v0.0.1 ([..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] `[..]target[/]debug[/]b[EXE]`
-"));
-}
-
-#[test]
-fn changing_bin_features_caches_targets() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- authors = []
- version = "0.0.1"
-
- [features]
- foo = []
- "#)
- .file("src/main.rs", r#"
- fn main() {
- let msg = if cfg!(feature = "foo") { "feature on" } else { "feature off" };
- println!("{}", msg);
- }
- "#)
- .build();
-
- assert_that(p.cargo("run"),
- execs().with_status(0)
- .with_stdout("feature off")
- .with_stderr("\
-[..]Compiling foo v0.0.1 ([..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] `target[/]debug[/]foo[EXE]`
-"));
-
- assert_that(p.cargo("run").arg("--features").arg("foo"),
- execs().with_status(0)
- .with_stdout("feature on")
- .with_stderr("\
-[..]Compiling foo v0.0.1 ([..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] `target[/]debug[/]foo[EXE]`
-"));
-
- /* Targets should be cached from the first build */
-
- assert_that(p.cargo("run"),
- execs().with_status(0)
- .with_stdout("feature off")
- .with_stderr("\
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] `target[/]debug[/]foo[EXE]`
-"));
-
- assert_that(p.cargo("run").arg("--features").arg("foo"),
- execs().with_status(0)
- .with_stdout("feature on")
- .with_stderr("\
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] `target[/]debug[/]foo[EXE]`
-"));
-}
-
-#[test]
-fn rebuild_tests_if_lib_changes() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/lib.rs", "pub fn foo() {}")
- .file("tests/foo.rs", r#"
- extern crate foo;
- #[test]
- fn test() { foo::foo(); }
- "#)
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0));
- assert_that(p.cargo("test"),
- execs().with_status(0));
-
- sleep_ms(1000);
- File::create(&p.root().join("src/lib.rs")).unwrap();
-
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(0));
- assert_that(p.cargo("test").arg("-v"),
- execs().with_status(101));
-}
-
-#[test]
-fn no_rebuild_transitive_target_deps() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- a = { path = "a" }
- [dev-dependencies]
- b = { path = "b" }
- "#)
- .file("src/lib.rs", "")
- .file("tests/foo.rs", "")
- .file("a/Cargo.toml", r#"
- [package]
- name = "a"
- version = "0.0.1"
- authors = []
-
- [target.foo.dependencies]
- c = { path = "../c" }
- "#)
- .file("a/src/lib.rs", "")
- .file("b/Cargo.toml", r#"
- [package]
- name = "b"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- c = { path = "../c" }
- "#)
- .file("b/src/lib.rs", "")
- .file("c/Cargo.toml", r#"
- [package]
- name = "c"
- version = "0.0.1"
- authors = []
- "#)
- .file("c/src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0));
- assert_that(p.cargo("test").arg("--no-run"),
- execs().with_status(0)
- .with_stderr("\
-[COMPILING] c v0.0.1 ([..])
-[COMPILING] b v0.0.1 ([..])
-[COMPILING] foo v0.0.1 ([..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-}
-
-#[test]
-fn rerun_if_changed_in_dep() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- a = { path = "a" }
- "#)
- .file("src/lib.rs", "")
- .file("a/Cargo.toml", r#"
- [package]
- name = "a"
- version = "0.0.1"
- authors = []
- build = "build.rs"
- "#)
- .file("a/build.rs", r#"
- fn main() {
- println!("cargo:rerun-if-changed=build.rs");
- }
- "#)
- .file("a/src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0));
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stdout(""));
-}
-
-#[test]
-fn same_build_dir_cached_packages() {
- let p = project("foo")
- .file("a1/Cargo.toml", r#"
- [package]
- name = "a1"
- version = "0.0.1"
- authors = []
- [dependencies]
- b = { path = "../b" }
- "#)
- .file("a1/src/lib.rs", "")
- .file("a2/Cargo.toml", r#"
- [package]
- name = "a2"
- version = "0.0.1"
- authors = []
- [dependencies]
- b = { path = "../b" }
- "#)
- .file("a2/src/lib.rs", "")
- .file("b/Cargo.toml", r#"
- [package]
- name = "b"
- version = "0.0.1"
- authors = []
- [dependencies]
- c = { path = "../c" }
- "#)
- .file("b/src/lib.rs", "")
- .file("c/Cargo.toml", r#"
- [package]
- name = "c"
- version = "0.0.1"
- authors = []
- [dependencies]
- d = { path = "../d" }
- "#)
- .file("c/src/lib.rs", "")
- .file("d/Cargo.toml", r#"
- [package]
- name = "d"
- version = "0.0.1"
- authors = []
- "#)
- .file("d/src/lib.rs", "")
- .file(".cargo/config", r#"
- [build]
- target-dir = "./target"
- "#)
- .build();
-
- assert_that(p.cargo("build").cwd(p.root().join("a1")),
- execs().with_status(0).with_stderr(&format!("\
-[COMPILING] d v0.0.1 ({dir}/d)
-[COMPILING] c v0.0.1 ({dir}/c)
-[COMPILING] b v0.0.1 ({dir}/b)
-[COMPILING] a1 v0.0.1 ({dir}/a1)
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-", dir = p.url())));
- assert_that(p.cargo("build").cwd(p.root().join("a2")),
- execs().with_status(0).with_stderr(&format!("\
-[COMPILING] a2 v0.0.1 ({dir}/a2)
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-", dir = p.url())));
-}
-
-#[test]
-fn no_rebuild_if_build_artifacts_move_backwards_in_time() {
- let p = project("backwards_in_time")
- .file("Cargo.toml", r#"
- [package]
- name = "backwards_in_time"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- a = { path = "a" }
- "#)
- .file("src/lib.rs", "")
- .file("a/Cargo.toml", r#"
- [package]
- name = "a"
- version = "0.0.1"
- authors = []
- "#)
- .file("a/src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0));
-
- p.root().move_into_the_past();
-
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stdout("").with_stderr("\
-[FINISHED] [..]
-"));
-}
-
-#[test]
-fn rebuild_if_build_artifacts_move_forward_in_time() {
- let p = project("forwards_in_time")
- .file("Cargo.toml", r#"
- [package]
- name = "forwards_in_time"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- a = { path = "a" }
- "#)
- .file("src/lib.rs", "")
- .file("a/Cargo.toml", r#"
- [package]
- name = "a"
- version = "0.0.1"
- authors = []
- "#)
- .file("a/src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0));
-
- p.root().move_into_the_future();
-
- assert_that(p.cargo("build").env("RUST_LOG", ""),
- execs().with_status(0).with_stdout("").with_stderr("\
-[COMPILING] a v0.0.1 ([..])
-[COMPILING] forwards_in_time v0.0.1 ([..])
-[FINISHED] [..]
-"));
-}
-
-#[test]
-fn rebuild_if_environment_changes() {
- let p = project("env_change")
- .file("Cargo.toml", r#"
- [package]
- name = "env_change"
- description = "old desc"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/main.rs", r#"
- fn main() {
- println!("{}", env!("CARGO_PKG_DESCRIPTION"));
- }
- "#)
- .build();
-
- assert_that(p.cargo("run"),
- execs().with_status(0)
- .with_stdout("old desc").with_stderr(&format!("\
-[COMPILING] env_change v0.0.1 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] `target[/]debug[/]env_change[EXE]`
-", dir = p.url())));
-
- File::create(&p.root().join("Cargo.toml")).unwrap().write_all(br#"
- [package]
- name = "env_change"
- description = "new desc"
- version = "0.0.1"
- authors = []
- "#).unwrap();
-
- assert_that(p.cargo("run"),
- execs().with_status(0)
- .with_stdout("new desc").with_stderr(&format!("\
-[COMPILING] env_change v0.0.1 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] `target[/]debug[/]env_change[EXE]`
-", dir = p.url())));
-}
-
-#[test]
-fn no_rebuild_when_rename_dir() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- foo = { path = "foo" }
- "#)
- .file("src/lib.rs", "")
- .file("foo/Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("foo/src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build"), execs().with_status(0));
- let mut new = p.root();
- new.pop();
- new.push("bar");
- fs::rename(p.root(), &new).unwrap();
-
- assert_that(p.cargo("build").cwd(&new),
- execs().with_status(0)
- .with_stderr("\
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-}
+++ /dev/null
-extern crate cargotest;
-extern crate hamcrest;
-
-use std::fs::{self, File};
-use std::io::prelude::*;
-
-use cargotest::support::{project, execs};
-use hamcrest::{assert_that, existing_file, is_not};
-
-#[test]
-fn adding_and_removing_packages() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- authors = []
- version = "0.0.1"
- "#)
- .file("src/main.rs", "fn main() {}")
- .file("bar/Cargo.toml", r#"
- [package]
- name = "bar"
- authors = []
- version = "0.0.1"
- "#)
- .file("bar/src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("generate-lockfile"),
- execs().with_status(0));
-
- let toml = p.root().join("Cargo.toml");
- let lock1 = p.read_lockfile();
-
- // add a dep
- File::create(&toml).unwrap().write_all(br#"
- [package]
- name = "foo"
- authors = []
- version = "0.0.1"
-
- [dependencies.bar]
- path = "bar"
- "#).unwrap();
- assert_that(p.cargo("generate-lockfile"),
- execs().with_status(0));
- let lock2 = p.read_lockfile();
- assert!(lock1 != lock2);
-
- // change the dep
- File::create(&p.root().join("bar/Cargo.toml")).unwrap().write_all(br#"
- [package]
- name = "bar"
- authors = []
- version = "0.0.2"
- "#).unwrap();
- assert_that(p.cargo("generate-lockfile"),
- execs().with_status(0));
- let lock3 = p.read_lockfile();
- assert!(lock1 != lock3);
- assert!(lock2 != lock3);
-
- // remove the dep
- println!("lock4");
- File::create(&toml).unwrap().write_all(br#"
- [package]
- name = "foo"
- authors = []
- version = "0.0.1"
- "#).unwrap();
- assert_that(p.cargo("generate-lockfile"),
- execs().with_status(0));
- let lock4 = p.read_lockfile();
- assert_eq!(lock1, lock4);
-}
-
-#[test]
-fn no_index_update() {
- use cargotest::ChannelChanger;
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- authors = []
- version = "0.0.1"
-
- [dependencies]
- serde = "1.0"
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("generate-lockfile"),
- execs().with_status(0).with_stdout("")
- .with_stderr_contains(" Updating registry `https://github.com/rust-lang/crates.io-index`"));
-
- assert_that(p.cargo("generate-lockfile").masquerade_as_nightly_cargo().arg("-Zno-index-update"),
- execs().with_status(0).with_stdout("")
- .with_stderr_does_not_contain(" Updating registry `https://github.com/rust-lang/crates.io-index`"));
-}
-
-#[test]
-fn preserve_metadata() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- authors = []
- version = "0.0.1"
- "#)
- .file("src/main.rs", "fn main() {}")
- .file("bar/Cargo.toml", r#"
- [package]
- name = "bar"
- authors = []
- version = "0.0.1"
- "#)
- .file("bar/src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("generate-lockfile"),
- execs().with_status(0));
-
- let metadata = r#"
-[metadata]
-bar = "baz"
-foo = "bar"
-"#;
- let lockfile = p.root().join("Cargo.lock");
- let lock = p.read_lockfile();
- let data = lock + metadata;
- File::create(&lockfile).unwrap().write_all(data.as_bytes()).unwrap();
-
- // Build and make sure the metadata is still there
- assert_that(p.cargo("build"),
- execs().with_status(0));
- let lock = p.read_lockfile();
- assert!(lock.contains(metadata.trim()), "{}", lock);
-
- // Update and make sure the metadata is still there
- assert_that(p.cargo("update"),
- execs().with_status(0));
- let lock = p.read_lockfile();
- assert!(lock.contains(metadata.trim()), "{}", lock);
-}
-
-#[test]
-fn preserve_line_endings_issue_2076() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- authors = []
- version = "0.0.1"
- "#)
- .file("src/main.rs", "fn main() {}")
- .file("bar/Cargo.toml", r#"
- [package]
- name = "bar"
- authors = []
- version = "0.0.1"
- "#)
- .file("bar/src/lib.rs", "")
- .build();
-
- let lockfile = p.root().join("Cargo.lock");
- assert_that(p.cargo("generate-lockfile"),
- execs().with_status(0));
- assert_that(&lockfile,
- existing_file());
- assert_that(p.cargo("generate-lockfile"),
- execs().with_status(0));
-
- let lock0 = p.read_lockfile();
-
- assert!(lock0.starts_with("[[package]]\n"));
-
- let lock1 = lock0.replace("\n", "\r\n");
- {
- File::create(&lockfile).unwrap().write_all(lock1.as_bytes()).unwrap();
- }
-
- assert_that(p.cargo("generate-lockfile"),
- execs().with_status(0));
-
- let lock2 = p.read_lockfile();
-
- assert!(lock2.starts_with("[[package]]\r\n"));
- assert_eq!(lock1, lock2);
-}
-
-#[test]
-fn cargo_update_generate_lockfile() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- authors = []
- version = "0.0.1"
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- let lockfile = p.root().join("Cargo.lock");
- assert_that(&lockfile, is_not(existing_file()));
- assert_that(p.cargo("update"), execs().with_status(0).with_stdout(""));
- assert_that(&lockfile, existing_file());
-
- fs::remove_file(p.root().join("Cargo.lock")).unwrap();
-
- assert_that(&lockfile, is_not(existing_file()));
- assert_that(p.cargo("update"), execs().with_status(0).with_stdout(""));
- assert_that(&lockfile, existing_file());
-
-}
+++ /dev/null
-extern crate cargo;
-extern crate cargotest;
-extern crate git2;
-extern crate hamcrest;
-
-use std::fs::{self, File};
-use std::io::prelude::*;
-use std::net::{TcpListener, TcpStream};
-use std::path::Path;
-use std::sync::Arc;
-use std::sync::atomic::{AtomicBool, Ordering};
-use std::thread;
-
-use cargo::util::process;
-use cargotest::sleep_ms;
-use cargotest::support::paths::{self, CargoPathExt};
-use cargotest::support::{git, project, execs, main_file, path2url};
-use cargotest::ChannelChanger;
-use hamcrest::{assert_that,existing_file};
-
-#[test]
-fn cargo_compile_simple_git_dep() {
- let project = project("foo");
- let git_project = git::new("dep1", |project| {
- project
- .file("Cargo.toml", r#"
- [project]
-
- name = "dep1"
- version = "0.5.0"
- authors = ["carlhuda@example.com"]
-
- [lib]
-
- name = "dep1"
- "#)
- .file("src/dep1.rs", r#"
- pub fn hello() -> &'static str {
- "hello world"
- }
- "#)
- }).unwrap();
-
- let project = project
- .file("Cargo.toml", &format!(r#"
- [project]
-
- name = "foo"
- version = "0.5.0"
- authors = ["wycats@example.com"]
-
- [dependencies.dep1]
-
- git = '{}'
- "#, git_project.url()))
- .file("src/main.rs", &main_file(r#""{}", dep1::hello()"#, &["dep1"]))
- .build();
-
- let root = project.root();
- let git_root = git_project.root();
-
- assert_that(project.cargo("build"),
- execs()
- .with_stderr(&format!("[UPDATING] git repository `{}`\n\
- [COMPILING] dep1 v0.5.0 ({}#[..])\n\
- [COMPILING] foo v0.5.0 ({})\n\
- [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]\n",
- path2url(git_root.clone()),
- path2url(git_root),
- path2url(root))));
-
- assert_that(&project.bin("foo"), existing_file());
-
- assert_that(
- process(&project.bin("foo")),
- execs().with_stdout("hello world\n"));
-}
-
-#[test]
-fn cargo_compile_forbird_git_httpsrepo_offline() {
-
- let p = project("need_remote_repo")
- .file("Cargo.toml", r#"
-
- [project]
- name = "need_remote_repo"
- version = "0.5.0"
- authors = ["chabapok@example.com"]
-
- [dependencies.dep1]
- git = 'https://github.com/some_user/dep1.git'
- "#)
- .file("src/main.rs", "")
- .build();
-
-
- assert_that(p.cargo("build").masquerade_as_nightly_cargo().arg("-Zoffline"),
- execs().with_status(101).
- with_stderr("\
-error: failed to load source for a dependency on `dep1`
-
-Caused by:
- Unable to update https://github.com/some_user/dep1.git
-
-Caused by:
- can't checkout from 'https://github.com/some_user/dep1.git': you are in the offline mode (-Z offline)"));
-}
-
-
-#[test]
-fn cargo_compile_offline_with_cached_git_dep() {
- let git_project = git::new("dep1", |project| {
- project
- .file("Cargo.toml", r#"
- [project]
- name = "dep1"
- version = "0.5.0"
- authors = ["chabapok@example.com"]
-
- [lib]
- name = "dep1""#)
- .file("src/lib.rs", r#"
- pub static COOL_STR:&str = "cached git repo rev1";
- "#)
- }).unwrap();
-
- let repo = git2::Repository::open(&git_project.root()).unwrap();
- let rev1 = repo.revparse_single("HEAD").unwrap().id();
-
- // Commit the changes and make sure we trigger a recompile
- File::create(&git_project.root().join("src/lib.rs")).unwrap().write_all(br#"
- pub static COOL_STR:&str = "cached git repo rev2";
- "#).unwrap();
- git::add(&repo);
- let rev2 = git::commit(&repo);
-
- {
- // cache to regisrty rev1 and rev2
- let prj = project("cache_git_dep")
- .file("Cargo.toml", &format!(r#"
- [project]
- name = "cache_git_dep"
- version = "0.5.0"
-
- [dependencies.dep1]
- git = '{}'
- rev = "{}"
- "#, git_project.url(), rev1.clone()))
- .file("src/main.rs", "fn main(){}")
- .build();
- assert_that(prj.cargo("build"), execs().with_status(0));
-
- File::create(&prj.root().join("Cargo.toml")).unwrap().write_all(
- &format!(r#"
- [project]
- name = "cache_git_dep"
- version = "0.5.0"
-
- [dependencies.dep1]
- git = '{}'
- rev = "{}"
- "#, git_project.url(), rev2.clone()).as_bytes()
- ).unwrap();
- assert_that(prj.cargo("build"), execs().with_status(0));
- }
-
- let project = project("foo")
- .file("Cargo.toml", &format!(r#"
- [project]
- name = "foo"
- version = "0.5.0"
-
- [dependencies.dep1]
- git = '{}'
- "#, git_project.url()))
- .file("src/main.rs", &main_file(r#""hello from {}", dep1::COOL_STR"#, &["dep1"]))
- .build();
-
- let root = project.root();
- let git_root = git_project.root();
-
- assert_that(project.cargo("build").masquerade_as_nightly_cargo().arg("-Zoffline"),
- execs().with_stderr(format!("\
-[COMPILING] dep1 v0.5.0 ({}#[..])
-[COMPILING] foo v0.5.0 ({})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]",
- path2url(git_root),
- path2url(root)
- )));
-
- assert_that(&project.bin("foo"), existing_file());
-
- assert_that(process(&project.bin("foo")),
- execs().with_stdout("hello from cached git repo rev2\n"));
-
- drop( File::create(&project.root().join("Cargo.toml")).unwrap()
- .write_all(&format!(r#"
- [project]
- name = "foo"
- version = "0.5.0"
-
- [dependencies.dep1]
- git = '{}'
- rev = "{}"
- "#, git_project.url(), rev1).as_bytes()).unwrap() );
-
- let _out = project.cargo("build").masquerade_as_nightly_cargo()
- .arg("-Zoffline").exec_with_output();
- assert_that(process(&project.bin("foo")),
- execs().with_stdout("hello from cached git repo rev1\n"));
-}
-
-
-#[test]
-fn cargo_compile_git_dep_branch() {
- let project = project("foo");
- let git_project = git::new("dep1", |project| {
- project
- .file("Cargo.toml", r#"
- [project]
-
- name = "dep1"
- version = "0.5.0"
- authors = ["carlhuda@example.com"]
-
- [lib]
-
- name = "dep1"
- "#)
- .file("src/dep1.rs", r#"
- pub fn hello() -> &'static str {
- "hello world"
- }
- "#)
- }).unwrap();
-
- // Make a new branch based on the current HEAD commit
- let repo = git2::Repository::open(&git_project.root()).unwrap();
- let head = repo.head().unwrap().target().unwrap();
- let head = repo.find_commit(head).unwrap();
- repo.branch("branchy", &head, true).unwrap();
-
- let project = project
- .file("Cargo.toml", &format!(r#"
- [project]
-
- name = "foo"
- version = "0.5.0"
- authors = ["wycats@example.com"]
-
- [dependencies.dep1]
-
- git = '{}'
- branch = "branchy"
-
- "#, git_project.url()))
- .file("src/main.rs", &main_file(r#""{}", dep1::hello()"#, &["dep1"]))
- .build();
-
- let root = project.root();
- let git_root = git_project.root();
-
- assert_that(project.cargo("build"),
- execs()
- .with_stderr(&format!("[UPDATING] git repository `{}`\n\
- [COMPILING] dep1 v0.5.0 ({}?branch=branchy#[..])\n\
- [COMPILING] foo v0.5.0 ({})\n\
- [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]\n",
- path2url(git_root.clone()),
- path2url(git_root),
- path2url(root))));
-
- assert_that(&project.bin("foo"), existing_file());
-
- assert_that(
- process(&project.bin("foo")),
- execs().with_stdout("hello world\n"));
-}
-
-#[test]
-fn cargo_compile_git_dep_tag() {
- let project = project("foo");
- let git_project = git::new("dep1", |project| {
- project
- .file("Cargo.toml", r#"
- [project]
-
- name = "dep1"
- version = "0.5.0"
- authors = ["carlhuda@example.com"]
-
- [lib]
-
- name = "dep1"
- "#)
- .file("src/dep1.rs", r#"
- pub fn hello() -> &'static str {
- "hello world"
- }
- "#)
- }).unwrap();
-
- // Make a tag corresponding to the current HEAD
- let repo = git2::Repository::open(&git_project.root()).unwrap();
- let head = repo.head().unwrap().target().unwrap();
- repo.tag("v0.1.0",
- &repo.find_object(head, None).unwrap(),
- &repo.signature().unwrap(),
- "make a new tag",
- false).unwrap();
-
- let project = project
- .file("Cargo.toml", &format!(r#"
- [project]
-
- name = "foo"
- version = "0.5.0"
- authors = ["wycats@example.com"]
-
- [dependencies.dep1]
-
- git = '{}'
- tag = "v0.1.0"
- "#, git_project.url()))
- .file("src/main.rs", &main_file(r#""{}", dep1::hello()"#, &["dep1"]))
- .build();
-
- let root = project.root();
- let git_root = git_project.root();
-
- assert_that(project.cargo("build"),
- execs()
- .with_stderr(&format!("[UPDATING] git repository `{}`\n\
- [COMPILING] dep1 v0.5.0 ({}?tag=v0.1.0#[..])\n\
- [COMPILING] foo v0.5.0 ({})\n\
- [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]\n",
- path2url(git_root.clone()),
- path2url(git_root),
- path2url(root))));
-
- assert_that(&project.bin("foo"), existing_file());
-
- assert_that(process(&project.bin("foo")),
- execs().with_stdout("hello world\n"));
-
- assert_that(project.cargo("build"),
- execs().with_status(0));
-}
-
-#[test]
-fn cargo_compile_with_nested_paths() {
- let git_project = git::new("dep1", |project| {
- project
- .file("Cargo.toml", r#"
- [project]
-
- name = "dep1"
- version = "0.5.0"
- authors = ["carlhuda@example.com"]
-
- [dependencies.dep2]
-
- version = "0.5.0"
- path = "vendor/dep2"
-
- [lib]
-
- name = "dep1"
- "#)
- .file("src/dep1.rs", r#"
- extern crate dep2;
-
- pub fn hello() -> &'static str {
- dep2::hello()
- }
- "#)
- .file("vendor/dep2/Cargo.toml", r#"
- [project]
-
- name = "dep2"
- version = "0.5.0"
- authors = ["carlhuda@example.com"]
-
- [lib]
-
- name = "dep2"
- "#)
- .file("vendor/dep2/src/dep2.rs", r#"
- pub fn hello() -> &'static str {
- "hello world"
- }
- "#)
- }).unwrap();
-
- let p = project("parent")
- .file("Cargo.toml", &format!(r#"
- [project]
-
- name = "parent"
- version = "0.5.0"
- authors = ["wycats@example.com"]
-
- [dependencies.dep1]
-
- version = "0.5.0"
- git = '{}'
-
- [[bin]]
-
- name = "parent"
- "#, git_project.url()))
- .file("src/parent.rs",
- &main_file(r#""{}", dep1::hello()"#, &["dep1"]))
- .build();
-
- p.cargo("build")
- .exec_with_output()
- .unwrap();
-
- assert_that(&p.bin("parent"), existing_file());
-
- assert_that(process(&p.bin("parent")),
- execs().with_stdout("hello world\n"));
-}
-
-#[test]
-fn cargo_compile_with_malformed_nested_paths() {
- let git_project = git::new("dep1", |project| {
- project
- .file("Cargo.toml", r#"
- [project]
-
- name = "dep1"
- version = "0.5.0"
- authors = ["carlhuda@example.com"]
-
- [lib]
-
- name = "dep1"
- "#)
- .file("src/dep1.rs", r#"
- pub fn hello() -> &'static str {
- "hello world"
- }
- "#)
- .file("vendor/dep2/Cargo.toml", r#"
- !INVALID!
- "#)
- }).unwrap();
-
- let p = project("parent")
- .file("Cargo.toml", &format!(r#"
- [project]
-
- name = "parent"
- version = "0.5.0"
- authors = ["wycats@example.com"]
-
- [dependencies.dep1]
-
- version = "0.5.0"
- git = '{}'
-
- [[bin]]
-
- name = "parent"
- "#, git_project.url()))
- .file("src/parent.rs",
- &main_file(r#""{}", dep1::hello()"#, &["dep1"]))
- .build();
-
- p.cargo("build")
- .exec_with_output()
- .unwrap();
-
- assert_that(&p.bin("parent"), existing_file());
-
- assert_that(process(&p.bin("parent")),
- execs().with_stdout("hello world\n"));
-}
-
-#[test]
-fn cargo_compile_with_meta_package() {
- let git_project = git::new("meta-dep", |project| {
- project
- .file("dep1/Cargo.toml", r#"
- [project]
-
- name = "dep1"
- version = "0.5.0"
- authors = ["carlhuda@example.com"]
-
- [lib]
-
- name = "dep1"
- "#)
- .file("dep1/src/dep1.rs", r#"
- pub fn hello() -> &'static str {
- "this is dep1"
- }
- "#)
- .file("dep2/Cargo.toml", r#"
- [project]
-
- name = "dep2"
- version = "0.5.0"
- authors = ["carlhuda@example.com"]
-
- [lib]
-
- name = "dep2"
- "#)
- .file("dep2/src/dep2.rs", r#"
- pub fn hello() -> &'static str {
- "this is dep2"
- }
- "#)
- }).unwrap();
-
- let p = project("parent")
- .file("Cargo.toml", &format!(r#"
- [project]
-
- name = "parent"
- version = "0.5.0"
- authors = ["wycats@example.com"]
-
- [dependencies.dep1]
-
- version = "0.5.0"
- git = '{}'
-
- [dependencies.dep2]
-
- version = "0.5.0"
- git = '{}'
-
- [[bin]]
-
- name = "parent"
- "#, git_project.url(), git_project.url()))
- .file("src/parent.rs",
- &main_file(r#""{} {}", dep1::hello(), dep2::hello()"#, &["dep1", "dep2"]))
- .build();
-
- p.cargo("build")
- .exec_with_output()
- .unwrap();
-
- assert_that(&p.bin("parent"), existing_file());
-
- assert_that(process(&p.bin("parent")),
- execs().with_stdout("this is dep1 this is dep2\n"));
-}
-
-#[test]
-fn cargo_compile_with_short_ssh_git() {
- let url = "git@github.com:a/dep";
-
- let project = project("project")
- .file("Cargo.toml", &format!(r#"
- [project]
-
- name = "foo"
- version = "0.5.0"
- authors = ["wycats@example.com"]
-
- [dependencies.dep]
-
- git = "{}"
-
- [[bin]]
-
- name = "foo"
- "#, url))
- .file("src/foo.rs", &main_file(r#""{}", dep1::hello()"#, &["dep1"]))
- .build();
-
- assert_that(project.cargo("build"),
- execs()
- .with_stdout("")
- .with_stderr(&format!("\
-[ERROR] failed to parse manifest at `[..]`
-
-Caused by:
- invalid url `{}`: relative URL without a base
-", url)));
-}
-
-#[test]
-fn two_revs_same_deps() {
- let bar = git::new("meta-dep", |project| {
- project.file("Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.0"
- authors = []
- "#)
- .file("src/lib.rs", "pub fn bar() -> i32 { 1 }")
- }).unwrap();
-
- let repo = git2::Repository::open(&bar.root()).unwrap();
- let rev1 = repo.revparse_single("HEAD").unwrap().id();
-
- // Commit the changes and make sure we trigger a recompile
- File::create(&bar.root().join("src/lib.rs")).unwrap().write_all(br#"
- pub fn bar() -> i32 { 2 }
- "#).unwrap();
- git::add(&repo);
- let rev2 = git::commit(&repo);
-
- let foo = project("foo")
- .file("Cargo.toml", &format!(r#"
- [project]
- name = "foo"
- version = "0.0.0"
- authors = []
-
- [dependencies.bar]
- git = '{}'
- rev = "{}"
-
- [dependencies.baz]
- path = "../baz"
- "#, bar.url(), rev1))
- .file("src/main.rs", r#"
- extern crate bar;
- extern crate baz;
-
- fn main() {
- assert_eq!(bar::bar(), 1);
- assert_eq!(baz::baz(), 2);
- }
- "#)
- .build();
-
- let _baz = project("baz")
- .file("Cargo.toml", &format!(r#"
- [package]
- name = "baz"
- version = "0.0.0"
- authors = []
-
- [dependencies.bar]
- git = '{}'
- rev = "{}"
- "#, bar.url(), rev2))
- .file("src/lib.rs", r#"
- extern crate bar;
- pub fn baz() -> i32 { bar::bar() }
- "#)
- .build();
-
- assert_that(foo.cargo("build").arg("-v"),
- execs().with_status(0));
- assert_that(&foo.bin("foo"), existing_file());
- assert_that(foo.process(&foo.bin("foo")), execs().with_status(0));
-}
-
-#[test]
-fn recompilation() {
- let git_project = git::new("bar", |project| {
- project
- .file("Cargo.toml", r#"
- [project]
-
- name = "bar"
- version = "0.5.0"
- authors = ["carlhuda@example.com"]
-
- [lib]
- name = "bar"
- "#)
- .file("src/bar.rs", r#"
- pub fn bar() {}
- "#)
- }).unwrap();
-
- let p = project("foo")
- .file("Cargo.toml", &format!(r#"
- [project]
-
- name = "foo"
- version = "0.5.0"
- authors = ["wycats@example.com"]
-
- [dependencies.bar]
-
- version = "0.5.0"
- git = '{}'
- "#, git_project.url()))
- .file("src/main.rs",
- &main_file(r#""{:?}", bar::bar()"#, &["bar"]))
- .build();
-
- // First time around we should compile both foo and bar
- assert_that(p.cargo("build"),
- execs().with_stderr(&format!("[UPDATING] git repository `{}`\n\
- [COMPILING] bar v0.5.0 ({}#[..])\n\
- [COMPILING] foo v0.5.0 ({})\n\
- [FINISHED] dev [unoptimized + debuginfo] target(s) \
- in [..]\n",
- git_project.url(),
- git_project.url(),
- p.url())));
-
- // Don't recompile the second time
- assert_that(p.cargo("build"),
- execs().with_stdout(""));
-
- // Modify a file manually, shouldn't trigger a recompile
- File::create(&git_project.root().join("src/bar.rs")).unwrap().write_all(br#"
- pub fn bar() { println!("hello!"); }
- "#).unwrap();
-
- assert_that(p.cargo("build"),
- execs().with_stdout(""));
-
- assert_that(p.cargo("update"),
- execs().with_stderr(&format!("[UPDATING] git repository `{}`",
- git_project.url())));
-
- assert_that(p.cargo("build"),
- execs().with_stdout(""));
-
- // Commit the changes and make sure we don't trigger a recompile because the
- // lockfile says not to change
- let repo = git2::Repository::open(&git_project.root()).unwrap();
- git::add(&repo);
- git::commit(&repo);
-
- println!("compile after commit");
- assert_that(p.cargo("build"),
- execs().with_stdout(""));
- p.root().move_into_the_past();
-
- // Update the dependency and carry on!
- assert_that(p.cargo("update"),
- execs().with_stderr(&format!("[UPDATING] git repository `{}`\n\
- [UPDATING] bar v0.5.0 ([..]) -> #[..]\n\
- ",
- git_project.url())));
- println!("going for the last compile");
- assert_that(p.cargo("build"),
- execs().with_stderr(&format!("[COMPILING] bar v0.5.0 ({}#[..])\n\
- [COMPILING] foo v0.5.0 ({})\n\
- [FINISHED] dev [unoptimized + debuginfo] target(s) \
- in [..]\n",
- git_project.url(),
- p.url())));
-
- // Make sure clean only cleans one dep
- assert_that(p.cargo("clean")
- .arg("-p").arg("foo"),
- execs().with_stdout(""));
- assert_that(p.cargo("build"),
- execs().with_stderr(&format!("[COMPILING] foo v0.5.0 ({})\n\
- [FINISHED] dev [unoptimized + debuginfo] target(s) \
- in [..]\n",
- p.url())));
-}
-
-#[test]
-fn update_with_shared_deps() {
- let git_project = git::new("bar", |project| {
- project
- .file("Cargo.toml", r#"
- [project]
-
- name = "bar"
- version = "0.5.0"
- authors = ["carlhuda@example.com"]
-
- [lib]
- name = "bar"
- "#)
- .file("src/bar.rs", r#"
- pub fn bar() {}
- "#)
- }).unwrap();
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.5.0"
- authors = ["wycats@example.com"]
-
- [dependencies.dep1]
- path = "dep1"
- [dependencies.dep2]
- path = "dep2"
- "#)
- .file("src/main.rs", r#"
- #[allow(unused_extern_crates)]
- extern crate dep1;
- #[allow(unused_extern_crates)]
- extern crate dep2;
- fn main() {}
- "#)
- .file("dep1/Cargo.toml", &format!(r#"
- [package]
- name = "dep1"
- version = "0.5.0"
- authors = ["wycats@example.com"]
-
- [dependencies.bar]
- version = "0.5.0"
- git = '{}'
- "#, git_project.url()))
- .file("dep1/src/lib.rs", "")
- .file("dep2/Cargo.toml", &format!(r#"
- [package]
- name = "dep2"
- version = "0.5.0"
- authors = ["wycats@example.com"]
-
- [dependencies.bar]
- version = "0.5.0"
- git = '{}'
- "#, git_project.url()))
- .file("dep2/src/lib.rs", "")
- .build();
-
- // First time around we should compile both foo and bar
- assert_that(p.cargo("build"),
- execs().with_stderr(&format!("\
-[UPDATING] git repository `{git}`
-[COMPILING] bar v0.5.0 ({git}#[..])
-[COMPILING] [..] v0.5.0 ([..])
-[COMPILING] [..] v0.5.0 ([..])
-[COMPILING] foo v0.5.0 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]\n",
-git = git_project.url(), dir = p.url())));
-
- // Modify a file manually, and commit it
- File::create(&git_project.root().join("src/bar.rs")).unwrap().write_all(br#"
- pub fn bar() { println!("hello!"); }
- "#).unwrap();
- let repo = git2::Repository::open(&git_project.root()).unwrap();
- let old_head = repo.head().unwrap().target().unwrap();
- git::add(&repo);
- git::commit(&repo);
-
- sleep_ms(1000);
-
- // By default, not transitive updates
- println!("dep1 update");
- assert_that(p.cargo("update")
- .arg("-p").arg("dep1"),
- execs().with_stdout(""));
-
- // Don't do anything bad on a weird --precise argument
- println!("bar bad precise update");
- assert_that(p.cargo("update")
- .arg("-p").arg("bar")
- .arg("--precise").arg("0.1.2"),
- execs().with_status(101).with_stderr("\
-[UPDATING] git repository [..]
-[ERROR] Unable to update [..]
-
-To learn more, run the command again with --verbose.
-"));
-
- // Specifying a precise rev to the old rev shouldn't actually update
- // anything because we already have the rev in the db.
- println!("bar precise update");
- assert_that(p.cargo("update")
- .arg("-p").arg("bar")
- .arg("--precise").arg(&old_head.to_string()),
- execs().with_stdout(""));
-
- // Updating aggressively should, however, update the repo.
- println!("dep1 aggressive update");
- assert_that(p.cargo("update")
- .arg("-p").arg("dep1")
- .arg("--aggressive"),
- execs().with_stderr(&format!("[UPDATING] git repository `{}`\n\
- [UPDATING] bar v0.5.0 ([..]) -> #[..]\n\
- ", git_project.url())));
-
- // Make sure we still only compile one version of the git repo
- println!("build");
- assert_that(p.cargo("build"),
- execs().with_stderr(&format!("\
-[COMPILING] bar v0.5.0 ({git}#[..])
-[COMPILING] [..] v0.5.0 ({dir}[..]dep[..])
-[COMPILING] [..] v0.5.0 ({dir}[..]dep[..])
-[COMPILING] foo v0.5.0 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]\n",
- git = git_project.url(), dir = p.url())));
-
- // We should be able to update transitive deps
- assert_that(p.cargo("update").arg("-p").arg("bar"),
- execs().with_stderr(&format!("[UPDATING] git repository `{}`",
- git_project.url())));
-}
-
-#[test]
-fn dep_with_submodule() {
- let project = project("foo");
- let git_project = git::new("dep1", |project| {
- project
- .file("Cargo.toml", r#"
- [package]
- name = "dep1"
- version = "0.5.0"
- authors = ["carlhuda@example.com"]
- "#)
- }).unwrap();
- let git_project2 = git::new("dep2", |project| {
- project.file("lib.rs", "pub fn dep() {}")
- }).unwrap();
-
- let repo = git2::Repository::open(&git_project.root()).unwrap();
- let url = path2url(git_project2.root()).to_string();
- git::add_submodule(&repo, &url, Path::new("src"));
- git::commit(&repo);
-
- let project = project
- .file("Cargo.toml", &format!(r#"
- [project]
-
- name = "foo"
- version = "0.5.0"
- authors = ["wycats@example.com"]
-
- [dependencies.dep1]
-
- git = '{}'
- "#, git_project.url()))
- .file("src/lib.rs", "
- extern crate dep1;
- pub fn foo() { dep1::dep() }
- ")
- .build();
-
- assert_that(project.cargo("build"),
- execs().with_stderr("\
-[UPDATING] git repository [..]
-[COMPILING] dep1 [..]
-[COMPILING] foo [..]
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]\n").with_status(0));
-}
-
-#[test]
-fn dep_with_bad_submodule() {
- let project = project("foo");
- let git_project = git::new("dep1", |project| {
- project
- .file("Cargo.toml", r#"
- [package]
- name = "dep1"
- version = "0.5.0"
- authors = ["carlhuda@example.com"]
- "#)
- }).unwrap();
- let git_project2 = git::new("dep2", |project| {
- project.file("lib.rs", "pub fn dep() {}")
- }).unwrap();
-
- let repo = git2::Repository::open(&git_project.root()).unwrap();
- let url = path2url(git_project2.root()).to_string();
- git::add_submodule(&repo, &url, Path::new("src"));
- git::commit(&repo);
-
- // now amend the first commit on git_project2 to make submodule ref point to not-found
- // commit
- let repo = git2::Repository::open(&git_project2.root()).unwrap();
- let original_submodule_ref = repo.refname_to_id("refs/heads/master").unwrap();
- let commit = repo.find_commit(original_submodule_ref).unwrap();
- commit.amend(
- Some("refs/heads/master"),
- None,
- None,
- None,
- Some("something something"),
- None).unwrap();
-
- let p = project
- .file("Cargo.toml", &format!(r#"
- [project]
-
- name = "foo"
- version = "0.5.0"
- authors = ["wycats@example.com"]
-
- [dependencies.dep1]
-
- git = '{}'
- "#, git_project.url()))
- .file("src/lib.rs", "
- extern crate dep1;
- pub fn foo() { dep1::dep() }
- ")
- .build();
-
- let expected = format!("\
-[UPDATING] git repository [..]
-[ERROR] failed to load source for a dependency on `dep1`
-
-Caused by:
- Unable to update {}
-
-Caused by:
- failed to update submodule `src`
-
-Caused by:
- object not found - no match for id [..]
-", path2url(git_project.root()));
-
- assert_that(p.cargo("build"),
- execs().with_stderr(expected).with_status(101));
-}
-
-#[test]
-fn two_deps_only_update_one() {
- let project = project("foo");
- let git1 = git::new("dep1", |project| {
- project
- .file("Cargo.toml", r#"
- [package]
- name = "dep1"
- version = "0.5.0"
- authors = ["carlhuda@example.com"]
- "#)
- .file("src/lib.rs", "")
- }).unwrap();
- let git2 = git::new("dep2", |project| {
- project
- .file("Cargo.toml", r#"
- [package]
- name = "dep2"
- version = "0.5.0"
- authors = ["carlhuda@example.com"]
- "#)
- .file("src/lib.rs", "")
- }).unwrap();
-
- let p = project
- .file("Cargo.toml", &format!(r#"
- [project]
-
- name = "foo"
- version = "0.5.0"
- authors = ["wycats@example.com"]
-
- [dependencies.dep1]
- git = '{}'
- [dependencies.dep2]
- git = '{}'
- "#, git1.url(), git2.url()))
- .file("src/main.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("build"),
- execs()
- .with_stderr(&format!("[UPDATING] git repository `[..]`\n\
- [UPDATING] git repository `[..]`\n\
- [COMPILING] [..] v0.5.0 ([..])\n\
- [COMPILING] [..] v0.5.0 ([..])\n\
- [COMPILING] foo v0.5.0 ({})\n\
- [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]\n",
- p.url())));
-
- File::create(&git1.root().join("src/lib.rs")).unwrap().write_all(br#"
- pub fn foo() {}
- "#).unwrap();
- let repo = git2::Repository::open(&git1.root()).unwrap();
- git::add(&repo);
- git::commit(&repo);
-
- assert_that(p.cargo("update")
- .arg("-p").arg("dep1"),
- execs()
- .with_stderr(&format!("[UPDATING] git repository `{}`\n\
- [UPDATING] dep1 v0.5.0 ([..]) -> #[..]\n\
- ", git1.url())));
-}
-
-#[test]
-fn stale_cached_version() {
- let bar = git::new("meta-dep", |project| {
- project.file("Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.0"
- authors = []
- "#)
- .file("src/lib.rs", "pub fn bar() -> i32 { 1 }")
- }).unwrap();
-
- // Update the git database in the cache with the current state of the git
- // repo
- let foo = project("foo")
- .file("Cargo.toml", &format!(r#"
- [project]
- name = "foo"
- version = "0.0.0"
- authors = []
-
- [dependencies.bar]
- git = '{}'
- "#, bar.url()))
- .file("src/main.rs", r#"
- extern crate bar;
-
- fn main() { assert_eq!(bar::bar(), 1) }
- "#)
- .build();
-
- assert_that(foo.cargo("build"), execs().with_status(0));
- assert_that(foo.process(&foo.bin("foo")), execs().with_status(0));
-
- // Update the repo, and simulate someone else updating the lockfile and then
- // us pulling it down.
- File::create(&bar.root().join("src/lib.rs")).unwrap().write_all(br#"
- pub fn bar() -> i32 { 1 + 0 }
- "#).unwrap();
- let repo = git2::Repository::open(&bar.root()).unwrap();
- git::add(&repo);
- git::commit(&repo);
-
- sleep_ms(1000);
-
- let rev = repo.revparse_single("HEAD").unwrap().id();
-
- File::create(&foo.root().join("Cargo.lock")).unwrap().write_all(format!(r#"
- [[package]]
- name = "foo"
- version = "0.0.0"
- dependencies = [
- 'bar 0.0.0 (git+{url}#{hash})'
- ]
-
- [[package]]
- name = "bar"
- version = "0.0.0"
- source = 'git+{url}#{hash}'
- "#, url = bar.url(), hash = rev).as_bytes()).unwrap();
-
- // Now build!
- assert_that(foo.cargo("build"),
- execs().with_status(0)
- .with_stderr(&format!("\
-[UPDATING] git repository `{bar}`
-[COMPILING] bar v0.0.0 ({bar}#[..])
-[COMPILING] foo v0.0.0 ({foo})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-", bar = bar.url(), foo = foo.url())));
- assert_that(foo.process(&foo.bin("foo")), execs().with_status(0));
-}
-
-#[test]
-fn dep_with_changed_submodule() {
- let project = project("foo");
- let git_project = git::new("dep1", |project| {
- project
- .file("Cargo.toml", r#"
- [package]
- name = "dep1"
- version = "0.5.0"
- authors = ["carlhuda@example.com"]
- "#)
- }).unwrap();
-
- let git_project2 = git::new("dep2", |project| {
- project
- .file("lib.rs", "pub fn dep() -> &'static str { \"project2\" }")
- }).unwrap();
-
- let git_project3 = git::new("dep3", |project| {
- project
- .file("lib.rs", "pub fn dep() -> &'static str { \"project3\" }")
- }).unwrap();
-
- let repo = git2::Repository::open(&git_project.root()).unwrap();
- let mut sub = git::add_submodule(&repo, &git_project2.url().to_string(),
- Path::new("src"));
- git::commit(&repo);
-
- let p = project
- .file("Cargo.toml", &format!(r#"
- [project]
- name = "foo"
- version = "0.5.0"
- authors = ["wycats@example.com"]
- [dependencies.dep1]
- git = '{}'
- "#, git_project.url()))
- .file("src/main.rs", "
- extern crate dep1;
- pub fn main() { println!(\"{}\", dep1::dep()) }
- ")
- .build();
-
- println!("first run");
- assert_that(p.cargo("run"), execs()
- .with_stderr("[UPDATING] git repository `[..]`\n\
- [COMPILING] dep1 v0.5.0 ([..])\n\
- [COMPILING] foo v0.5.0 ([..])\n\
- [FINISHED] dev [unoptimized + debuginfo] target(s) in \
- [..]\n\
- [RUNNING] `target[/]debug[/]foo[EXE]`\n")
- .with_stdout("project2\n")
- .with_status(0));
-
- File::create(&git_project.root().join(".gitmodules")).unwrap()
- .write_all(format!("[submodule \"src\"]\n\tpath = src\n\turl={}",
- git_project3.url()).as_bytes()).unwrap();
-
- // Sync the submodule and reset it to the new remote.
- sub.sync().unwrap();
- {
- let subrepo = sub.open().unwrap();
- subrepo.remote_add_fetch("origin",
- "refs/heads/*:refs/heads/*").unwrap();
- subrepo.remote_set_url("origin",
- &git_project3.url().to_string()).unwrap();
- let mut origin = subrepo.find_remote("origin").unwrap();
- origin.fetch(&[], None, None).unwrap();
- let id = subrepo.refname_to_id("refs/remotes/origin/master").unwrap();
- let obj = subrepo.find_object(id, None).unwrap();
- subrepo.reset(&obj, git2::ResetType::Hard, None).unwrap();
- }
- sub.add_to_index(true).unwrap();
- git::add(&repo);
- git::commit(&repo);
-
- sleep_ms(1000);
- // Update the dependency and carry on!
- println!("update");
- assert_that(p.cargo("update").arg("-v"),
- execs()
- .with_stderr("")
- .with_stderr(&format!("[UPDATING] git repository `{}`\n\
- [UPDATING] dep1 v0.5.0 ([..]) -> #[..]\n\
- ", git_project.url())));
-
- println!("last run");
- assert_that(p.cargo("run"), execs()
- .with_stderr("[COMPILING] dep1 v0.5.0 ([..])\n\
- [COMPILING] foo v0.5.0 ([..])\n\
- [FINISHED] dev [unoptimized + debuginfo] target(s) in \
- [..]\n\
- [RUNNING] `target[/]debug[/]foo[EXE]`\n")
- .with_stdout("project3\n")
- .with_status(0));
-}
-
-#[test]
-fn dev_deps_with_testing() {
- let p2 = git::new("bar", |project| {
- project.file("Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.5.0"
- authors = ["wycats@example.com"]
- "#)
- .file("src/lib.rs", r#"
- pub fn gimme() -> &'static str { "zoidberg" }
- "#)
- }).unwrap();
-
- let p = project("foo")
- .file("Cargo.toml", &format!(r#"
- [project]
-
- name = "foo"
- version = "0.5.0"
- authors = ["wycats@example.com"]
-
- [dev-dependencies.bar]
- version = "0.5.0"
- git = '{}'
- "#, p2.url()))
- .file("src/main.rs", r#"
- fn main() {}
-
- #[cfg(test)]
- mod tests {
- extern crate bar;
- #[test] fn foo() { bar::gimme(); }
- }
- "#)
- .build();
-
- // Generate a lockfile which did not use `bar` to compile, but had to update
- // `bar` to generate the lockfile
- assert_that(p.cargo("build"),
- execs().with_stderr(&format!("\
-[UPDATING] git repository `{bar}`
-[COMPILING] foo v0.5.0 ({url})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-", url = p.url(), bar = p2.url())));
-
- // Make sure we use the previous resolution of `bar` instead of updating it
- // a second time.
- assert_that(p.cargo("test"),
- execs().with_stderr("\
-[COMPILING] [..] v0.5.0 ([..])
-[COMPILING] [..] v0.5.0 ([..]
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] target[/]debug[/]deps[/]foo-[..][EXE]")
- .with_stdout_contains("test tests::foo ... ok"));
-}
-
-#[test]
-fn git_build_cmd_freshness() {
- let foo = git::new("foo", |project| {
- project.file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.0"
- authors = []
- build = "build.rs"
- "#)
- .file("build.rs", "fn main() {}")
- .file("src/lib.rs", "pub fn bar() -> i32 { 1 }")
- .file(".gitignore", "
- src/bar.rs
- ")
- }).unwrap();
- foo.root().move_into_the_past();
-
- sleep_ms(1000);
-
- assert_that(foo.cargo("build"),
- execs().with_status(0)
- .with_stderr(&format!("\
-[COMPILING] foo v0.0.0 ({url})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-", url = foo.url())));
-
- // Smoke test to make sure it doesn't compile again
- println!("first pass");
- assert_that(foo.cargo("build"),
- execs().with_status(0)
- .with_stdout(""));
-
- // Modify an ignored file and make sure we don't rebuild
- println!("second pass");
- File::create(&foo.root().join("src/bar.rs")).unwrap();
- assert_that(foo.cargo("build"),
- execs().with_status(0)
- .with_stdout(""));
-}
-
-#[test]
-fn git_name_not_always_needed() {
- let p2 = git::new("bar", |project| {
- project.file("Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.5.0"
- authors = ["wycats@example.com"]
- "#)
- .file("src/lib.rs", r#"
- pub fn gimme() -> &'static str { "zoidberg" }
- "#)
- }).unwrap();
-
- let repo = git2::Repository::open(&p2.root()).unwrap();
- let mut cfg = repo.config().unwrap();
- let _ = cfg.remove("user.name");
- let _ = cfg.remove("user.email");
-
- let p = project("foo")
- .file("Cargo.toml", &format!(r#"
- [project]
- name = "foo"
- version = "0.5.0"
- authors = []
-
- [dev-dependencies.bar]
- git = '{}'
- "#, p2.url()))
- .file("src/main.rs", "fn main() {}")
- .build();
-
- // Generate a lockfile which did not use `bar` to compile, but had to update
- // `bar` to generate the lockfile
- assert_that(p.cargo("build"),
- execs().with_stderr(&format!("\
-[UPDATING] git repository `{bar}`
-[COMPILING] foo v0.5.0 ({url})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-", url = p.url(), bar = p2.url())));
-}
-
-#[test]
-fn git_repo_changing_no_rebuild() {
- let bar = git::new("bar", |project| {
- project.file("Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.5.0"
- authors = ["wycats@example.com"]
- "#)
- .file("src/lib.rs", "pub fn bar() -> i32 { 1 }")
- }).unwrap();
-
- // Lock p1 to the first rev in the git repo
- let p1 = project("p1")
- .file("Cargo.toml", &format!(r#"
- [project]
- name = "p1"
- version = "0.5.0"
- authors = []
- build = 'build.rs'
- [dependencies.bar]
- git = '{}'
- "#, bar.url()))
- .file("src/main.rs", "fn main() {}")
- .file("build.rs", "fn main() {}")
- .build();
- p1.root().move_into_the_past();
- assert_that(p1.cargo("build"),
- execs().with_stderr(&format!("\
-[UPDATING] git repository `{bar}`
-[COMPILING] [..]
-[COMPILING] [..]
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-", bar = bar.url())));
-
- // Make a commit to lock p2 to a different rev
- File::create(&bar.root().join("src/lib.rs")).unwrap().write_all(br#"
- pub fn bar() -> i32 { 2 }
- "#).unwrap();
- let repo = git2::Repository::open(&bar.root()).unwrap();
- git::add(&repo);
- git::commit(&repo);
-
- // Lock p2 to the second rev
- let p2 = project("p2")
- .file("Cargo.toml", &format!(r#"
- [project]
- name = "p2"
- version = "0.5.0"
- authors = []
- [dependencies.bar]
- git = '{}'
- "#, bar.url()))
- .file("src/main.rs", "fn main() {}")
- .build();
- assert_that(p2.cargo("build"),
- execs().with_stderr(&format!("\
-[UPDATING] git repository `{bar}`
-[COMPILING] [..]
-[COMPILING] [..]
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-", bar = bar.url())));
-
- // And now for the real test! Make sure that p1 doesn't get rebuilt
- // even though the git repo has changed.
- assert_that(p1.cargo("build"),
- execs().with_stdout(""));
-}
-
-#[test]
-fn git_dep_build_cmd() {
- let p = git::new("foo", |project| {
- project.file("Cargo.toml", r#"
- [project]
-
- name = "foo"
- version = "0.5.0"
- authors = ["wycats@example.com"]
-
- [dependencies.bar]
-
- version = "0.5.0"
- path = "bar"
-
- [[bin]]
-
- name = "foo"
- "#)
- .file("src/foo.rs",
- &main_file(r#""{}", bar::gimme()"#, &["bar"]))
- .file("bar/Cargo.toml", r#"
- [project]
-
- name = "bar"
- version = "0.5.0"
- authors = ["wycats@example.com"]
- build = "build.rs"
-
- [lib]
- name = "bar"
- path = "src/bar.rs"
- "#)
- .file("bar/src/bar.rs.in", r#"
- pub fn gimme() -> i32 { 0 }
- "#)
- .file("bar/build.rs", r#"
- use std::fs;
- fn main() {
- fs::copy("src/bar.rs.in", "src/bar.rs").unwrap();
- }
- "#)
- }).unwrap();
-
- p.root().join("bar").move_into_the_past();
-
- assert_that(p.cargo("build"),
- execs().with_status(0));
-
- assert_that(process(&p.bin("foo")),
- execs().with_stdout("0\n"));
-
- // Touching bar.rs.in should cause the `build` command to run again.
- fs::File::create(&p.root().join("bar/src/bar.rs.in")).unwrap()
- .write_all(b"pub fn gimme() -> i32 { 1 }").unwrap();
-
- assert_that(p.cargo("build"),
- execs().with_status(0));
-
- assert_that(process(&p.bin("foo")),
- execs().with_stdout("1\n"));
-}
-
-#[test]
-fn fetch_downloads() {
- let bar = git::new("bar", |project| {
- project.file("Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.5.0"
- authors = ["wycats@example.com"]
- "#)
- .file("src/lib.rs", "pub fn bar() -> i32 { 1 }")
- }).unwrap();
-
- let p = project("p1")
- .file("Cargo.toml", &format!(r#"
- [project]
- name = "p1"
- version = "0.5.0"
- authors = []
- [dependencies.bar]
- git = '{}'
- "#, bar.url()))
- .file("src/main.rs", "fn main() {}")
- .build();
- assert_that(p.cargo("fetch"),
- execs().with_status(0).with_stderr(&format!("\
-[UPDATING] git repository `{url}`
-", url = bar.url())));
-
- assert_that(p.cargo("fetch"),
- execs().with_status(0).with_stdout(""));
-}
-
-#[test]
-fn warnings_in_git_dep() {
- let bar = git::new("bar", |project| {
- project.file("Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.5.0"
- authors = ["wycats@example.com"]
- "#)
- .file("src/lib.rs", "fn unused() {}")
- }).unwrap();
-
- let p = project("foo")
- .file("Cargo.toml", &format!(r#"
- [project]
- name = "foo"
- version = "0.5.0"
- authors = []
- [dependencies.bar]
- git = '{}'
- "#, bar.url()))
- .file("src/main.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("build"),
- execs()
- .with_stderr(&format!("[UPDATING] git repository `{}`\n\
- [COMPILING] bar v0.5.0 ({}#[..])\n\
- [COMPILING] foo v0.5.0 ({})\n\
- [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]\n",
- bar.url(),
- bar.url(),
- p.url())));
-}
-
-#[test]
-fn update_ambiguous() {
- let foo1 = git::new("foo1", |project| {
- project.file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.5.0"
- authors = ["wycats@example.com"]
- "#)
- .file("src/lib.rs", "")
- }).unwrap();
- let foo2 = git::new("foo2", |project| {
- project.file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.6.0"
- authors = ["wycats@example.com"]
- "#)
- .file("src/lib.rs", "")
- }).unwrap();
- let bar = git::new("bar", |project| {
- project.file("Cargo.toml", &format!(r#"
- [package]
- name = "bar"
- version = "0.5.0"
- authors = ["wycats@example.com"]
-
- [dependencies.foo]
- git = '{}'
- "#, foo2.url()))
- .file("src/lib.rs", "")
- }).unwrap();
-
- let p = project("project")
- .file("Cargo.toml", &format!(r#"
- [project]
- name = "project"
- version = "0.5.0"
- authors = []
- [dependencies.foo]
- git = '{}'
- [dependencies.bar]
- git = '{}'
- "#, foo1.url(), bar.url()))
- .file("src/main.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("generate-lockfile"), execs().with_status(0));
- assert_that(p.cargo("update")
- .arg("-p").arg("foo"),
- execs().with_status(101)
- .with_stderr("\
-[ERROR] There are multiple `foo` packages in your project, and the specification `foo` \
-is ambiguous.
-Please re-run this command with `-p <spec>` where `<spec>` is one of the \
-following:
- foo:0.[..].0
- foo:0.[..].0
-"));
-}
-
-#[test]
-fn update_one_dep_in_repo_with_many_deps() {
- let foo = git::new("foo", |project| {
- project.file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.5.0"
- authors = ["wycats@example.com"]
- "#)
- .file("src/lib.rs", "")
- .file("a/Cargo.toml", r#"
- [package]
- name = "a"
- version = "0.5.0"
- authors = ["wycats@example.com"]
- "#)
- .file("a/src/lib.rs", "")
- }).unwrap();
-
- let p = project("project")
- .file("Cargo.toml", &format!(r#"
- [project]
- name = "project"
- version = "0.5.0"
- authors = []
- [dependencies.foo]
- git = '{}'
- [dependencies.a]
- git = '{}'
- "#, foo.url(), foo.url()))
- .file("src/main.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("generate-lockfile"), execs().with_status(0));
- assert_that(p.cargo("update")
- .arg("-p").arg("foo"),
- execs().with_status(0)
- .with_stderr(&format!("\
-[UPDATING] git repository `{}`
-", foo.url())));
-}
-
-#[test]
-fn switch_deps_does_not_update_transitive() {
- let transitive = git::new("transitive", |project| {
- project.file("Cargo.toml", r#"
- [package]
- name = "transitive"
- version = "0.5.0"
- authors = ["wycats@example.com"]
- "#)
- .file("src/lib.rs", "")
- }).unwrap();
- let dep1 = git::new("dep1", |project| {
- project.file("Cargo.toml", &format!(r#"
- [package]
- name = "dep"
- version = "0.5.0"
- authors = ["wycats@example.com"]
-
- [dependencies.transitive]
- git = '{}'
- "#, transitive.url()))
- .file("src/lib.rs", "")
- }).unwrap();
- let dep2 = git::new("dep2", |project| {
- project.file("Cargo.toml", &format!(r#"
- [package]
- name = "dep"
- version = "0.5.0"
- authors = ["wycats@example.com"]
-
- [dependencies.transitive]
- git = '{}'
- "#, transitive.url()))
- .file("src/lib.rs", "")
- }).unwrap();
-
- let p = project("project")
- .file("Cargo.toml", &format!(r#"
- [project]
- name = "project"
- version = "0.5.0"
- authors = []
- [dependencies.dep]
- git = '{}'
- "#, dep1.url()))
- .file("src/main.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0)
- .with_stderr(&format!("\
-[UPDATING] git repository `{}`
-[UPDATING] git repository `{}`
-[COMPILING] transitive [..]
-[COMPILING] dep [..]
-[COMPILING] project [..]
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-", dep1.url(), transitive.url())));
-
- // Update the dependency to point to the second repository, but this
- // shouldn't update the transitive dependency which is the same.
- File::create(&p.root().join("Cargo.toml")).unwrap().write_all(format!(r#"
- [project]
- name = "project"
- version = "0.5.0"
- authors = []
- [dependencies.dep]
- git = '{}'
- "#, dep2.url()).as_bytes()).unwrap();
-
- assert_that(p.cargo("build"),
- execs().with_status(0)
- .with_stderr(&format!("\
-[UPDATING] git repository `{}`
-[COMPILING] dep [..]
-[COMPILING] project [..]
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-", dep2.url())));
-}
-
-#[test]
-fn update_one_source_updates_all_packages_in_that_git_source() {
- let dep = git::new("dep", |project| {
- project.file("Cargo.toml", r#"
- [package]
- name = "dep"
- version = "0.5.0"
- authors = []
-
- [dependencies.a]
- path = "a"
- "#)
- .file("src/lib.rs", "")
- .file("a/Cargo.toml", r#"
- [package]
- name = "a"
- version = "0.5.0"
- authors = []
- "#)
- .file("a/src/lib.rs", "")
- }).unwrap();
-
- let p = project("project")
- .file("Cargo.toml", &format!(r#"
- [project]
- name = "project"
- version = "0.5.0"
- authors = []
- [dependencies.dep]
- git = '{}'
- "#, dep.url()))
- .file("src/main.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0));
-
- let repo = git2::Repository::open(&dep.root()).unwrap();
- let rev1 = repo.revparse_single("HEAD").unwrap().id();
-
- // Just be sure to change a file
- File::create(&dep.root().join("src/lib.rs")).unwrap().write_all(br#"
- pub fn bar() -> i32 { 2 }
- "#).unwrap();
- git::add(&repo);
- git::commit(&repo);
-
- assert_that(p.cargo("update").arg("-p").arg("dep"),
- execs().with_status(0));
- let mut lockfile = String::new();
- File::open(&p.root().join("Cargo.lock")).unwrap()
- .read_to_string(&mut lockfile).unwrap();
- assert!(!lockfile.contains(&rev1.to_string()),
- "{} in {}", rev1, lockfile);
-}
-
-#[test]
-fn switch_sources() {
- let a1 = git::new("a1", |project| {
- project.file("Cargo.toml", r#"
- [package]
- name = "a"
- version = "0.5.0"
- authors = []
- "#)
- .file("src/lib.rs", "")
- }).unwrap();
- let a2 = git::new("a2", |project| {
- project.file("Cargo.toml", r#"
- [package]
- name = "a"
- version = "0.5.1"
- authors = []
- "#)
- .file("src/lib.rs", "")
- }).unwrap();
-
- let p = project("project")
- .file("Cargo.toml", r#"
- [project]
- name = "project"
- version = "0.5.0"
- authors = []
- [dependencies.b]
- path = "b"
- "#)
- .file("src/main.rs", "fn main() {}")
- .file("b/Cargo.toml", &format!(r#"
- [project]
- name = "b"
- version = "0.5.0"
- authors = []
- [dependencies.a]
- git = '{}'
- "#, a1.url()))
- .file("b/src/lib.rs", "pub fn main() {}")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0)
- .with_stderr("\
-[UPDATING] git repository `file://[..]a1`
-[COMPILING] a v0.5.0 ([..]a1#[..]
-[COMPILING] b v0.5.0 ([..])
-[COMPILING] project v0.5.0 ([..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-
- File::create(&p.root().join("b/Cargo.toml")).unwrap().write_all(format!(r#"
- [project]
- name = "b"
- version = "0.5.0"
- authors = []
- [dependencies.a]
- git = '{}'
- "#, a2.url()).as_bytes()).unwrap();
-
- assert_that(p.cargo("build"),
- execs().with_status(0)
- .with_stderr("\
-[UPDATING] git repository `file://[..]a2`
-[COMPILING] a v0.5.1 ([..]a2#[..]
-[COMPILING] b v0.5.0 ([..])
-[COMPILING] project v0.5.0 ([..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-}
-
-#[test]
-fn dont_require_submodules_are_checked_out() {
- let p = project("foo").build();
- let git1 = git::new("dep1", |p| {
- p.file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.5.0"
- authors = []
- build = "build.rs"
- "#)
- .file("build.rs", "fn main() {}")
- .file("src/lib.rs", "")
- .file("a/foo", "")
- }).unwrap();
- let git2 = git::new("dep2", |p| p).unwrap();
-
- let repo = git2::Repository::open(&git1.root()).unwrap();
- let url = path2url(git2.root()).to_string();
- git::add_submodule(&repo, &url, Path::new("a/submodule"));
- git::commit(&repo);
-
- git2::Repository::init(&p.root()).unwrap();
- let url = path2url(git1.root()).to_string();
- let dst = paths::home().join("foo");
- git2::Repository::clone(&url, &dst).unwrap();
-
- assert_that(git1.cargo("build").arg("-v").cwd(&dst),
- execs().with_status(0));
-}
-
-#[test]
-fn doctest_same_name() {
- let a2 = git::new("a2", |p| {
- p.file("Cargo.toml", r#"
- [project]
- name = "a"
- version = "0.5.0"
- authors = []
- "#)
- .file("src/lib.rs", "pub fn a2() {}")
- }).unwrap();
-
- let a1 = git::new("a1", |p| {
- p.file("Cargo.toml", &format!(r#"
- [project]
- name = "a"
- version = "0.5.0"
- authors = []
- [dependencies]
- a = {{ git = '{}' }}
- "#, a2.url()))
- .file("src/lib.rs", "extern crate a; pub fn a1() {}")
- }).unwrap();
-
- let p = project("foo")
- .file("Cargo.toml", &format!(r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- a = {{ git = '{}' }}
- "#, a1.url()))
- .file("src/lib.rs", r#"
- #[macro_use]
- extern crate a;
- "#)
- .build();
-
- assert_that(p.cargo("test").arg("-v"),
- execs().with_status(0));
-}
-
-#[test]
-fn lints_are_suppressed() {
- let a = git::new("a", |p| {
- p.file("Cargo.toml", r#"
- [project]
- name = "a"
- version = "0.5.0"
- authors = []
- "#)
- .file("src/lib.rs", "
- use std::option;
- ")
- }).unwrap();
-
- let p = project("foo")
- .file("Cargo.toml", &format!(r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- a = {{ git = '{}' }}
- "#, a.url()))
- .file("src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr("\
-[UPDATING] git repository `[..]`
-[COMPILING] a v0.5.0 ([..])
-[COMPILING] foo v0.0.1 ([..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-}
-
-#[test]
-fn denied_lints_are_allowed() {
- let a = git::new("a", |p| {
- p.file("Cargo.toml", r#"
- [project]
- name = "a"
- version = "0.5.0"
- authors = []
- "#)
- .file("src/lib.rs", "
- #![deny(warnings)]
- use std::option;
- ")
- }).unwrap();
-
- let p = project("foo")
- .file("Cargo.toml", &format!(r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- a = {{ git = '{}' }}
- "#, a.url()))
- .file("src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr("\
-[UPDATING] git repository `[..]`
-[COMPILING] a v0.5.0 ([..])
-[COMPILING] foo v0.0.1 ([..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-}
-
-#[test]
-fn add_a_git_dep() {
- let git = git::new("git", |p| {
- p.file("Cargo.toml", r#"
- [project]
- name = "git"
- version = "0.5.0"
- authors = []
- "#)
- .file("src/lib.rs", "")
- }).unwrap();
-
- let p = project("foo")
- .file("Cargo.toml", &format!(r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- a = {{ path = 'a' }}
- git = {{ git = '{}' }}
- "#, git.url()))
- .file("src/lib.rs", "")
- .file("a/Cargo.toml", r#"
- [package]
- name = "a"
- version = "0.0.1"
- authors = []
- "#)
- .file("a/src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build"), execs().with_status(0));
-
- File::create(p.root().join("a/Cargo.toml")).unwrap().write_all(format!(r#"
- [package]
- name = "a"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- git = {{ git = '{}' }}
- "#, git.url()).as_bytes()).unwrap();
-
- assert_that(p.cargo("build"), execs().with_status(0));
-}
-
-#[test]
-fn two_at_rev_instead_of_tag() {
- let git = git::new("git", |p| {
- p.file("Cargo.toml", r#"
- [project]
- name = "git1"
- version = "0.5.0"
- authors = []
- "#)
- .file("src/lib.rs", "")
- .file("a/Cargo.toml", r#"
- [project]
- name = "git2"
- version = "0.5.0"
- authors = []
- "#)
- .file("a/src/lib.rs", "")
- }).unwrap();
-
- // Make a tag corresponding to the current HEAD
- let repo = git2::Repository::open(&git.root()).unwrap();
- let head = repo.head().unwrap().target().unwrap();
- repo.tag("v0.1.0",
- &repo.find_object(head, None).unwrap(),
- &repo.signature().unwrap(),
- "make a new tag",
- false).unwrap();
-
- let p = project("foo")
- .file("Cargo.toml", &format!(r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- git1 = {{ git = '{0}', rev = 'v0.1.0' }}
- git2 = {{ git = '{0}', rev = 'v0.1.0' }}
- "#, git.url()))
- .file("src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("generate-lockfile"), execs().with_status(0));
- assert_that(p.cargo("build").arg("-v"), execs().with_status(0));
-}
-
-#[test]
-#[ignore] // accesses crates.io
-fn include_overrides_gitignore() {
- let p = git::new("reduction", |repo| {
- repo.file("Cargo.toml", r#"
- [package]
- name = "reduction"
- version = "0.5.0"
- authors = ["pnkfelix"]
- build = "tango-build.rs"
- include = ["src/lib.rs", "src/incl.rs", "src/mod.md", "tango-build.rs", "Cargo.toml"]
-
- [build-dependencies]
- filetime = "0.1"
- "#)
- .file(".gitignore", r#"
- target
- Cargo.lock
- # Below files represent generated code, thus not managed by `git`
- src/incl.rs
- src/not_incl.rs
- "#)
- .file("tango-build.rs", r#"
- extern crate filetime;
- use filetime::FileTime;
- use std::fs::{self, File};
-
- fn main() {
- // generate files, or bring their timestamps into sync.
- let source = "src/mod.md";
-
- let metadata = fs::metadata(source).unwrap();
- let mtime = FileTime::from_last_modification_time(&metadata);
- let atime = FileTime::from_last_access_time(&metadata);
-
- // sync time stamps for generated files with time stamp of source file.
-
- let files = ["src/not_incl.rs", "src/incl.rs"];
- for file in files.iter() {
- File::create(file).unwrap();
- filetime::set_file_times(file, atime, mtime).unwrap();
- }
- }
- "#)
- .file("src/lib.rs", r#"
- mod not_incl;
- mod incl;
- "#)
- .file("src/mod.md", r#"
- (The content of this file does not matter since we are not doing real codegen.)
- "#)
- }).unwrap();
-
- println!("build 1: all is new");
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(0)
- .with_stderr("\
-[UPDATING] registry `[..]`
-[DOWNLOADING] filetime [..]
-[DOWNLOADING] libc [..]
-[COMPILING] libc [..]
-[RUNNING] `rustc --crate-name libc [..]`
-[COMPILING] filetime [..]
-[RUNNING] `rustc --crate-name filetime [..]`
-[COMPILING] reduction [..]
-[RUNNING] `rustc --crate-name build_script_tango_build tango-build.rs --crate-type bin [..]`
-[RUNNING] `[..][/]build-script-tango-build`
-[RUNNING] `rustc --crate-name reduction src[/]lib.rs --crate-type lib [..]`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-
- println!("build 2: nothing changed; file timestamps reset by build script");
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(0)
- .with_stderr("\
-[FRESH] libc [..]
-[FRESH] filetime [..]
-[FRESH] reduction [..]
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-
- println!("build 3: touch `src/not_incl.rs`; expect build script *not* re-run");
- sleep_ms(1000);
- File::create(p.root().join("src").join("not_incl.rs")).unwrap();
-
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(0)
- .with_stderr("\
-[FRESH] libc [..]
-[FRESH] filetime [..]
-[COMPILING] reduction [..]
-[RUNNING] `rustc --crate-name reduction src[/]lib.rs --crate-type lib [..]`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-
- // This final case models the bug from rust-lang/cargo#4135: an
- // explicitly included file should cause a build-script re-run,
- // even if that same file is matched by `.gitignore`.
- println!("build 4: touch `src/incl.rs`; expect build script re-run");
- sleep_ms(1000);
- File::create(p.root().join("src").join("incl.rs")).unwrap();
-
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(0)
- .with_stderr("\
-[FRESH] libc [..]
-[FRESH] filetime [..]
-[COMPILING] reduction [..]
-[RUNNING] `[..][/]build-script-tango-build`
-[RUNNING] `rustc --crate-name reduction src[/]lib.rs --crate-type lib [..]`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-}
-
-#[test]
-fn invalid_git_dependency_manifest() {
- let project = project("foo");
- let git_project = git::new("dep1", |project| {
- project
- .file("Cargo.toml", r#"
- [project]
-
- name = "dep1"
- version = "0.5.0"
- authors = ["carlhuda@example.com"]
- categories = ["algorithms"]
- categories = ["algorithms"]
-
- [lib]
-
- name = "dep1"
- "#)
- .file("src/dep1.rs", r#"
- pub fn hello() -> &'static str {
- "hello world"
- }
- "#)
- }).unwrap();
-
- let project = project
- .file("Cargo.toml", &format!(r#"
- [project]
-
- name = "foo"
- version = "0.5.0"
- authors = ["wycats@example.com"]
-
- [dependencies.dep1]
-
- git = '{}'
- "#, git_project.url()))
- .file("src/main.rs", &main_file(r#""{}", dep1::hello()"#, &["dep1"]))
- .build();
-
- let git_root = git_project.root();
-
- assert_that(project.cargo("build"),
- execs()
- .with_stderr(&format!("[UPDATING] git repository `{}`\n\
- error: failed to load source for a dependency on `dep1`\n\
- \n\
- Caused by:\n \
- Unable to update {}\n\
- \n\
- Caused by:\n \
- failed to parse manifest at `[..]`\n\
- \n\
- Caused by:\n \
- could not parse input as TOML\n\
- \n\
- Caused by:\n \
- duplicate key: `categories` for key `project`",
- path2url(git_root.clone()),
- path2url(git_root),
- )));
-}
-
-#[test]
-fn failed_submodule_checkout() {
- let project = project("foo");
- let git_project = git::new("dep1", |project| {
- project
- .file("Cargo.toml", r#"
- [package]
- name = "dep1"
- version = "0.5.0"
- authors = [""]
- "#)
- }).unwrap();
-
- let git_project2 = git::new("dep2", |project| {
- project.file("lib.rs", "")
- }).unwrap();
-
- let listener = TcpListener::bind("127.0.0.1:0").unwrap();
- let addr = listener.local_addr().unwrap();
- let done = Arc::new(AtomicBool::new(false));
- let done2 = done.clone();
-
- let t = thread::spawn(move || {
- while !done2.load(Ordering::SeqCst) {
- if let Ok((mut socket, _)) = listener.accept() {
- drop(socket.write_all(b"foo\r\n"));
- }
- }
- });
-
- let repo = git2::Repository::open(&git_project2.root()).unwrap();
- let url = format!("http://{}:{}/", addr.ip(), addr.port());
- {
- let mut s = repo.submodule(&url, Path::new("bar"), false).unwrap();
- let subrepo = s.open().unwrap();
- let mut cfg = subrepo.config().unwrap();
- cfg.set_str("user.email", "foo@bar.com").unwrap();
- cfg.set_str("user.name", "Foo Bar").unwrap();
- git::commit(&subrepo);
- s.add_finalize().unwrap();
- }
- git::commit(&repo);
- drop((repo, url));
-
- let repo = git2::Repository::open(&git_project.root()).unwrap();
- let url = path2url(git_project2.root()).to_string();
- git::add_submodule(&repo, &url, Path::new("src"));
- git::commit(&repo);
- drop(repo);
-
- let project = project
- .file("Cargo.toml", &format!(r#"
- [project]
- name = "foo"
- version = "0.5.0"
- authors = []
-
- [dependencies]
- dep1 = {{ git = '{}' }}
- "#, git_project.url()))
- .file("src/lib.rs", "")
- .build();
-
- assert_that(project.cargo("build"),
- execs().with_status(101)
- .with_stderr_contains(" failed to update submodule `src`")
- .with_stderr_contains(" failed to update submodule `bar`"));
- assert_that(project.cargo("build"),
- execs().with_status(101)
- .with_stderr_contains(" failed to update submodule `src`")
- .with_stderr_contains(" failed to update submodule `bar`"));
-
- done.store(true, Ordering::SeqCst);
- drop(TcpStream::connect(&addr));
- t.join().unwrap();
-}
+++ /dev/null
-extern crate cargotest;
-extern crate cargo;
-extern crate tempdir;
-extern crate hamcrest;
-
-use std::fs::{self, File};
-use std::io::prelude::*;
-use std::env;
-
-use cargo::util::ProcessBuilder;
-use cargotest::support::{execs, paths, cargo_exe};
-use hamcrest::{assert_that, existing_file, existing_dir, is_not};
-use tempdir::TempDir;
-
-fn cargo_process(s: &str) -> ProcessBuilder {
- let mut p = cargotest::process(&cargo_exe());
- p.arg(s).cwd(&paths::root()).env("HOME", &paths::home());
- p
-}
-
-#[test]
-fn simple_lib() {
- assert_that(cargo_process("init").arg("--lib").arg("--vcs").arg("none")
- .env("USER", "foo"),
- execs().with_status(0).with_stderr("\
-[CREATED] library project
-"));
-
- assert_that(&paths::root().join("Cargo.toml"), existing_file());
- assert_that(&paths::root().join("src/lib.rs"), existing_file());
- assert_that(&paths::root().join(".gitignore"), is_not(existing_file()));
-
- assert_that(cargo_process("build"),
- execs().with_status(0));
-}
-
-#[test]
-fn simple_bin() {
- let path = paths::root().join("foo");
- fs::create_dir(&path).unwrap();
- assert_that(cargo_process("init").arg("--bin").arg("--vcs").arg("none")
- .env("USER", "foo").cwd(&path),
- execs().with_status(0).with_stderr("\
-[CREATED] binary (application) project
-"));
-
- assert_that(&paths::root().join("foo/Cargo.toml"), existing_file());
- assert_that(&paths::root().join("foo/src/main.rs"), existing_file());
-
- assert_that(cargo_process("build").cwd(&path),
- execs().with_status(0));
- assert_that(&paths::root().join(&format!("foo/target/debug/foo{}",
- env::consts::EXE_SUFFIX)),
- existing_file());
-}
-
-#[test]
-fn both_lib_and_bin() {
- let td = TempDir::new("cargo").unwrap();
- assert_that(cargo_process("init").arg("--lib").arg("--bin").cwd(td.path())
- .env("USER", "foo"),
- execs().with_status(101).with_stderr(
- "[ERROR] can't specify both lib and binary outputs"));
-}
-
-fn bin_already_exists(explicit: bool, rellocation: &str) {
- let path = paths::root().join("foo");
- fs::create_dir_all(&path.join("src")).unwrap();
-
- let sourcefile_path = path.join(rellocation);
-
- let content = br#"
- fn main() {
- println!("Hello, world 2!");
- }
- "#;
-
- File::create(&sourcefile_path).unwrap().write_all(content).unwrap();
-
- if explicit {
- assert_that(cargo_process("init").arg("--bin").arg("--vcs").arg("none")
- .env("USER", "foo").cwd(&path),
- execs().with_status(0));
- } else {
- assert_that(cargo_process("init").arg("--vcs").arg("none")
- .env("USER", "foo").cwd(&path),
- execs().with_status(0));
- }
-
- assert_that(&paths::root().join("foo/Cargo.toml"), existing_file());
- assert_that(&paths::root().join("foo/src/lib.rs"), is_not(existing_file()));
-
- // Check that our file is not overwritten
- let mut new_content = Vec::new();
- File::open(&sourcefile_path).unwrap().read_to_end(&mut new_content).unwrap();
- assert_eq!(Vec::from(content as &[u8]), new_content);
-}
-
-#[test]
-fn bin_already_exists_explicit() {
- bin_already_exists(true, "src/main.rs")
-}
-
-#[test]
-fn bin_already_exists_implicit() {
- bin_already_exists(false, "src/main.rs")
-}
-
-#[test]
-fn bin_already_exists_explicit_nosrc() {
- bin_already_exists(true, "main.rs")
-}
-
-#[test]
-fn bin_already_exists_implicit_nosrc() {
- bin_already_exists(false, "main.rs")
-}
-
-#[test]
-fn bin_already_exists_implicit_namenosrc() {
- bin_already_exists(false, "foo.rs")
-}
-
-#[test]
-fn bin_already_exists_implicit_namesrc() {
- bin_already_exists(false, "src/foo.rs")
-}
-
-#[test]
-fn confused_by_multiple_lib_files() {
- let path = paths::root().join("foo");
- fs::create_dir_all(&path.join("src")).unwrap();
-
- let sourcefile_path1 = path.join("src/lib.rs");
-
- File::create(&sourcefile_path1).unwrap().write_all(br#"
- fn qqq () {
- println!("Hello, world 2!");
- }
- "#).unwrap();
-
- let sourcefile_path2 = path.join("lib.rs");
-
- File::create(&sourcefile_path2).unwrap().write_all(br#"
- fn qqq () {
- println!("Hello, world 3!");
- }
- "#).unwrap();
-
- assert_that(cargo_process("init").arg("--vcs").arg("none")
- .env("USER", "foo").cwd(&path),
- execs().with_status(101).with_stderr("\
-[ERROR] cannot have a project with multiple libraries, found both `src/lib.rs` and `lib.rs`
-"));
-
- assert_that(&paths::root().join("foo/Cargo.toml"), is_not(existing_file()));
-}
-
-
-#[test]
-fn multibin_project_name_clash() {
- let path = paths::root().join("foo");
- fs::create_dir(&path).unwrap();
-
- let sourcefile_path1 = path.join("foo.rs");
-
- File::create(&sourcefile_path1).unwrap().write_all(br#"
- fn main () {
- println!("Hello, world 2!");
- }
- "#).unwrap();
-
- let sourcefile_path2 = path.join("main.rs");
-
- File::create(&sourcefile_path2).unwrap().write_all(br#"
- fn main () {
- println!("Hello, world 3!");
- }
- "#).unwrap();
-
- assert_that(cargo_process("init").arg("--lib").arg("--vcs").arg("none")
- .env("USER", "foo").cwd(&path),
- execs().with_status(101).with_stderr("\
-[ERROR] multiple possible binary sources found:
- main.rs
- foo.rs
-cannot automatically generate Cargo.toml as the main target would be ambiguous
-"));
-
- assert_that(&paths::root().join("foo/Cargo.toml"), is_not(existing_file()));
-}
-
-fn lib_already_exists(rellocation: &str) {
- let path = paths::root().join("foo");
- fs::create_dir_all(&path.join("src")).unwrap();
-
- let sourcefile_path = path.join(rellocation);
-
- let content = br#"
- pub fn qqq() {}
- "#;
-
- File::create(&sourcefile_path).unwrap().write_all(content).unwrap();
-
- assert_that(cargo_process("init").arg("--vcs").arg("none")
- .env("USER", "foo").cwd(&path),
- execs().with_status(0));
-
- assert_that(&paths::root().join("foo/Cargo.toml"), existing_file());
- assert_that(&paths::root().join("foo/src/main.rs"), is_not(existing_file()));
-
- // Check that our file is not overwritten
- let mut new_content = Vec::new();
- File::open(&sourcefile_path).unwrap().read_to_end(&mut new_content).unwrap();
- assert_eq!(Vec::from(content as &[u8]), new_content);
-}
-
-#[test]
-fn lib_already_exists_src() {
- lib_already_exists("src/lib.rs")
-}
-
-#[test]
-fn lib_already_exists_nosrc() {
- lib_already_exists("lib.rs")
-}
-
-#[test]
-fn simple_git() {
- assert_that(cargo_process("init").arg("--lib")
- .arg("--vcs")
- .arg("git")
- .env("USER", "foo"),
- execs().with_status(0));
-
- assert_that(&paths::root().join("Cargo.toml"), existing_file());
- assert_that(&paths::root().join("src/lib.rs"), existing_file());
- assert_that(&paths::root().join(".git"), existing_dir());
- assert_that(&paths::root().join(".gitignore"), existing_file());
-}
-
-#[test]
-fn auto_git() {
- let td = TempDir::new("cargo").unwrap();
- let foo = &td.path().join("foo");
- fs::create_dir_all(&foo).unwrap();
- assert_that(cargo_process("init").arg("--lib")
- .cwd(foo.clone())
- .env("USER", "foo"),
- execs().with_status(0));
-
- assert_that(&foo.join("Cargo.toml"), existing_file());
- assert_that(&foo.join("src/lib.rs"), existing_file());
- assert_that(&foo.join(".git"), existing_dir());
- assert_that(&foo.join(".gitignore"), existing_file());
-}
-
-#[test]
-fn invalid_dir_name() {
- let foo = &paths::root().join("foo.bar");
- fs::create_dir_all(&foo).unwrap();
- assert_that(cargo_process("init").cwd(foo.clone())
- .env("USER", "foo"),
- execs().with_status(101).with_stderr("\
-[ERROR] Invalid character `.` in crate name: `foo.bar`
-use --name to override crate name
-"));
-
- assert_that(&foo.join("Cargo.toml"), is_not(existing_file()));
-}
-
-#[test]
-fn reserved_name() {
- let test = &paths::root().join("test");
- fs::create_dir_all(&test).unwrap();
- assert_that(cargo_process("init").cwd(test.clone())
- .env("USER", "foo"),
- execs().with_status(101).with_stderr("\
-[ERROR] The name `test` cannot be used as a crate name\n\
-use --name to override crate name
-"));
-
- assert_that(&test.join("Cargo.toml"), is_not(existing_file()));
-}
-
-#[test]
-fn git_autodetect() {
- fs::create_dir(&paths::root().join(".git")).unwrap();
-
- assert_that(cargo_process("init").arg("--lib")
- .env("USER", "foo"),
- execs().with_status(0));
-
-
- assert_that(&paths::root().join("Cargo.toml"), existing_file());
- assert_that(&paths::root().join("src/lib.rs"), existing_file());
- assert_that(&paths::root().join(".git"), existing_dir());
- assert_that(&paths::root().join(".gitignore"), existing_file());
-}
-
-
-#[test]
-fn mercurial_autodetect() {
- fs::create_dir(&paths::root().join(".hg")).unwrap();
-
- assert_that(cargo_process("init").arg("--lib")
- .env("USER", "foo"),
- execs().with_status(0));
-
-
- assert_that(&paths::root().join("Cargo.toml"), existing_file());
- assert_that(&paths::root().join("src/lib.rs"), existing_file());
- assert_that(&paths::root().join(".git"), is_not(existing_dir()));
- assert_that(&paths::root().join(".hgignore"), existing_file());
-}
-
-#[test]
-fn gitignore_appended_not_replaced() {
- fs::create_dir(&paths::root().join(".git")).unwrap();
-
- File::create(&paths::root().join(".gitignore")).unwrap().write_all(b"qqqqqq\n").unwrap();
-
- assert_that(cargo_process("init").arg("--lib")
- .env("USER", "foo"),
- execs().with_status(0));
-
-
- assert_that(&paths::root().join("Cargo.toml"), existing_file());
- assert_that(&paths::root().join("src/lib.rs"), existing_file());
- assert_that(&paths::root().join(".git"), existing_dir());
- assert_that(&paths::root().join(".gitignore"), existing_file());
-
- let mut contents = String::new();
- File::open(&paths::root().join(".gitignore")).unwrap().read_to_string(&mut contents).unwrap();
- assert!(contents.contains(r#"qqqqqq"#));
-}
-
-#[test]
-fn gitignore_added_newline_if_required() {
- fs::create_dir(&paths::root().join(".git")).unwrap();
-
- File::create(&paths::root().join(".gitignore")).unwrap().write_all(b"first").unwrap();
-
- assert_that(cargo_process("init").arg("--lib")
- .env("USER", "foo"),
- execs().with_status(0));
-
- assert_that(&paths::root().join(".gitignore"), existing_file());
-
- let mut contents = String::new();
- File::open(&paths::root().join(".gitignore")).unwrap().read_to_string(&mut contents).unwrap();
- assert!(contents.starts_with("first\n"));
-}
-
-#[test]
-fn mercurial_added_newline_if_required() {
- fs::create_dir(&paths::root().join(".hg")).unwrap();
-
- File::create(&paths::root().join(".hgignore")).unwrap().write_all(b"first").unwrap();
-
- assert_that(cargo_process("init").arg("--lib")
- .env("USER", "foo"),
- execs().with_status(0));
-
- assert_that(&paths::root().join(".hgignore"), existing_file());
-
- let mut contents = String::new();
- File::open(&paths::root().join(".hgignore")).unwrap().read_to_string(&mut contents).unwrap();
- assert!(contents.starts_with("first\n"));
-}
-
-#[test]
-fn cargo_lock_gitignored_if_lib1() {
- fs::create_dir(&paths::root().join(".git")).unwrap();
-
- assert_that(cargo_process("init").arg("--lib").arg("--vcs").arg("git")
- .env("USER", "foo"),
- execs().with_status(0));
-
- assert_that(&paths::root().join(".gitignore"), existing_file());
-
- let mut contents = String::new();
- File::open(&paths::root().join(".gitignore")).unwrap().read_to_string(&mut contents).unwrap();
- assert!(contents.contains(r#"Cargo.lock"#));
-}
-
-#[test]
-fn cargo_lock_gitignored_if_lib2() {
- fs::create_dir(&paths::root().join(".git")).unwrap();
-
- File::create(&paths::root().join("lib.rs")).unwrap().write_all(br#""#).unwrap();
-
- assert_that(cargo_process("init").arg("--vcs").arg("git")
- .env("USER", "foo"),
- execs().with_status(0));
-
- assert_that(&paths::root().join(".gitignore"), existing_file());
-
- let mut contents = String::new();
- File::open(&paths::root().join(".gitignore")).unwrap().read_to_string(&mut contents).unwrap();
- assert!(contents.contains(r#"Cargo.lock"#));
-}
-
-#[test]
-fn cargo_lock_not_gitignored_if_bin1() {
- fs::create_dir(&paths::root().join(".git")).unwrap();
-
- assert_that(cargo_process("init").arg("--vcs").arg("git")
- .arg("--bin")
- .env("USER", "foo"),
- execs().with_status(0));
-
- assert_that(&paths::root().join(".gitignore"), existing_file());
-
- let mut contents = String::new();
- File::open(&paths::root().join(".gitignore")).unwrap().read_to_string(&mut contents).unwrap();
- assert!(!contents.contains(r#"Cargo.lock"#));
-}
-
-#[test]
-fn cargo_lock_not_gitignored_if_bin2() {
- fs::create_dir(&paths::root().join(".git")).unwrap();
-
- File::create(&paths::root().join("main.rs")).unwrap().write_all(br#""#).unwrap();
-
- assert_that(cargo_process("init").arg("--vcs").arg("git")
- .env("USER", "foo"),
- execs().with_status(0));
-
- assert_that(&paths::root().join(".gitignore"), existing_file());
-
- let mut contents = String::new();
- File::open(&paths::root().join(".gitignore")).unwrap().read_to_string(&mut contents).unwrap();
- assert!(!contents.contains(r#"Cargo.lock"#));
-}
-
-#[test]
-fn with_argument() {
- assert_that(cargo_process("init").arg("foo").arg("--vcs").arg("none")
- .env("USER", "foo"),
- execs().with_status(0));
- assert_that(&paths::root().join("foo/Cargo.toml"), existing_file());
-}
-
-
-#[test]
-fn unknown_flags() {
- assert_that(cargo_process("init").arg("foo").arg("--flag"),
- execs().with_status(1)
- .with_stderr("\
-[ERROR] Unknown flag: '--flag'
-
-Usage:
- cargo init [options] [<path>]
- cargo init -h | --help
-"));
-}
-
-#[cfg(not(windows))]
-#[test]
-fn no_filename() {
- assert_that(cargo_process("init").arg("/"),
- execs().with_status(101)
- .with_stderr("\
-[ERROR] cannot auto-detect project name from path \"/\" ; use --name to override
-".to_string()));
-}
+++ /dev/null
-extern crate cargo;
-extern crate cargotest;
-extern crate hamcrest;
-
-use std::fs::{self, File, OpenOptions};
-use std::io::prelude::*;
-
-use cargo::util::ProcessBuilder;
-use cargotest::install::{cargo_home, has_installed_exe};
-use cargotest::support::git;
-use cargotest::support::paths;
-use cargotest::support::registry::Package;
-use cargotest::support::{project, execs};
-use hamcrest::{assert_that, existing_dir, is_not};
-
-fn cargo_process(s: &str) -> ProcessBuilder {
- let mut p = cargotest::cargo_process();
- p.arg(s);
- p
-}
-
-fn pkg(name: &str, vers: &str) {
- Package::new(name, vers)
- .file("src/lib.rs", "")
- .file("src/main.rs", &format!("
- extern crate {};
- fn main() {{}}
- ", name))
- .publish();
-}
-
-#[test]
-fn simple() {
- pkg("foo", "0.0.1");
-
- assert_that(cargo_process("install").arg("foo"),
- execs().with_status(0).with_stderr(&format!("\
-[UPDATING] registry `[..]`
-[DOWNLOADING] foo v0.0.1 (registry [..])
-[INSTALLING] foo v0.0.1
-[COMPILING] foo v0.0.1
-[FINISHED] release [optimized] target(s) in [..]
-[INSTALLING] {home}[..]bin[..]foo[..]
-warning: be sure to add `[..]` to your PATH to be able to run the installed binaries
-",
- home = cargo_home().display())));
- assert_that(cargo_home(), has_installed_exe("foo"));
-
- assert_that(cargo_process("uninstall").arg("foo"),
- execs().with_status(0).with_stderr(&format!("\
-[REMOVING] {home}[..]bin[..]foo[..]
-",
- home = cargo_home().display())));
- assert_that(cargo_home(), is_not(has_installed_exe("foo")));
-}
-
-#[test]
-fn multiple_pkgs() {
- pkg("foo", "0.0.1");
- pkg("bar", "0.0.2");
-
- assert_that(cargo_process("install").args(&["foo", "bar", "baz"]),
- execs().with_status(101).with_stderr(&format!("\
-[UPDATING] registry `[..]`
-[DOWNLOADING] foo v0.0.1 (registry `file://[..]`)
-[INSTALLING] foo v0.0.1
-[COMPILING] foo v0.0.1
-[FINISHED] release [optimized] target(s) in [..]
-[INSTALLING] {home}[..]bin[..]foo[..]
-[DOWNLOADING] bar v0.0.2 (registry `file://[..]`)
-[INSTALLING] bar v0.0.2
-[COMPILING] bar v0.0.2
-[FINISHED] release [optimized] target(s) in [..]
-[INSTALLING] {home}[..]bin[..]bar[..]
-error: could not find `baz` in registry `[..]`
-[SUMMARY] Successfully installed foo, bar! Failed to install baz (see error(s) above).
-warning: be sure to add `[..]` to your PATH to be able to run the installed binaries
-error: some crates failed to install
-",
- home = cargo_home().display())));
- assert_that(cargo_home(), has_installed_exe("foo"));
- assert_that(cargo_home(), has_installed_exe("bar"));
-
- assert_that(cargo_process("uninstall").args(&["foo", "bar"]),
- execs().with_status(0).with_stderr(&format!("\
-[REMOVING] {home}[..]bin[..]foo[..]
-[REMOVING] {home}[..]bin[..]bar[..]
-[SUMMARY] Successfully uninstalled foo, bar!
-",
- home = cargo_home().display())));
-
- assert_that(cargo_home(), is_not(has_installed_exe("foo")));
- assert_that(cargo_home(), is_not(has_installed_exe("bar")));
-}
-
-#[test]
-fn pick_max_version() {
- pkg("foo", "0.0.1");
- pkg("foo", "0.0.2");
-
- assert_that(cargo_process("install").arg("foo"),
- execs().with_status(0).with_stderr(&format!("\
-[UPDATING] registry `[..]`
-[DOWNLOADING] foo v0.0.2 (registry [..])
-[INSTALLING] foo v0.0.2
-[COMPILING] foo v0.0.2
-[FINISHED] release [optimized] target(s) in [..]
-[INSTALLING] {home}[..]bin[..]foo[..]
-warning: be sure to add `[..]` to your PATH to be able to run the installed binaries
-",
- home = cargo_home().display())));
- assert_that(cargo_home(), has_installed_exe("foo"));
-}
-
-#[test]
-fn missing() {
- pkg("foo", "0.0.1");
- assert_that(cargo_process("install").arg("bar"),
- execs().with_status(101).with_stderr("\
-[UPDATING] registry [..]
-[ERROR] could not find `bar` in registry `[..]`
-"));
-}
-
-#[test]
-fn bad_version() {
- pkg("foo", "0.0.1");
- assert_that(cargo_process("install").arg("foo").arg("--vers=0.2.0"),
- execs().with_status(101).with_stderr("\
-[UPDATING] registry [..]
-[ERROR] could not find `foo` in registry `[..]` with version `=0.2.0`
-"));
-}
-
-#[test]
-fn no_crate() {
- assert_that(cargo_process("install"),
- execs().with_status(101).with_stderr("\
-[ERROR] `[..]` is not a crate root; specify a crate to install [..]
-
-Caused by:
- failed to read `[..]Cargo.toml`
-
-Caused by:
- [..] (os error [..])
-"));
-}
-
-#[test]
-fn install_location_precedence() {
- pkg("foo", "0.0.1");
-
- let root = paths::root();
- let t1 = root.join("t1");
- let t2 = root.join("t2");
- let t3 = root.join("t3");
- let t4 = cargo_home();
-
- fs::create_dir(root.join(".cargo")).unwrap();
- File::create(root.join(".cargo/config")).unwrap().write_all(format!("\
- [install]
- root = '{}'
- ", t3.display()).as_bytes()).unwrap();
-
- println!("install --root");
-
- assert_that(cargo_process("install").arg("foo")
- .arg("--root").arg(&t1)
- .env("CARGO_INSTALL_ROOT", &t2),
- execs().with_status(0));
- assert_that(&t1, has_installed_exe("foo"));
- assert_that(&t2, is_not(has_installed_exe("foo")));
-
- println!("install CARGO_INSTALL_ROOT");
-
- assert_that(cargo_process("install").arg("foo")
- .env("CARGO_INSTALL_ROOT", &t2),
- execs().with_status(0));
- assert_that(&t2, has_installed_exe("foo"));
- assert_that(&t3, is_not(has_installed_exe("foo")));
-
- println!("install install.root");
-
- assert_that(cargo_process("install").arg("foo"),
- execs().with_status(0));
- assert_that(&t3, has_installed_exe("foo"));
- assert_that(&t4, is_not(has_installed_exe("foo")));
-
- fs::remove_file(root.join(".cargo/config")).unwrap();
-
- println!("install cargo home");
-
- assert_that(cargo_process("install").arg("foo"),
- execs().with_status(0));
- assert_that(&t4, has_installed_exe("foo"));
-}
-
-#[test]
-fn install_path() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- assert_that(cargo_process("install").arg("--path").arg(p.root()),
- execs().with_status(0));
- assert_that(cargo_home(), has_installed_exe("foo"));
- assert_that(cargo_process("install").arg("--path").arg(".").cwd(p.root()),
- execs().with_status(101).with_stderr("\
-[INSTALLING] foo v0.1.0 [..]
-[ERROR] binary `foo[..]` already exists in destination as part of `foo v0.1.0 [..]`
-Add --force to overwrite
-"));
-}
-
-#[test]
-fn multiple_crates_error() {
- let p = git::repo(&paths::root().join("foo"))
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
- "#)
- .file("src/main.rs", "fn main() {}")
- .file("a/Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.1.0"
- authors = []
- "#)
- .file("a/src/main.rs", "fn main() {}")
- .build();
-
- assert_that(cargo_process("install").arg("--git").arg(p.url().to_string()),
- execs().with_status(101).with_stderr("\
-[UPDATING] git repository [..]
-[ERROR] multiple packages with binaries found: bar, foo
-"));
-}
-
-#[test]
-fn multiple_crates_select() {
- let p = git::repo(&paths::root().join("foo"))
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
- "#)
- .file("src/main.rs", "fn main() {}")
- .file("a/Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.1.0"
- authors = []
- "#)
- .file("a/src/main.rs", "fn main() {}")
- .build();
-
- assert_that(cargo_process("install").arg("--git").arg(p.url().to_string())
- .arg("foo"),
- execs().with_status(0));
- assert_that(cargo_home(), has_installed_exe("foo"));
- assert_that(cargo_home(), is_not(has_installed_exe("bar")));
-
- assert_that(cargo_process("install").arg("--git").arg(p.url().to_string())
- .arg("bar"),
- execs().with_status(0));
- assert_that(cargo_home(), has_installed_exe("bar"));
-}
-
-#[test]
-fn multiple_crates_auto_binaries() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
-
- [dependencies]
- bar = { path = "a" }
- "#)
- .file("src/main.rs", "extern crate bar; fn main() {}")
- .file("a/Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.1.0"
- authors = []
- "#)
- .file("a/src/lib.rs", "")
- .build();
-
- assert_that(cargo_process("install").arg("--path").arg(p.root()),
- execs().with_status(0));
- assert_that(cargo_home(), has_installed_exe("foo"));
-}
-
-#[test]
-fn multiple_crates_auto_examples() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
-
- [dependencies]
- bar = { path = "a" }
- "#)
- .file("src/lib.rs", "extern crate bar;")
- .file("examples/foo.rs", "
- extern crate bar;
- extern crate foo;
- fn main() {}
- ")
- .file("a/Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.1.0"
- authors = []
- "#)
- .file("a/src/lib.rs", "")
- .build();
-
- assert_that(cargo_process("install").arg("--path").arg(p.root())
- .arg("--example=foo"),
- execs().with_status(0));
- assert_that(cargo_home(), has_installed_exe("foo"));
-}
-
-#[test]
-fn no_binaries_or_examples() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
-
- [dependencies]
- bar = { path = "a" }
- "#)
- .file("src/lib.rs", "")
- .file("a/Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.1.0"
- authors = []
- "#)
- .file("a/src/lib.rs", "")
- .build();
-
- assert_that(cargo_process("install").arg("--path").arg(p.root()),
- execs().with_status(101).with_stderr("\
-[ERROR] no packages found with binaries or examples
-"));
-}
-
-#[test]
-fn no_binaries() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
- "#)
- .file("src/lib.rs", "")
- .file("examples/foo.rs", "fn main() {}")
- .build();
-
- assert_that(cargo_process("install").arg("--path").arg(p.root()).arg("foo"),
- execs().with_status(101).with_stderr("\
-[INSTALLING] foo [..]
-[ERROR] specified package has no binaries
-"));
-}
-
-#[test]
-fn examples() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
- "#)
- .file("src/lib.rs", "")
- .file("examples/foo.rs", "extern crate foo; fn main() {}")
- .build();
-
- assert_that(cargo_process("install").arg("--path").arg(p.root())
- .arg("--example=foo"),
- execs().with_status(0));
- assert_that(cargo_home(), has_installed_exe("foo"));
-}
-
-#[test]
-fn install_twice() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
- "#)
- .file("src/bin/foo-bin1.rs", "fn main() {}")
- .file("src/bin/foo-bin2.rs", "fn main() {}")
- .build();
-
- assert_that(cargo_process("install").arg("--path").arg(p.root()),
- execs().with_status(0));
- assert_that(cargo_process("install").arg("--path").arg(p.root()),
- execs().with_status(101).with_stderr("\
-[INSTALLING] foo v0.1.0 [..]
-[ERROR] binary `foo-bin1[..]` already exists in destination as part of `foo v0.1.0 ([..])`
-binary `foo-bin2[..]` already exists in destination as part of `foo v0.1.0 ([..])`
-Add --force to overwrite
-"));
-}
-
-#[test]
-fn install_force() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- assert_that(cargo_process("install").arg("--path").arg(p.root()),
- execs().with_status(0));
-
- let p = project("foo2")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.2.0"
- authors = []
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- assert_that(cargo_process("install").arg("--force").arg("--path").arg(p.root()),
- execs().with_status(0).with_stderr(&format!("\
-[INSTALLING] foo v0.2.0 ([..])
-[COMPILING] foo v0.2.0 ([..])
-[FINISHED] release [optimized] target(s) in [..]
-[REPLACING] {home}[..]bin[..]foo[..]
-warning: be sure to add `[..]` to your PATH to be able to run the installed binaries
-",
- home = cargo_home().display())));
-
- assert_that(cargo_process("install").arg("--list"),
- execs().with_status(0).with_stdout("\
-foo v0.2.0 ([..]):
- foo[..]
-"));
-}
-
-#[test]
-fn install_force_partial_overlap() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
- "#)
- .file("src/bin/foo-bin1.rs", "fn main() {}")
- .file("src/bin/foo-bin2.rs", "fn main() {}")
- .build();
-
- assert_that(cargo_process("install").arg("--path").arg(p.root()),
- execs().with_status(0));
-
- let p = project("foo2")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.2.0"
- authors = []
- "#)
- .file("src/bin/foo-bin2.rs", "fn main() {}")
- .file("src/bin/foo-bin3.rs", "fn main() {}")
- .build();
-
- assert_that(cargo_process("install").arg("--force").arg("--path").arg(p.root()),
- execs().with_status(0).with_stderr(&format!("\
-[INSTALLING] foo v0.2.0 ([..])
-[COMPILING] foo v0.2.0 ([..])
-[FINISHED] release [optimized] target(s) in [..]
-[INSTALLING] {home}[..]bin[..]foo-bin3[..]
-[REPLACING] {home}[..]bin[..]foo-bin2[..]
-warning: be sure to add `[..]` to your PATH to be able to run the installed binaries
-",
- home = cargo_home().display())));
-
- assert_that(cargo_process("install").arg("--list"),
- execs().with_status(0).with_stdout("\
-foo v0.1.0 ([..]):
- foo-bin1[..]
-foo v0.2.0 ([..]):
- foo-bin2[..]
- foo-bin3[..]
-"));
-}
-
-#[test]
-fn install_force_bin() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
- "#)
- .file("src/bin/foo-bin1.rs", "fn main() {}")
- .file("src/bin/foo-bin2.rs", "fn main() {}")
- .build();
-
- assert_that(cargo_process("install").arg("--path").arg(p.root()),
- execs().with_status(0));
-
- let p = project("foo2")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.2.0"
- authors = []
- "#)
- .file("src/bin/foo-bin1.rs", "fn main() {}")
- .file("src/bin/foo-bin2.rs", "fn main() {}")
- .build();
-
- assert_that(cargo_process("install").arg("--force")
- .arg("--bin")
- .arg("foo-bin2")
- .arg("--path")
- .arg(p.root()),
- execs().with_status(0).with_stderr(&format!("\
-[INSTALLING] foo v0.2.0 ([..])
-[COMPILING] foo v0.2.0 ([..])
-[FINISHED] release [optimized] target(s) in [..]
-[REPLACING] {home}[..]bin[..]foo-bin2[..]
-warning: be sure to add `[..]` to your PATH to be able to run the installed binaries
-",
- home = cargo_home().display())));
-
- assert_that(cargo_process("install").arg("--list"),
- execs().with_status(0).with_stdout("\
-foo v0.1.0 ([..]):
- foo-bin1[..]
-foo v0.2.0 ([..]):
- foo-bin2[..]
-"));
-}
-
-#[test]
-fn compile_failure() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
- "#)
- .file("src/main.rs", "")
- .build();
-
- assert_that(cargo_process("install").arg("--path").arg(p.root()),
- execs().with_status(101).with_stderr_contains("\
-[ERROR] failed to compile `foo v0.1.0 ([..])`, intermediate artifacts can be \
- found at `[..]target`
-
-Caused by:
- Could not compile `foo`.
-
-To learn more, run the command again with --verbose.
-"));
-}
-
-#[test]
-fn git_repo() {
- let p = git::repo(&paths::root().join("foo"))
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- // use `--locked` to test that we don't even try to write a lockfile
- assert_that(cargo_process("install").arg("--locked").arg("--git").arg(p.url().to_string()),
- execs().with_status(0).with_stderr(&format!("\
-[UPDATING] git repository `[..]`
-[INSTALLING] foo v0.1.0 ([..])
-[COMPILING] foo v0.1.0 ([..])
-[FINISHED] release [optimized] target(s) in [..]
-[INSTALLING] {home}[..]bin[..]foo[..]
-warning: be sure to add `[..]` to your PATH to be able to run the installed binaries
-",
- home = cargo_home().display())));
- assert_that(cargo_home(), has_installed_exe("foo"));
- assert_that(cargo_home(), has_installed_exe("foo"));
-}
-
-#[test]
-fn list() {
- pkg("foo", "0.0.1");
- pkg("bar", "0.2.1");
- pkg("bar", "0.2.2");
-
- assert_that(cargo_process("install").arg("--list"),
- execs().with_status(0).with_stdout(""));
-
- assert_that(cargo_process("install").arg("bar").arg("--vers").arg("=0.2.1"),
- execs().with_status(0));
- assert_that(cargo_process("install").arg("foo"),
- execs().with_status(0));
- assert_that(cargo_process("install").arg("--list"),
- execs().with_status(0).with_stdout("\
-bar v0.2.1:
- bar[..]
-foo v0.0.1:
- foo[..]
-"));
-}
-
-#[test]
-fn list_error() {
- pkg("foo", "0.0.1");
- assert_that(cargo_process("install").arg("foo"),
- execs().with_status(0));
- assert_that(cargo_process("install").arg("--list"),
- execs().with_status(0).with_stdout("\
-foo v0.0.1:
- foo[..]
-"));
- let mut worldfile_path = cargo_home();
- worldfile_path.push(".crates.toml");
- let mut worldfile = OpenOptions::new()
- .write(true)
- .open(worldfile_path)
- .expect(".crates.toml should be there");
- worldfile.write_all(b"\x00").unwrap();
- drop(worldfile);
- assert_that(cargo_process("install").arg("--list").arg("--verbose"),
- execs().with_status(101).with_stderr("\
-[ERROR] failed to parse crate metadata at `[..]`
-
-Caused by:
- invalid TOML found for metadata
-
-Caused by:
- unexpected character[..]
-"));
-}
-
-#[test]
-fn uninstall_pkg_does_not_exist() {
- assert_that(cargo_process("uninstall").arg("foo"),
- execs().with_status(101).with_stderr("\
-[ERROR] package id specification `foo` matched no packages
-"));
-}
-
-#[test]
-fn uninstall_bin_does_not_exist() {
- pkg("foo", "0.0.1");
-
- assert_that(cargo_process("install").arg("foo"),
- execs().with_status(0));
- assert_that(cargo_process("uninstall").arg("foo").arg("--bin=bar"),
- execs().with_status(101).with_stderr("\
-[ERROR] binary `bar[..]` not installed as part of `foo v0.0.1`
-"));
-}
-
-#[test]
-fn uninstall_piecemeal() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
- "#)
- .file("src/bin/foo.rs", "fn main() {}")
- .file("src/bin/bar.rs", "fn main() {}")
- .build();
-
- assert_that(cargo_process("install").arg("--path").arg(p.root()),
- execs().with_status(0));
- assert_that(cargo_home(), has_installed_exe("foo"));
- assert_that(cargo_home(), has_installed_exe("bar"));
-
- assert_that(cargo_process("uninstall").arg("foo").arg("--bin=bar"),
- execs().with_status(0).with_stderr("\
-[REMOVING] [..]bar[..]
-"));
-
- assert_that(cargo_home(), has_installed_exe("foo"));
- assert_that(cargo_home(), is_not(has_installed_exe("bar")));
-
- assert_that(cargo_process("uninstall").arg("foo").arg("--bin=foo"),
- execs().with_status(0).with_stderr("\
-[REMOVING] [..]foo[..]
-"));
- assert_that(cargo_home(), is_not(has_installed_exe("foo")));
-
- assert_that(cargo_process("uninstall").arg("foo"),
- execs().with_status(101).with_stderr("\
-[ERROR] package id specification `foo` matched no packages
-"));
-}
-
-#[test]
-fn subcommand_works_out_of_the_box() {
- Package::new("cargo-foo", "1.0.0")
- .file("src/main.rs", r#"
- fn main() {
- println!("bar");
- }
- "#)
- .publish();
- assert_that(cargo_process("install").arg("cargo-foo"),
- execs().with_status(0));
- assert_that(cargo_process("foo"),
- execs().with_status(0).with_stdout("bar\n"));
- assert_that(cargo_process("--list"),
- execs().with_status(0).with_stdout_contains(" foo\n"));
-}
-
-#[test]
-fn installs_from_cwd_by_default() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- assert_that(cargo_process("install").cwd(p.root()),
- execs().with_status(0));
- assert_that(cargo_home(), has_installed_exe("foo"));
-}
-
-#[test]
-fn do_not_rebuilds_on_local_install() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("build").arg("--release"),
- execs().with_status(0));
- assert_that(cargo_process("install").arg("--path").arg(p.root()),
- execs().with_status(0).with_stderr("[INSTALLING] [..]
-[FINISHED] release [optimized] target(s) in [..]
-[INSTALLING] [..]
-warning: be sure to add `[..]` to your PATH to be able to run the installed binaries
-"));
-
- assert!(p.build_dir().exists());
- assert!(p.release_bin("foo").exists());
- assert_that(cargo_home(), has_installed_exe("foo"));
-}
-
-#[test]
-fn reports_unsuccessful_subcommand_result() {
- Package::new("cargo-fail", "1.0.0")
- .file("src/main.rs", r#"
- fn main() {
- panic!();
- }
- "#)
- .publish();
- assert_that(cargo_process("install").arg("cargo-fail"),
- execs().with_status(0));
- assert_that(cargo_process("--list"),
- execs().with_status(0).with_stdout_contains(" fail\n"));
- assert_that(cargo_process("fail"),
- execs().with_status(101).with_stderr_contains("\
-thread '[..]' panicked at 'explicit panic', [..]
-"));
-}
-
-#[test]
-fn git_with_lockfile() {
- let p = git::repo(&paths::root().join("foo"))
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
-
- [dependencies]
- bar = { path = "bar" }
- "#)
- .file("src/main.rs", "fn main() {}")
- .file("bar/Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.1.0"
- authors = []
- "#)
- .file("bar/src/lib.rs", "fn main() {}")
- .file("Cargo.lock", r#"
- [[package]]
- name = "foo"
- version = "0.1.0"
- dependencies = [ "bar 0.1.0" ]
-
- [[package]]
- name = "bar"
- version = "0.1.0"
- "#)
- .build();
-
- assert_that(cargo_process("install").arg("--git").arg(p.url().to_string()),
- execs().with_status(0));
-}
-
-#[test]
-fn q_silences_warnings() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- assert_that(cargo_process("install").arg("-q").arg("--path").arg(p.root()),
- execs().with_status(0).with_stderr(""));
-}
-
-#[test]
-fn readonly_dir() {
- pkg("foo", "0.0.1");
-
- let root = paths::root();
- let dir = &root.join("readonly");
- fs::create_dir(root.join("readonly")).unwrap();
- let mut perms = fs::metadata(dir).unwrap().permissions();
- perms.set_readonly(true);
- fs::set_permissions(dir, perms).unwrap();
-
- assert_that(cargo_process("install").arg("foo").cwd(dir),
- execs().with_status(0));
- assert_that(cargo_home(), has_installed_exe("foo"));
-}
-
-#[test]
-fn use_path_workspace() {
- Package::new("foo", "1.0.0").publish();
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.1.0"
- authors = []
-
- [workspace]
- members = ["baz"]
- "#)
- .file("src/main.rs", "fn main() {}")
- .file("baz/Cargo.toml", r#"
- [package]
- name = "baz"
- version = "0.1.0"
- authors = []
-
- [dependencies]
- foo = "1"
- "#)
- .file("baz/src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build"), execs().with_status(0));
- let lock = p.read_lockfile();
- assert_that(p.cargo("install"), execs().with_status(0));
- let lock2 = p.read_lockfile();
- assert!(lock == lock2, "different lockfiles");
-}
-
-#[test]
-fn vers_precise() {
- pkg("foo", "0.1.1");
- pkg("foo", "0.1.2");
-
- assert_that(cargo_process("install").arg("foo").arg("--vers").arg("0.1.1"),
- execs().with_status(0).with_stderr_contains("\
-[DOWNLOADING] foo v0.1.1 (registry [..])
-"));
-}
-
-#[test]
-fn version_too() {
- pkg("foo", "0.1.1");
- pkg("foo", "0.1.2");
-
- assert_that(cargo_process("install").arg("foo").arg("--version").arg("0.1.1"),
- execs().with_status(0).with_stderr_contains("\
- [DOWNLOADING] foo v0.1.1 (registry [..])
-"));
-}
-
-#[test]
-fn not_both_vers_and_version() {
- pkg("foo", "0.1.1");
- pkg("foo", "0.1.2");
-
- assert_that(cargo_process("install").arg("foo").arg("--version").arg("0.1.1").arg("--vers").arg("0.1.2"),
- execs().with_status(101).with_stderr_contains("\
-error: invalid arguments
-"));
-}
-
-#[test]
-fn legacy_version_requirement() {
- pkg("foo", "0.1.1");
-
- assert_that(cargo_process("install").arg("foo").arg("--vers").arg("0.1"),
- execs().with_status(0).with_stderr_contains("\
-warning: the `--vers` provided, `0.1`, is not a valid semver version
-
-historically Cargo treated this as a semver version requirement accidentally
-and will continue to do so, but this behavior will be removed eventually
-"));
-}
-
-#[test]
-fn test_install_git_cannot_be_a_base_url() {
- assert_that(cargo_process("install").arg("--git").arg("github.com:rust-lang-nursery/rustfmt.git"),
- execs().with_status(101).with_stderr("\
-error: invalid url `github.com:rust-lang-nursery/rustfmt.git`: cannot-be-a-base-URLs are not supported
-"));
-}
-
-#[test]
-fn uninstall_multiple_and_specifying_bin() {
- assert_that(cargo_process("uninstall").args(&["foo", "bar"]).arg("--bin").arg("baz"),
- execs().with_status(101).with_stderr("\
-error: A binary can only be associated with a single installed package, specifying multiple specs with --bin is redundant.
-"));
-}
-
-#[test]
-fn uninstall_multiple_and_some_pkg_does_not_exist() {
- pkg("foo", "0.0.1");
-
- assert_that(cargo_process("install").arg("foo"),
- execs().with_status(0));
-
- assert_that(cargo_process("uninstall").args(&["foo", "bar"]),
- execs().with_status(101).with_stderr(&format!("\
-[REMOVING] {home}[..]bin[..]foo[..]
-error: package id specification `bar` matched no packages
-[SUMMARY] Successfully uninstalled foo! Failed to uninstall bar (see error(s) above).
-error: some packages failed to uninstall
-",
- home = cargo_home().display())));
-
- assert_that(cargo_home(), is_not(has_installed_exe("foo")));
- assert_that(cargo_home(), is_not(has_installed_exe("bar")));
-}
-
-#[test]
-fn custom_target_dir_for_git_source() {
- let p = git::repo(&paths::root().join("foo"))
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- assert_that(cargo_process("install")
- .arg("--git").arg(p.url().to_string()),
- execs().with_status(0));
- assert_that(&paths::root().join("target/release"),
- is_not(existing_dir()));
-
- assert_that(cargo_process("install").arg("--force")
- .arg("--git").arg(p.url().to_string())
- .env("CARGO_TARGET_DIR", "target"),
- execs().with_status(0));
- assert_that(&paths::root().join("target/release"),
- existing_dir());
-}
+++ /dev/null
-extern crate cargotest;
-extern crate hamcrest;
-
-use std::net::TcpListener;
-use std::thread;
-use std::process::Command;
-
-use cargotest::support::{project, execs, cargo_exe};
-use hamcrest::assert_that;
-
-#[test]
-fn jobserver_exists() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("build.rs", r#"
- use std::env;
-
- fn main() {
- let var = env::var("CARGO_MAKEFLAGS").unwrap();
- let arg = var.split(' ')
- .find(|p| p.starts_with("--jobserver"))
- .unwrap();
- let val = &arg[arg.find('=').unwrap() + 1..];
- validate(val);
- }
-
- #[cfg(unix)]
- fn validate(s: &str) {
- use std::fs::File;
- use std::io::*;
- use std::os::unix::prelude::*;
-
- let fds = s.split(',').collect::<Vec<_>>();
- println!("{}", s);
- assert_eq!(fds.len(), 2);
- unsafe {
- let mut read = File::from_raw_fd(fds[0].parse().unwrap());
- let mut write = File::from_raw_fd(fds[1].parse().unwrap());
-
- let mut buf = [0];
- assert_eq!(read.read(&mut buf).unwrap(), 1);
- assert_eq!(write.write(&buf).unwrap(), 1);
- }
- }
-
- #[cfg(windows)]
- fn validate(_: &str) {
- // a little too complicated for a test...
- }
- "#)
- .file("src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0));
-}
-
-#[test]
-fn makes_jobserver_used() {
- let make = if cfg!(windows) {"mingw32-make"} else {"make"};
- if Command::new(make).arg("--version").output().is_err() {
- return
- }
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- d1 = { path = "d1" }
- d2 = { path = "d2" }
- d3 = { path = "d3" }
- "#)
- .file("src/lib.rs", "")
- .file("d1/Cargo.toml", r#"
- [package]
- name = "d1"
- version = "0.0.1"
- authors = []
- build = "../dbuild.rs"
- "#)
- .file("d1/src/lib.rs", "")
- .file("d2/Cargo.toml", r#"
- [package]
- name = "d2"
- version = "0.0.1"
- authors = []
- build = "../dbuild.rs"
- "#)
- .file("d2/src/lib.rs", "")
- .file("d3/Cargo.toml", r#"
- [package]
- name = "d3"
- version = "0.0.1"
- authors = []
- build = "../dbuild.rs"
- "#)
- .file("d3/src/lib.rs", "")
- .file("dbuild.rs", r#"
- use std::net::TcpStream;
- use std::env;
- use std::io::Read;
-
- fn main() {
- let addr = env::var("ADDR").unwrap();
- let mut stream = TcpStream::connect(addr).unwrap();
- let mut v = Vec::new();
- stream.read_to_end(&mut v).unwrap();
- }
- "#)
- .file("Makefile", "\
-all:
-\t+$(CARGO) build
-")
- .build();
-
- let l = TcpListener::bind("127.0.0.1:0").unwrap();
- let addr = l.local_addr().unwrap();
-
- let child = thread::spawn(move || {
- let a1 = l.accept().unwrap();
- let a2 = l.accept().unwrap();
- l.set_nonblocking(true).unwrap();
-
- for _ in 0..1000 {
- assert!(l.accept().is_err());
- thread::yield_now();
- }
-
- drop(a1);
- l.set_nonblocking(false).unwrap();
- let a3 = l.accept().unwrap();
-
- drop((a2, a3));
- });
-
- assert_that(p.process(make)
- .env("CARGO", cargo_exe())
- .env("ADDR", addr.to_string())
- .arg("-j2"),
- execs().with_status(0));
- child.join().unwrap();
-}
-
-#[test]
-fn jobserver_and_j() {
- let make = if cfg!(windows) {"mingw32-make"} else {"make"};
- if Command::new(make).arg("--version").output().is_err() {
- return
- }
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/lib.rs", "")
- .file("Makefile", "\
-all:
-\t+$(CARGO) build -j2
-")
- .build();
-
- assert_that(p.process(make)
- .env("CARGO", cargo_exe())
- .arg("-j2"),
- execs().with_status(0).with_stderr("\
-warning: a `-j` argument was passed to Cargo but Cargo is also configured \
-with an external jobserver in its environment, ignoring the `-j` parameter
-[COMPILING] [..]
-[FINISHED] [..]
-"));
-}
+++ /dev/null
-#[macro_use]
-extern crate cargotest;
-extern crate hamcrest;
-
-use std::fs::{self, File};
-use std::io::prelude::*;
-
-use cargotest::support::paths::{self, CargoPathExt};
-use cargotest::support::registry::Package;
-use cargotest::support::{project, execs};
-use hamcrest::assert_that;
-
-fn setup() {
- let root = paths::root();
- t!(fs::create_dir(&root.join(".cargo")));
- t!(t!(File::create(root.join(".cargo/config"))).write_all(br#"
- [source.crates-io]
- registry = 'https://wut'
- replace-with = 'my-awesome-local-registry'
-
- [source.my-awesome-local-registry]
- local-registry = 'registry'
- "#));
-}
-
-#[test]
-fn simple() {
- setup();
- Package::new("foo", "0.0.1")
- .local(true)
- .file("src/lib.rs", "pub fn foo() {}")
- .publish();
-
- let p = project("bar")
- .file("Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- foo = "0.0.1"
- "#)
- .file("src/lib.rs", r#"
- extern crate foo;
- pub fn bar() {
- foo::foo();
- }
- "#)
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr(&format!("\
-[UNPACKING] foo v0.0.1 ([..])
-[COMPILING] foo v0.0.1
-[COMPILING] bar v0.0.1 ({dir})
-[FINISHED] [..]
-",
- dir = p.url())));
- assert_that(p.cargo("build"), execs().with_status(0).with_stderr("\
-[FINISHED] [..]
-"));
- assert_that(p.cargo("test"), execs().with_status(0));
-}
-
-#[test]
-fn multiple_versions() {
- setup();
- Package::new("foo", "0.0.1").local(true).publish();
- Package::new("foo", "0.1.0")
- .local(true)
- .file("src/lib.rs", "pub fn foo() {}")
- .publish();
-
- let p = project("bar")
- .file("Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- foo = "*"
- "#)
- .file("src/lib.rs", r#"
- extern crate foo;
- pub fn bar() {
- foo::foo();
- }
- "#)
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr(&format!("\
-[UNPACKING] foo v0.1.0 ([..])
-[COMPILING] foo v0.1.0
-[COMPILING] bar v0.0.1 ({dir})
-[FINISHED] [..]
-",
- dir = p.url())));
-
- Package::new("foo", "0.2.0")
- .local(true)
- .file("src/lib.rs", "pub fn foo() {}")
- .publish();
-
- assert_that(p.cargo("update").arg("-v"),
- execs().with_status(0).with_stderr("\
-[UPDATING] foo v0.1.0 -> v0.2.0
-"));
-}
-
-#[test]
-fn multiple_names() {
- setup();
- Package::new("foo", "0.0.1")
- .local(true)
- .file("src/lib.rs", "pub fn foo() {}")
- .publish();
- Package::new("bar", "0.1.0")
- .local(true)
- .file("src/lib.rs", "pub fn bar() {}")
- .publish();
-
- let p = project("local")
- .file("Cargo.toml", r#"
- [project]
- name = "local"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- foo = "*"
- bar = "*"
- "#)
- .file("src/lib.rs", r#"
- extern crate foo;
- extern crate bar;
- pub fn local() {
- foo::foo();
- bar::bar();
- }
- "#)
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr(&format!("\
-[UNPACKING] [..]
-[UNPACKING] [..]
-[COMPILING] [..]
-[COMPILING] [..]
-[COMPILING] local v0.0.1 ({dir})
-[FINISHED] [..]
-",
- dir = p.url())));
-}
-
-#[test]
-fn interdependent() {
- setup();
- Package::new("foo", "0.0.1")
- .local(true)
- .file("src/lib.rs", "pub fn foo() {}")
- .publish();
- Package::new("bar", "0.1.0")
- .local(true)
- .dep("foo", "*")
- .file("src/lib.rs", "extern crate foo; pub fn bar() {}")
- .publish();
-
- let p = project("local")
- .file("Cargo.toml", r#"
- [project]
- name = "local"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- foo = "*"
- bar = "*"
- "#)
- .file("src/lib.rs", r#"
- extern crate foo;
- extern crate bar;
- pub fn local() {
- foo::foo();
- bar::bar();
- }
- "#)
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr(&format!("\
-[UNPACKING] [..]
-[UNPACKING] [..]
-[COMPILING] foo v0.0.1
-[COMPILING] bar v0.1.0
-[COMPILING] local v0.0.1 ({dir})
-[FINISHED] [..]
-",
- dir = p.url())));
-}
-
-#[test]
-fn path_dep_rewritten() {
- setup();
- Package::new("foo", "0.0.1")
- .local(true)
- .file("src/lib.rs", "pub fn foo() {}")
- .publish();
- Package::new("bar", "0.1.0")
- .local(true)
- .dep("foo", "*")
- .file("Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.1.0"
- authors = []
-
- [dependencies]
- foo = { path = "foo", version = "*" }
- "#)
- .file("src/lib.rs", "extern crate foo; pub fn bar() {}")
- .file("foo/Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("foo/src/lib.rs", "pub fn foo() {}")
- .publish();
-
- let p = project("local")
- .file("Cargo.toml", r#"
- [project]
- name = "local"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- foo = "*"
- bar = "*"
- "#)
- .file("src/lib.rs", r#"
- extern crate foo;
- extern crate bar;
- pub fn local() {
- foo::foo();
- bar::bar();
- }
- "#)
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr(&format!("\
-[UNPACKING] [..]
-[UNPACKING] [..]
-[COMPILING] foo v0.0.1
-[COMPILING] bar v0.1.0
-[COMPILING] local v0.0.1 ({dir})
-[FINISHED] [..]
-",
- dir = p.url())));
-}
-
-#[test]
-fn invalid_dir_bad() {
- setup();
- let p = project("local")
- .file("Cargo.toml", r#"
- [project]
- name = "local"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- foo = "*"
- "#)
- .file("src/lib.rs", "")
- .file(".cargo/config", r#"
- [source.crates-io]
- registry = 'https://wut'
- replace-with = 'my-awesome-local-directory'
-
- [source.my-awesome-local-directory]
- local-registry = '/path/to/nowhere'
- "#)
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(101).with_stderr("\
-[ERROR] failed to load source for a dependency on `foo`
-
-Caused by:
- Unable to update registry `https://[..]`
-
-Caused by:
- failed to update replaced source registry `https://[..]`
-
-Caused by:
- local registry path is not a directory: [..]path[..]to[..]nowhere
-"));
-}
-
-#[test]
-fn different_directory_replacing_the_registry_is_bad() {
- setup();
-
- // Move our test's .cargo/config to a temporary location and publish a
- // registry package we're going to use first.
- let config = paths::root().join(".cargo");
- let config_tmp = paths::root().join(".cargo-old");
- t!(fs::rename(&config, &config_tmp));
-
- let p = project("local")
- .file("Cargo.toml", r#"
- [project]
- name = "local"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- foo = "*"
- "#)
- .file("src/lib.rs", "")
- .build();
-
- // Generate a lock file against the crates.io registry
- Package::new("foo", "0.0.1").publish();
- assert_that(p.cargo("build"), execs().with_status(0));
-
- // Switch back to our directory source, and now that we're replacing
- // crates.io make sure that this fails because we're replacing with a
- // different checksum
- config.rm_rf();
- t!(fs::rename(&config_tmp, &config));
- Package::new("foo", "0.0.1")
- .file("src/lib.rs", "invalid")
- .local(true)
- .publish();
-
- assert_that(p.cargo("build"),
- execs().with_status(101).with_stderr("\
-[ERROR] checksum for `foo v0.0.1` 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 `foo v0.0.1` is the same as when the lockfile was generated
-
-"));
-}
-
-#[test]
-fn crates_io_registry_url_is_optional() {
- let root = paths::root();
- t!(fs::create_dir(&root.join(".cargo")));
- t!(t!(File::create(root.join(".cargo/config"))).write_all(br#"
- [source.crates-io]
- replace-with = 'my-awesome-local-registry'
-
- [source.my-awesome-local-registry]
- local-registry = 'registry'
- "#));
-
- Package::new("foo", "0.0.1")
- .local(true)
- .file("src/lib.rs", "pub fn foo() {}")
- .publish();
-
- let p = project("bar")
- .file("Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- foo = "0.0.1"
- "#)
- .file("src/lib.rs", r#"
- extern crate foo;
- pub fn bar() {
- foo::foo();
- }
- "#)
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr(&format!("\
-[UNPACKING] foo v0.0.1 ([..])
-[COMPILING] foo v0.0.1
-[COMPILING] bar v0.0.1 ({dir})
-[FINISHED] [..]
-",
- dir = p.url())));
- assert_that(p.cargo("build"), execs().with_status(0).with_stderr("\
-[FINISHED] [..]
-"));
- assert_that(p.cargo("test"), execs().with_status(0));
-}
+++ /dev/null
-extern crate cargotest;
-extern crate hamcrest;
-
-use cargotest::support::git;
-use cargotest::support::registry::Package;
-use cargotest::support::{execs, project, lines_match};
-use hamcrest::assert_that;
-
-#[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("foo", "0.1.0").publish();
-
- let expected_lockfile =
-r#"[[package]]
-name = "foo"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "zzz"
-version = "0.0.1"
-dependencies = [
- "foo 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[metadata]
-"checksum foo 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "[..]"
-"#;
-
- let old_lockfile =
-r#"[root]
-name = "zzz"
-version = "0.0.1"
-dependencies = [
- "foo 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "foo"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-"#;
-
- let p = project("bar")
- .file("Cargo.toml", r#"
- [project]
- name = "zzz"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- foo = "0.1.0"
- "#)
- .file("src/lib.rs", "")
- .file("Cargo.lock", old_lockfile)
- .build();
-
- assert_that(p.cargo(cargo_command),
- execs().with_status(0));
-
- let lock = p.read_lockfile();
- for (l, r) in expected_lockfile.lines().zip(lock.lines()) {
- assert!(lines_match(l, r), "Lines differ:\n{}\n\n{}", l, r);
- }
-
- assert_eq!(lock.lines().count(), expected_lockfile.lines().count());
-}
-
-
-#[test]
-fn frozen_flag_preserves_old_lockfile() {
- let cksum = Package::new("foo", "0.1.0").publish();
-
- let old_lockfile = format!(
- r#"[root]
-name = "zzz"
-version = "0.0.1"
-dependencies = [
- "foo 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "foo"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[metadata]
-"checksum foo 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "{}"
-"#,
- cksum,
- );
-
- let p = project("bar")
- .file("Cargo.toml", r#"
- [project]
- name = "zzz"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- foo = "0.1.0"
- "#)
- .file("src/lib.rs", "")
- .file("Cargo.lock", &old_lockfile)
- .build();
-
- assert_that(p.cargo("build").arg("--locked"),
- execs().with_status(0));
-
- let lock = p.read_lockfile();
- for (l, r) in old_lockfile.lines().zip(lock.lines()) {
- assert!(lines_match(l, r), "Lines differ:\n{}\n\n{}", l, r);
- }
-
- assert_eq!(lock.lines().count(), old_lockfile.lines().count());
-}
-
-
-#[test]
-fn totally_wild_checksums_works() {
- Package::new("foo", "0.1.0").publish();
-
- let p = project("bar")
- .file("Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- foo = "0.1.0"
- "#)
- .file("src/lib.rs", "")
- .file("Cargo.lock", r#"
-[[package]]
-name = "bar"
-version = "0.0.1"
-dependencies = [
- "foo 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "foo"
-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 foo 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "checksum"
-"#);
-
- let p = p.build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0));
-
- let lock = p.read_lockfile();
- assert!(lock.starts_with(r#"
-[[package]]
-name = "bar"
-version = "0.0.1"
-dependencies = [
- "foo 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "foo"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[metadata]
-"#.trim()));
-}
-
-#[test]
-fn wrong_checksum_is_an_error() {
- Package::new("foo", "0.1.0").publish();
-
- let p = project("bar")
- .file("Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- foo = "0.1.0"
- "#)
- .file("src/lib.rs", "")
- .file("Cargo.lock", r#"
-[[package]]
-name = "bar"
-version = "0.0.1"
-dependencies = [
- "foo 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "foo"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[metadata]
-"checksum foo 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "checksum"
-"#);
-
- let p = p.build();
-
- assert_that(p.cargo("build"),
- execs().with_status(101).with_stderr("\
-[UPDATING] registry `[..]`
-error: checksum for `foo 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 `foo v0.1.0` is the same as when the lockfile was generated
-
-"));
-}
-
-// If the checksum is unlisted in the lockfile (e.g. <none>) yet we can
-// calculate it (e.g. it's a registry dep), then we should in theory just fill
-// it in.
-#[test]
-fn unlisted_checksum_is_bad_if_we_calculate() {
- Package::new("foo", "0.1.0").publish();
-
- let p = project("bar")
- .file("Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- foo = "0.1.0"
- "#)
- .file("src/lib.rs", "")
- .file("Cargo.lock", r#"
-[[package]]
-name = "bar"
-version = "0.0.1"
-dependencies = [
- "foo 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "foo"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[metadata]
-"checksum foo 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "<none>"
-"#);
- let p = p.build();
-
- assert_that(p.cargo("fetch"),
- execs().with_status(101).with_stderr("\
-[UPDATING] registry `[..]`
-error: checksum for `foo 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
-
-"));
-}
-
-// If the checksum is listed in the lockfile yet we cannot calculate it (e.g.
-// git dependencies as of today), then make sure we choke.
-#[test]
-fn listed_checksum_bad_if_we_cannot_compute() {
- let git = git::new("foo", |p| {
- p.file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.1.0"
- authors = []
- "#)
- .file("src/lib.rs", "")
- }).unwrap();
-
- let p = project("bar")
- .file("Cargo.toml", &format!(r#"
- [project]
- name = "bar"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- foo = {{ git = '{}' }}
- "#, git.url()))
- .file("src/lib.rs", "")
- .file("Cargo.lock", &format!(r#"
-[[package]]
-name = "bar"
-version = "0.0.1"
-dependencies = [
- "foo 0.1.0 (git+{0})"
-]
-
-[[package]]
-name = "foo"
-version = "0.1.0"
-source = "git+{0}"
-
-[metadata]
-"checksum foo 0.1.0 (git+{0})" = "checksum"
-"#, git.url()));
-
- let p = p.build();
-
- assert_that(p.cargo("fetch"),
- execs().with_status(101).with_stderr("\
-[UPDATING] git repository `[..]`
-error: checksum for `foo 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 `foo v0.1.0 ([..])` is the same as when the lockfile was generated
-
-"));
-}
-
-#[test]
-fn current_lockfile_format() {
- Package::new("foo", "0.1.0").publish();
-
- let p = project("bar")
- .file("Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- foo = "0.1.0"
- "#)
- .file("src/lib.rs", "");
- let p = p.build();
-
- assert_that(p.cargo("build"), execs().with_status(0));
-
- let actual = p.read_lockfile();
-
- let expected = "\
-[[package]]
-name = \"bar\"
-version = \"0.0.1\"
-dependencies = [
- \"foo 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)\",
-]
-
-[[package]]
-name = \"foo\"
-version = \"0.1.0\"
-source = \"registry+https://github.com/rust-lang/crates.io-index\"
-
-[metadata]
-\"checksum foo 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)\" = \"[..]\"";
-
- for (l, r) in expected.lines().zip(actual.lines()) {
- assert!(lines_match(l, r), "Lines differ:\n{}\n\n{}", l, r);
- }
-
- assert_eq!(actual.lines().count(), expected.lines().count());
-}
-
-#[test]
-fn lockfile_without_root() {
- Package::new("foo", "0.1.0").publish();
-
- let lockfile = r#"[[package]]
-name = "bar"
-version = "0.0.1"
-dependencies = [
- "foo 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "foo"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-"#;
-
- let p = project("bar")
- .file("Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- foo = "0.1.0"
- "#)
- .file("src/lib.rs", "")
- .file("Cargo.lock", lockfile);
-
- let p = p.build();
-
- assert_that(p.cargo("build"), execs().with_status(0));
-
- let lock = p.read_lockfile();
- assert!(lock.starts_with(lockfile.trim()));
-}
-
-#[test]
-fn locked_correct_error() {
- Package::new("foo", "0.1.0").publish();
-
- let p = project("bar")
- .file("Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- foo = "0.1.0"
- "#)
- .file("src/lib.rs", "");
- let p = p.build();
-
- assert_that(p.cargo("build").arg("--locked"),
- execs().with_status(101).with_stderr("\
-[UPDATING] registry `[..]`
-error: the lock file needs to be updated but --locked was passed to prevent this
-"));
-}
+++ /dev/null
-#[macro_use]
-extern crate cargotest;
-extern crate cargo;
-extern crate hamcrest;
-extern crate toml;
-
-use std::io::prelude::*;
-use std::fs::{self, File};
-
-use cargotest::{ChannelChanger, cargo_process};
-use cargotest::support::execs;
-use cargotest::support::registry::registry;
-use cargotest::install::cargo_home;
-use cargo::util::config::Config;
-use cargo::core::Shell;
-use hamcrest::{assert_that, existing_file, is_not};
-
-const TOKEN: &str = "test-token";
-const ORIGINAL_TOKEN: &str = "api-token";
-const CONFIG_FILE: &str = r#"
- [registry]
- token = "api-token"
-
- [registries.test-reg]
- index = "http://dummy_index/"
-"#;
-
-fn setup_old_credentials() {
- let config = cargo_home().join("config");
- t!(fs::create_dir_all(config.parent().unwrap()));
- t!(t!(File::create(&config)).write_all(CONFIG_FILE.as_bytes()));
-}
-
-fn setup_new_credentials() {
- let config = cargo_home().join("credentials");
- t!(fs::create_dir_all(config.parent().unwrap()));
- t!(t!(File::create(&config)).write_all(format!(r#"
- token = "{token}"
- "#, token = ORIGINAL_TOKEN)
- .as_bytes()));
-}
-
-fn check_token(expected_token: &str, registry: Option<&str>) -> bool {
-
- let credentials = cargo_home().join("credentials");
- assert_that(&credentials, existing_file());
-
- let mut contents = String::new();
- File::open(&credentials).unwrap().read_to_string(&mut contents).unwrap();
- let toml: toml::Value = contents.parse().unwrap();
-
- let token = match (registry, toml) {
- // A registry has been provided, so check that the token exists in a
- // table for the registry.
- (Some(registry), toml::Value::Table(table)) => {
- table.get("registries")
- .and_then(|registries_table| registries_table.get(registry))
- .and_then(|registry_table| {
- match registry_table.get("token") {
- Some(&toml::Value::String(ref token)) => Some(token.as_str().to_string()),
- _ => None,
- }
- })
- },
- // There is no registry provided, so check the global token instead.
- (None, toml::Value::Table(table)) => {
- table.get("registry")
- .and_then(|registry_table| registry_table.get("token"))
- .and_then(|v| {
- match v {
- &toml::Value::String(ref token) => Some(token.as_str().to_string()),
- _ => None,
- }
- })
- }
- _ => None
- };
-
- if let Some(token_val) = token {
- token_val == expected_token
- } else {
- false
- }
-}
-
-#[test]
-fn login_with_old_credentials() {
- setup_old_credentials();
-
- assert_that(cargo_process().arg("login")
- .arg("--host").arg(registry().to_string()).arg(TOKEN),
- execs().with_status(0));
-
- let config = cargo_home().join("config");
- assert_that(&config, existing_file());
-
- let mut contents = String::new();
- File::open(&config).unwrap().read_to_string(&mut contents).unwrap();
- assert_eq!(CONFIG_FILE, contents);
-
- // Ensure that we get the new token for the registry
- assert!(check_token(TOKEN, None));
-}
-
-#[test]
-fn login_with_new_credentials() {
- setup_new_credentials();
-
- assert_that(cargo_process().arg("login")
- .arg("--host").arg(registry().to_string()).arg(TOKEN),
- execs().with_status(0));
-
- let config = cargo_home().join("config");
- assert_that(&config, is_not(existing_file()));
-
- // Ensure that we get the new token for the registry
- assert!(check_token(TOKEN, None));
-}
-
-#[test]
-fn login_with_old_and_new_credentials() {
- setup_new_credentials();
- login_with_old_credentials();
-}
-
-#[test]
-fn login_without_credentials() {
- assert_that(cargo_process().arg("login")
- .arg("--host").arg(registry().to_string()).arg(TOKEN),
- execs().with_status(0));
-
- let config = cargo_home().join("config");
- assert_that(&config, is_not(existing_file()));
-
- // Ensure that we get the new token for the registry
- assert!(check_token(TOKEN, None));
-}
-
-#[test]
-fn new_credentials_is_used_instead_old() {
- setup_old_credentials();
- setup_new_credentials();
-
- assert_that(cargo_process().arg("login")
- .arg("--host").arg(registry().to_string()).arg(TOKEN),
- execs().with_status(0));
-
- let config = Config::new(Shell::new(), cargo_home(), cargo_home());
-
- let token = config.get_string("registry.token").unwrap().map(|p| p.val);
- assert_eq!(token.unwrap(), TOKEN);
-}
-
-#[test]
-fn registry_credentials() {
- setup_old_credentials();
- setup_new_credentials();
-
- let reg = "test-reg";
-
- assert_that(cargo_process().arg("login").masquerade_as_nightly_cargo()
- .arg("--registry").arg(reg).arg(TOKEN).arg("-Zunstable-options"),
- execs().with_status(0));
-
- // Ensure that we have not updated the default token
- assert!(check_token(ORIGINAL_TOKEN, None));
-
- // Also ensure that we get the new token for the registry
- assert!(check_token(TOKEN, Some(reg)));
-}
+++ /dev/null
-extern crate cargotest;
-extern crate hamcrest;
-
-use hamcrest::assert_that;
-use cargotest::support::registry::Package;
-use cargotest::support::{project, execs, basic_bin_manifest, basic_lib_manifest, main_file};
-
-#[test]
-fn cargo_metadata_simple() {
- let p = project("foo")
- .file("src/foo.rs", "")
- .file("Cargo.toml", &basic_bin_manifest("foo"))
- .build();
-
- assert_that(p.cargo("metadata"), execs().with_json(r#"
- {
- "packages": [
- {
- "name": "foo",
- "version": "0.5.0",
- "id": "foo[..]",
- "source": null,
- "dependencies": [],
- "license": null,
- "license_file": null,
- "description": null,
- "targets": [
- {
- "kind": [
- "bin"
- ],
- "crate_types": [
- "bin"
- ],
- "name": "foo",
- "src_path": "[..][/]foo[/]src[/]foo.rs"
- }
- ],
- "features": {},
- "manifest_path": "[..]Cargo.toml"
- }
- ],
- "workspace_members": ["foo 0.5.0 (path+file:[..]foo)"],
- "resolve": {
- "nodes": [
- {
- "dependencies": [],
- "id": "foo 0.5.0 (path+file:[..]foo)"
- }
- ],
- "root": "foo 0.5.0 (path+file:[..]foo)"
- },
- "target_directory": "[..]foo[/]target",
- "version": 1,
- "workspace_root": "[..][/]foo"
- }"#));
-}
-
-#[test]
-fn cargo_metadata_warns_on_implicit_version() {
- let p = project("foo")
- .file("src/foo.rs", "")
- .file("Cargo.toml", &basic_bin_manifest("foo"))
- .build();
-
- assert_that(p.cargo("metadata"),
- execs().with_stderr("\
-[WARNING] please specify `--format-version` flag explicitly to avoid compatibility problems"));
-
- assert_that(p.cargo("metadata").arg("--format-version").arg("1"),
- execs().with_stderr(""));
-}
-
-#[test]
-fn library_with_several_crate_types() {
- let p = project("foo")
- .file("src/lib.rs", "")
- .file("Cargo.toml", r#"
-[package]
-name = "foo"
-version = "0.5.0"
-
-[lib]
-crate-type = ["lib", "staticlib"]
- "#)
- .build();
-
- assert_that(p.cargo("metadata"), execs().with_json(r#"
- {
- "packages": [
- {
- "name": "foo",
- "version": "0.5.0",
- "id": "foo[..]",
- "source": null,
- "dependencies": [],
- "license": null,
- "license_file": null,
- "description": null,
- "targets": [
- {
- "kind": [
- "lib",
- "staticlib"
- ],
- "crate_types": [
- "lib",
- "staticlib"
- ],
- "name": "foo",
- "src_path": "[..][/]foo[/]src[/]lib.rs"
- }
- ],
- "features": {},
- "manifest_path": "[..]Cargo.toml"
- }
- ],
- "workspace_members": ["foo 0.5.0 (path+file:[..]foo)"],
- "resolve": {
- "nodes": [
- {
- "dependencies": [],
- "id": "foo 0.5.0 (path+file:[..]foo)"
- }
- ],
- "root": "foo 0.5.0 (path+file:[..]foo)"
- },
- "target_directory": "[..]foo[/]target",
- "version": 1,
- "workspace_root": "[..][/]foo"
- }"#));
-}
-
-#[test]
-fn cargo_metadata_with_deps_and_version() {
- let p = project("foo")
- .file("src/foo.rs", "")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.5.0"
- authors = []
- license = "MIT"
- description = "foo"
-
- [[bin]]
- name = "foo"
-
- [dependencies]
- bar = "*"
- "#)
- .build();
- Package::new("baz", "0.0.1").publish();
- Package::new("bar", "0.0.1").dep("baz", "0.0.1").publish();
-
- assert_that(p.cargo("metadata")
- .arg("-q")
- .arg("--format-version").arg("1"),
- execs().with_json(r#"
- {
- "packages": [
- {
- "dependencies": [],
- "features": {},
- "id": "baz 0.0.1 (registry+[..])",
- "manifest_path": "[..]Cargo.toml",
- "name": "baz",
- "source": "registry+[..]",
- "license": null,
- "license_file": null,
- "description": null,
- "targets": [
- {
- "kind": [
- "lib"
- ],
- "crate_types": [
- "lib"
- ],
- "name": "baz",
- "src_path": "[..]lib.rs"
- }
- ],
- "version": "0.0.1"
- },
- {
- "dependencies": [
- {
- "features": [],
- "kind": null,
- "name": "baz",
- "optional": false,
- "req": "^0.0.1",
- "source": "registry+[..]",
- "target": null,
- "uses_default_features": true,
- "rename": null
- }
- ],
- "features": {},
- "id": "bar 0.0.1 (registry+[..])",
- "manifest_path": "[..]Cargo.toml",
- "name": "bar",
- "source": "registry+[..]",
- "license": null,
- "license_file": null,
- "description": null,
- "targets": [
- {
- "kind": [
- "lib"
- ],
- "crate_types": [
- "lib"
- ],
- "name": "bar",
- "src_path": "[..]lib.rs"
- }
- ],
- "version": "0.0.1"
- },
- {
- "dependencies": [
- {
- "features": [],
- "kind": null,
- "name": "bar",
- "optional": false,
- "req": "*",
- "source": "registry+[..]",
- "target": null,
- "uses_default_features": true,
- "rename": null
- }
- ],
- "features": {},
- "id": "foo 0.5.0 (path+file:[..]foo)",
- "manifest_path": "[..]Cargo.toml",
- "name": "foo",
- "source": null,
- "license": "MIT",
- "license_file": null,
- "description": "foo",
- "targets": [
- {
- "kind": [
- "bin"
- ],
- "crate_types": [
- "bin"
- ],
- "name": "foo",
- "src_path": "[..]foo.rs"
- }
- ],
- "version": "0.5.0"
- }
- ],
- "workspace_members": ["foo 0.5.0 (path+file:[..]foo)"],
- "resolve": {
- "nodes": [
- {
- "dependencies": [
- "bar 0.0.1 (registry+[..])"
- ],
- "id": "foo 0.5.0 (path+file:[..]foo)"
- },
- {
- "dependencies": [
- "baz 0.0.1 (registry+[..])"
- ],
- "id": "bar 0.0.1 (registry+[..])"
- },
- {
- "dependencies": [],
- "id": "baz 0.0.1 (registry+[..])"
- }
- ],
- "root": "foo 0.5.0 (path+file:[..]foo)"
- },
- "target_directory": "[..]foo[/]target",
- "version": 1,
- "workspace_root": "[..][/]foo"
- }"#));
-}
-
-#[test]
-fn example() {
- let p = project("foo")
- .file("src/lib.rs", "")
- .file("examples/ex.rs", "")
- .file("Cargo.toml", r#"
-[package]
-name = "foo"
-version = "0.1.0"
-
-[[example]]
-name = "ex"
- "#)
- .build();
-
- assert_that(p.cargo("metadata"), execs().with_json(r#"
- {
- "packages": [
- {
- "name": "foo",
- "version": "0.1.0",
- "id": "foo[..]",
- "license": null,
- "license_file": null,
- "description": null,
- "source": null,
- "dependencies": [],
- "targets": [
- {
- "kind": [ "lib" ],
- "crate_types": [ "lib" ],
- "name": "foo",
- "src_path": "[..][/]foo[/]src[/]lib.rs"
- },
- {
- "kind": [ "example" ],
- "crate_types": [ "bin" ],
- "name": "ex",
- "src_path": "[..][/]foo[/]examples[/]ex.rs"
- }
- ],
- "features": {},
- "manifest_path": "[..]Cargo.toml"
- }
- ],
- "workspace_members": [
- "foo 0.1.0 (path+file:[..]foo)"
- ],
- "resolve": {
- "root": "foo 0.1.0 (path+file://[..]foo)",
- "nodes": [
- {
- "id": "foo 0.1.0 (path+file:[..]foo)",
- "dependencies": []
- }
- ]
- },
- "target_directory": "[..]foo[/]target",
- "version": 1,
- "workspace_root": "[..][/]foo"
- }"#));
-}
-
-#[test]
-fn example_lib() {
- let p = project("foo")
- .file("src/lib.rs", "")
- .file("examples/ex.rs", "")
- .file("Cargo.toml", r#"
-[package]
-name = "foo"
-version = "0.1.0"
-
-[[example]]
-name = "ex"
-crate-type = ["rlib", "dylib"]
- "#)
- .build();
-
- assert_that(p.cargo("metadata"), execs().with_json(r#"
- {
- "packages": [
- {
- "name": "foo",
- "version": "0.1.0",
- "id": "foo[..]",
- "license": null,
- "license_file": null,
- "description": null,
- "source": null,
- "dependencies": [],
- "targets": [
- {
- "kind": [ "lib" ],
- "crate_types": [ "lib" ],
- "name": "foo",
- "src_path": "[..][/]foo[/]src[/]lib.rs"
- },
- {
- "kind": [ "example" ],
- "crate_types": [ "rlib", "dylib" ],
- "name": "ex",
- "src_path": "[..][/]foo[/]examples[/]ex.rs"
- }
- ],
- "features": {},
- "manifest_path": "[..]Cargo.toml"
- }
- ],
- "workspace_members": [
- "foo 0.1.0 (path+file:[..]foo)"
- ],
- "resolve": {
- "root": "foo 0.1.0 (path+file://[..]foo)",
- "nodes": [
- {
- "id": "foo 0.1.0 (path+file:[..]foo)",
- "dependencies": []
- }
- ]
- },
- "target_directory": "[..]foo[/]target",
- "version": 1,
- "workspace_root": "[..][/]foo"
- }"#));
-}
-
-#[test]
-fn workspace_metadata() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [workspace]
- members = ["bar", "baz"]
- "#)
- .file("bar/Cargo.toml", &basic_lib_manifest("bar"))
- .file("bar/src/lib.rs", "")
- .file("baz/Cargo.toml", &basic_lib_manifest("baz"))
- .file("baz/src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("metadata"), execs().with_status(0).with_json(r#"
- {
- "packages": [
- {
- "name": "bar",
- "version": "0.5.0",
- "id": "bar[..]",
- "source": null,
- "dependencies": [],
- "license": null,
- "license_file": null,
- "description": null,
- "targets": [
- {
- "kind": [ "lib" ],
- "crate_types": [ "lib" ],
- "name": "bar",
- "src_path": "[..]bar[/]src[/]lib.rs"
- }
- ],
- "features": {},
- "manifest_path": "[..]bar[/]Cargo.toml"
- },
- {
- "name": "baz",
- "version": "0.5.0",
- "id": "baz[..]",
- "source": null,
- "dependencies": [],
- "license": null,
- "license_file": null,
- "description": null,
- "targets": [
- {
- "kind": [ "lib" ],
- "crate_types": [ "lib" ],
- "name": "baz",
- "src_path": "[..]baz[/]src[/]lib.rs"
- }
- ],
- "features": {},
- "manifest_path": "[..]baz[/]Cargo.toml"
- }
- ],
- "workspace_members": ["baz 0.5.0 (path+file:[..]baz)", "bar 0.5.0 (path+file:[..]bar)"],
- "resolve": {
- "nodes": [
- {
- "dependencies": [],
- "id": "baz 0.5.0 (path+file:[..]baz)"
- },
- {
- "dependencies": [],
- "id": "bar 0.5.0 (path+file:[..]bar)"
- }
- ],
- "root": null
- },
- "target_directory": "[..]foo[/]target",
- "version": 1,
- "workspace_root": "[..][/]foo"
- }"#))
-}
-
-#[test]
-fn workspace_metadata_no_deps() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [workspace]
- members = ["bar", "baz"]
- "#)
- .file("bar/Cargo.toml", &basic_lib_manifest("bar"))
- .file("bar/src/lib.rs", "")
- .file("baz/Cargo.toml", &basic_lib_manifest("baz"))
- .file("baz/src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("metadata").arg("--no-deps"), execs().with_status(0).with_json(r#"
- {
- "packages": [
- {
- "name": "bar",
- "version": "0.5.0",
- "id": "bar[..]",
- "source": null,
- "dependencies": [],
- "license": null,
- "license_file": null,
- "description": null,
- "targets": [
- {
- "kind": [ "lib" ],
- "crate_types": [ "lib" ],
- "name": "bar",
- "src_path": "[..]bar[/]src[/]lib.rs"
- }
- ],
- "features": {},
- "manifest_path": "[..]bar[/]Cargo.toml"
- },
- {
- "name": "baz",
- "version": "0.5.0",
- "id": "baz[..]",
- "source": null,
- "dependencies": [],
- "license": null,
- "license_file": null,
- "description": null,
- "targets": [
- {
- "kind": [ "lib" ],
- "crate_types": ["lib"],
- "name": "baz",
- "src_path": "[..]baz[/]src[/]lib.rs"
- }
- ],
- "features": {},
- "manifest_path": "[..]baz[/]Cargo.toml"
- }
- ],
- "workspace_members": ["baz 0.5.0 (path+file:[..]baz)", "bar 0.5.0 (path+file:[..]bar)"],
- "resolve": null,
- "target_directory": "[..]foo[/]target",
- "version": 1,
- "workspace_root": "[..][/]foo"
- }"#))
-}
-
-#[test]
-fn cargo_metadata_with_invalid_manifest() {
- let p = project("foo")
- .file("Cargo.toml", "")
- .build();
-
- assert_that(p.cargo("metadata").arg("--format-version").arg("1"),
- execs().with_status(101).with_stderr("\
-[ERROR] failed to parse manifest at `[..]`
-
-Caused by:
- virtual manifests must be configured with [workspace]"))
-}
-
-const MANIFEST_OUTPUT: &'static str=
- r#"
-{
- "packages": [{
- "name":"foo",
- "version":"0.5.0",
- "id":"foo[..]0.5.0[..](path+file://[..]/foo)",
- "source":null,
- "dependencies":[],
- "license": null,
- "license_file": null,
- "description": null,
- "targets":[{
- "kind":["bin"],
- "crate_types":["bin"],
- "name":"foo",
- "src_path":"[..][/]foo[/]src[/]foo.rs"
- }],
- "features":{},
- "manifest_path":"[..]Cargo.toml"
- }],
- "workspace_members": [ "foo 0.5.0 (path+file:[..]foo)" ],
- "resolve": null,
- "target_directory": "[..]foo[/]target",
- "version": 1,
- "workspace_root": "[..][/]foo"
-}"#;
-
-#[test]
-fn cargo_metadata_no_deps_path_to_cargo_toml_relative() {
- let p = project("foo")
- .file("Cargo.toml", &basic_bin_manifest("foo"))
- .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
- .build();
-
- assert_that(p.cargo("metadata").arg("--no-deps")
- .arg("--manifest-path").arg("foo/Cargo.toml")
- .cwd(p.root().parent().unwrap()),
- execs().with_status(0)
- .with_json(MANIFEST_OUTPUT));
-}
-
-#[test]
-fn cargo_metadata_no_deps_path_to_cargo_toml_absolute() {
- let p = project("foo")
- .file("Cargo.toml", &basic_bin_manifest("foo"))
- .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
- .build();
-
- assert_that(p.cargo("metadata").arg("--no-deps")
- .arg("--manifest-path").arg(p.root().join("Cargo.toml"))
- .cwd(p.root().parent().unwrap()),
- execs().with_status(0)
- .with_json(MANIFEST_OUTPUT));
-}
-
-#[test]
-fn cargo_metadata_no_deps_path_to_cargo_toml_parent_relative() {
- let p = project("foo")
- .file("Cargo.toml", &basic_bin_manifest("foo"))
- .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
- .build();
-
- assert_that(p.cargo("metadata").arg("--no-deps")
- .arg("--manifest-path").arg("foo")
- .cwd(p.root().parent().unwrap()),
- execs().with_status(101)
- .with_stderr("[ERROR] the manifest-path must be \
- a path to a Cargo.toml file"));
-}
-
-#[test]
-fn cargo_metadata_no_deps_path_to_cargo_toml_parent_absolute() {
- let p = project("foo")
- .file("Cargo.toml", &basic_bin_manifest("foo"))
- .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
- .build();
-
- assert_that(p.cargo("metadata").arg("--no-deps")
- .arg("--manifest-path").arg(p.root())
- .cwd(p.root().parent().unwrap()),
- execs().with_status(101)
- .with_stderr("[ERROR] the manifest-path must be \
- a path to a Cargo.toml file"));
-}
-
-#[test]
-fn cargo_metadata_no_deps_cwd() {
- let p = project("foo")
- .file("Cargo.toml", &basic_bin_manifest("foo"))
- .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
- .build();
-
- assert_that(p.cargo("metadata").arg("--no-deps")
- .cwd(p.root()),
- execs().with_status(0)
- .with_json(MANIFEST_OUTPUT));
-}
-
-#[test]
-fn cargo_metadata_bad_version() {
- let p = project("foo")
- .file("Cargo.toml", &basic_bin_manifest("foo"))
- .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
- .build();
-
- assert_that(p.cargo("metadata").arg("--no-deps")
- .arg("--format-version").arg("2")
- .cwd(p.root()),
- execs().with_status(101)
- .with_stderr("[ERROR] metadata version 2 not supported, only 1 is currently supported"));
-}
-
-#[test]
-fn multiple_features() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
-
- [features]
- a = []
- b = []
- "#)
- .file("src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("metadata")
- .arg("--features").arg("a b"),
- execs().with_status(0));
-}
+++ /dev/null
-extern crate cargotest;
-extern crate hamcrest;
-
-use cargotest::support::{project, execs};
-use hamcrest::assert_that;
-
-#[test]
-fn net_retry_loads_from_config() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies.bar]
- git = "https://127.0.0.1:11/foo/bar"
- "#)
- .file("src/main.rs", "").file(".cargo/config", r#"
- [net]
- retry=1
- [http]
- timeout=1
- "#)
- .build();
-
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(101)
- .with_stderr_contains("[WARNING] spurious network error \
-(1 tries remaining): [..]"));
-}
-
-#[test]
-fn net_retry_git_outputs_warning() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies.bar]
- git = "https://127.0.0.1:11/foo/bar"
- "#)
- .file(".cargo/config", r#"
- [http]
- timeout=1
- "#)
- .file("src/main.rs", "")
- .build();
-
- assert_that(p.cargo("build").arg("-v").arg("-j").arg("1"),
- execs().with_status(101)
- .with_stderr_contains("[WARNING] spurious network error \
-(2 tries remaining): [..]")
- .with_stderr_contains("\
-[WARNING] spurious network error (1 tries remaining): [..]"));
-}
+++ /dev/null
-extern crate cargo;
-extern crate cargotest;
-extern crate hamcrest;
-extern crate tempdir;
-
-use std::fs::{self, File};
-use std::io::prelude::*;
-use std::env;
-
-use cargo::util::ProcessBuilder;
-use cargotest::process;
-use cargotest::support::{execs, paths};
-use hamcrest::{assert_that, existing_file, existing_dir, is_not};
-use tempdir::TempDir;
-
-fn cargo_process(s: &str) -> ProcessBuilder {
- let mut p = cargotest::cargo_process();
- p.arg(s);
- p
-}
-
-fn create_empty_gitconfig() {
- // This helps on Windows where libgit2 is very aggressive in attempting to
- // find a git config file.
- let gitconfig = paths::home().join(".gitconfig");
- File::create(gitconfig).unwrap();
-}
-
-
-#[test]
-fn simple_lib() {
- assert_that(cargo_process("new").arg("--lib").arg("foo").arg("--vcs").arg("none")
- .env("USER", "foo"),
- execs().with_status(0).with_stderr("\
-[CREATED] library `foo` project
-"));
-
- assert_that(&paths::root().join("foo"), existing_dir());
- assert_that(&paths::root().join("foo/Cargo.toml"), existing_file());
- assert_that(&paths::root().join("foo/src/lib.rs"), existing_file());
- assert_that(&paths::root().join("foo/.gitignore"), is_not(existing_file()));
-
- let lib = paths::root().join("foo/src/lib.rs");
- let mut contents = String::new();
- File::open(&lib).unwrap().read_to_string(&mut contents).unwrap();
- assert_eq!(contents, r#"#[cfg(test)]
-mod tests {
- #[test]
- fn it_works() {
- assert_eq!(2 + 2, 4);
- }
-}
-"#);
-
- assert_that(cargo_process("build").cwd(&paths::root().join("foo")),
- execs().with_status(0));
-}
-
-#[test]
-fn simple_bin() {
- assert_that(cargo_process("new").arg("--bin").arg("foo")
- .env("USER", "foo"),
- execs().with_status(0).with_stderr("\
-[CREATED] binary (application) `foo` project
-"));
-
- assert_that(&paths::root().join("foo"), existing_dir());
- assert_that(&paths::root().join("foo/Cargo.toml"), existing_file());
- assert_that(&paths::root().join("foo/src/main.rs"), existing_file());
-
- assert_that(cargo_process("build").cwd(&paths::root().join("foo")),
- execs().with_status(0));
- assert_that(&paths::root().join(&format!("foo/target/debug/foo{}",
- env::consts::EXE_SUFFIX)),
- existing_file());
-}
-
-#[test]
-fn both_lib_and_bin() {
- assert_that(cargo_process("new").arg("--lib").arg("--bin").arg("foo")
- .env("USER", "foo"),
- execs().with_status(101).with_stderr(
- "[ERROR] can't specify both lib and binary outputs"));
-}
-
-#[test]
-fn simple_git() {
- // Run inside a temp directory so that cargo will initialize a git repo.
- // If this ran inside paths::root() it would detect that we are already
- // inside a git repo and skip the initialization.
- let td = TempDir::new("cargo").unwrap();
- assert_that(cargo_process("new").arg("--lib").arg("foo").cwd(td.path())
- .env("USER", "foo"),
- execs().with_status(0));
-
- assert_that(td.path(), existing_dir());
- assert_that(&td.path().join("foo/Cargo.toml"), existing_file());
- assert_that(&td.path().join("foo/src/lib.rs"), existing_file());
- assert_that(&td.path().join("foo/.git"), existing_dir());
- assert_that(&td.path().join("foo/.gitignore"), existing_file());
-
- assert_that(cargo_process("build").cwd(&td.path().join("foo")),
- execs().with_status(0));
-}
-
-#[test]
-fn no_argument() {
- assert_that(cargo_process("new"),
- execs().with_status(1)
- .with_stderr("\
-[ERROR] Invalid arguments.
-
-Usage:
- cargo new [options] <path>
- cargo new -h | --help
-"));
-}
-
-#[test]
-fn existing() {
- let dst = paths::root().join("foo");
- fs::create_dir(&dst).unwrap();
- assert_that(cargo_process("new").arg("foo"),
- execs().with_status(101)
- .with_stderr(format!("[ERROR] destination `{}` already exists\n\n\
- Use `cargo init` to initialize the directory",
- dst.display())));
-}
-
-#[test]
-fn invalid_characters() {
- assert_that(cargo_process("new").arg("foo.rs"),
- execs().with_status(101)
- .with_stderr("\
-[ERROR] Invalid character `.` in crate name: `foo.rs`
-use --name to override crate name"));
-}
-
-#[test]
-fn reserved_name() {
- assert_that(cargo_process("new").arg("test"),
- execs().with_status(101)
- .with_stderr("\
-[ERROR] The name `test` cannot be used as a crate name\n\
-use --name to override crate name"));
-}
-
-#[test]
-fn reserved_binary_name() {
- assert_that(cargo_process("new").arg("--bin").arg("incremental"),
- execs().with_status(101)
- .with_stderr("\
-[ERROR] The name `incremental` cannot be used as a crate name\n\
-use --name to override crate name"));
-}
-
-#[test]
-fn keyword_name() {
- assert_that(cargo_process("new").arg("pub"),
- execs().with_status(101)
- .with_stderr("\
-[ERROR] The name `pub` cannot be used as a crate name\n\
-use --name to override crate name"));
-}
-
-#[test]
-fn finds_author_user() {
- create_empty_gitconfig();
- assert_that(cargo_process("new").arg("foo").env("USER", "foo"),
- execs().with_status(0));
-
- let toml = paths::root().join("foo/Cargo.toml");
- let mut contents = String::new();
- File::open(&toml).unwrap().read_to_string(&mut contents).unwrap();
- assert!(contents.contains(r#"authors = ["foo"]"#));
-}
-
-#[test]
-fn finds_author_user_escaped() {
- create_empty_gitconfig();
- assert_that(cargo_process("new").arg("foo").env("USER", "foo \"bar\""),
- execs().with_status(0));
-
- let toml = paths::root().join("foo/Cargo.toml");
- let mut contents = String::new();
- File::open(&toml).unwrap().read_to_string(&mut contents).unwrap();
- assert!(contents.contains(r#"authors = ["foo \"bar\""]"#));
-}
-
-#[test]
-fn finds_author_username() {
- create_empty_gitconfig();
- assert_that(cargo_process("new").arg("foo")
- .env_remove("USER")
- .env("USERNAME", "foo"),
- execs().with_status(0));
-
- let toml = paths::root().join("foo/Cargo.toml");
- let mut contents = String::new();
- File::open(&toml).unwrap().read_to_string(&mut contents).unwrap();
- assert!(contents.contains(r#"authors = ["foo"]"#));
-}
-
-#[test]
-fn finds_author_priority() {
- assert_that(cargo_process("new").arg("foo")
- .env("USER", "bar2")
- .env("EMAIL", "baz2")
- .env("CARGO_NAME", "bar")
- .env("CARGO_EMAIL", "baz"),
- execs().with_status(0));
-
- let toml = paths::root().join("foo/Cargo.toml");
- let mut contents = String::new();
- File::open(&toml).unwrap().read_to_string(&mut contents).unwrap();
- assert!(contents.contains(r#"authors = ["bar <baz>"]"#));
-}
-
-#[test]
-fn finds_author_email() {
- create_empty_gitconfig();
- assert_that(cargo_process("new").arg("foo")
- .env("USER", "bar")
- .env("EMAIL", "baz"),
- execs().with_status(0));
-
- let toml = paths::root().join("foo/Cargo.toml");
- let mut contents = String::new();
- File::open(&toml).unwrap().read_to_string(&mut contents).unwrap();
- assert!(contents.contains(r#"authors = ["bar <baz>"]"#));
-}
-
-#[test]
-fn finds_author_git() {
- process("git").args(&["config", "--global", "user.name", "bar"])
- .exec().unwrap();
- process("git").args(&["config", "--global", "user.email", "baz"])
- .exec().unwrap();
- assert_that(cargo_process("new").arg("foo").env("USER", "foo"),
- execs().with_status(0));
-
- let toml = paths::root().join("foo/Cargo.toml");
- let mut contents = String::new();
- File::open(&toml).unwrap().read_to_string(&mut contents).unwrap();
- assert!(contents.contains(r#"authors = ["bar <baz>"]"#));
-}
-
-#[test]
-fn finds_local_author_git() {
- process("git").args(&["init"])
- .exec().unwrap();
- process("git").args(&["config", "--global", "user.name", "foo"])
- .exec().unwrap();
- process("git").args(&["config", "--global", "user.email", "foo@bar"])
- .exec().unwrap();
-
- // Set local git user config
- process("git").args(&["config", "user.name", "bar"])
- .exec().unwrap();
- process("git").args(&["config", "user.email", "baz"])
- .exec().unwrap();
- assert_that(cargo_process("init").env("USER", "foo"),
- execs().with_status(0));
-
- let toml = paths::root().join("Cargo.toml");
- let mut contents = String::new();
- File::open(&toml).unwrap().read_to_string(&mut contents).unwrap();
- assert!(contents.contains(r#"authors = ["bar <baz>"]"#));
-}
-
-#[test]
-fn finds_git_email() {
- assert_that(cargo_process("new").arg("foo")
- .env("GIT_AUTHOR_NAME", "foo")
- .env("GIT_AUTHOR_EMAIL", "gitfoo"),
- execs().with_status(0));
-
- let toml = paths::root().join("foo/Cargo.toml");
- let mut contents = String::new();
- File::open(&toml).unwrap().read_to_string(&mut contents).unwrap();
- assert!(contents.contains(r#"authors = ["foo <gitfoo>"]"#), contents);
-}
-
-
-#[test]
-fn finds_git_author() {
- create_empty_gitconfig();
- assert_that(cargo_process("new").arg("foo")
- .env_remove("USER")
- .env("GIT_COMMITTER_NAME", "gitfoo"),
- execs().with_status(0));
-
- let toml = paths::root().join("foo/Cargo.toml");
- let mut contents = String::new();
- File::open(&toml).unwrap().read_to_string(&mut contents).unwrap();
- assert!(contents.contains(r#"authors = ["gitfoo"]"#));
-}
-
-#[test]
-fn author_prefers_cargo() {
- process("git").args(&["config", "--global", "user.name", "foo"])
- .exec().unwrap();
- process("git").args(&["config", "--global", "user.email", "bar"])
- .exec().unwrap();
- let root = paths::root();
- fs::create_dir(&root.join(".cargo")).unwrap();
- File::create(&root.join(".cargo/config")).unwrap().write_all(br#"
- [cargo-new]
- name = "new-foo"
- email = "new-bar"
- vcs = "none"
- "#).unwrap();
-
- assert_that(cargo_process("new").arg("foo").env("USER", "foo"),
- execs().with_status(0));
-
- let toml = paths::root().join("foo/Cargo.toml");
- let mut contents = String::new();
- File::open(&toml).unwrap().read_to_string(&mut contents).unwrap();
- assert!(contents.contains(r#"authors = ["new-foo <new-bar>"]"#));
- assert!(!root.join("foo/.gitignore").exists());
-}
-
-#[test]
-fn git_prefers_command_line() {
- let root = paths::root();
- fs::create_dir(&root.join(".cargo")).unwrap();
- File::create(&root.join(".cargo/config")).unwrap().write_all(br#"
- [cargo-new]
- vcs = "none"
- name = "foo"
- email = "bar"
- "#).unwrap();
-
- assert_that(cargo_process("new").arg("foo").arg("--vcs").arg("git")
- .env("USER", "foo"),
- execs().with_status(0));
- assert!(paths::root().join("foo/.gitignore").exists());
-}
-
-#[test]
-fn subpackage_no_git() {
- assert_that(cargo_process("new").arg("foo").env("USER", "foo"),
- execs().with_status(0));
-
- let subpackage = paths::root().join("foo").join("components");
- fs::create_dir(&subpackage).unwrap();
- assert_that(cargo_process("new").arg("foo/components/subcomponent")
- .env("USER", "foo"),
- execs().with_status(0));
-
- assert_that(&paths::root().join("foo/components/subcomponent/.git"),
- is_not(existing_file()));
- assert_that(&paths::root().join("foo/components/subcomponent/.gitignore"),
- is_not(existing_file()));
-}
-
-#[test]
-fn subpackage_git_with_vcs_arg() {
- assert_that(cargo_process("new").arg("foo").env("USER", "foo"),
- execs().with_status(0));
-
- let subpackage = paths::root().join("foo").join("components");
- fs::create_dir(&subpackage).unwrap();
- assert_that(cargo_process("new").arg("foo/components/subcomponent")
- .arg("--vcs").arg("git")
- .env("USER", "foo"),
- execs().with_status(0));
-
- assert_that(&paths::root().join("foo/components/subcomponent/.git"),
- existing_dir());
- assert_that(&paths::root().join("foo/components/subcomponent/.gitignore"),
- existing_file());
-}
-
-#[test]
-fn unknown_flags() {
- assert_that(cargo_process("new").arg("foo").arg("--flag"),
- execs().with_status(1)
- .with_stderr("\
-[ERROR] Unknown flag: '--flag'
-
-Usage:
- cargo new [..]
- cargo new [..]
-"));
-}
-
-#[test]
-fn explicit_invalid_name_not_suggested() {
- assert_that(cargo_process("new").arg("--name").arg("10-invalid").arg("a"),
- execs().with_status(101)
- .with_stderr("\
-[ERROR] Package names starting with a digit cannot be used as a crate name"));
-}
+++ /dev/null
-extern crate cargotest;
-extern crate hamcrest;
-
-use cargotest::support::git;
-use cargotest::support::paths;
-use cargotest::support::registry::Package;
-use cargotest::support::{execs, project};
-use hamcrest::assert_that;
-
-#[test]
-fn override_simple() {
- Package::new("foo", "0.1.0").publish();
-
- let foo = git::repo(&paths::root().join("override"))
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
- "#)
- .file("src/lib.rs", "pub fn foo() {}")
- .build();
-
- let p = project("local")
- .file("Cargo.toml", &format!(r#"
- [package]
- name = "local"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- foo = "0.1.0"
-
- [replace]
- "foo:0.1.0" = {{ git = '{}' }}
- "#, foo.url()))
- .file("src/lib.rs", "
- extern crate foo;
- pub fn bar() {
- foo::foo();
- }
- ")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr("\
-[UPDATING] registry `file://[..]`
-[UPDATING] git repository `[..]`
-[COMPILING] foo v0.1.0 (file://[..])
-[COMPILING] local v0.0.1 (file://[..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-}
-
-#[test]
-fn missing_version() {
- let p = project("local")
- .file("Cargo.toml", r#"
- [package]
- name = "local"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- foo = "0.1.0"
-
- [replace]
- foo = { git = 'https://example.com' }
- "#)
- .file("src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(101).with_stderr("\
-error: failed to parse manifest at `[..]`
-
-Caused by:
- replacements must specify a version to replace, but `[..]foo` does not
-"));
-}
-
-#[test]
-fn invalid_semver_version() {
- let p = project("local")
- .file("Cargo.toml", r#"
- [package]
- name = "local"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- foo = "*"
-
- [replace]
- "foo:*" = { git = 'https://example.com' }
- "#)
- .file("src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(101).with_stderr_contains("\
-error: failed to parse manifest at `[..]`
-
-Caused by:
- replacements must specify a valid semver version to replace, but `foo:*` does not
-"));
-}
-
-#[test]
-fn different_version() {
- Package::new("foo", "0.2.0").publish();
- Package::new("foo", "0.1.0").publish();
-
- let p = project("local")
- .file("Cargo.toml", r#"
- [package]
- name = "local"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- foo = "0.1.0"
-
- [replace]
- "foo:0.1.0" = "0.2.0"
- "#)
- .file("src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(101).with_stderr("\
-error: failed to parse manifest at `[..]`
-
-Caused by:
- replacements cannot specify a version requirement, but found one for [..]
-"));
-}
-
-#[test]
-fn transitive() {
- Package::new("foo", "0.1.0").publish();
- Package::new("bar", "0.2.0")
- .dep("foo", "0.1.0")
- .file("src/lib.rs", "extern crate foo; fn bar() { foo::foo(); }")
- .publish();
-
- let foo = git::repo(&paths::root().join("override"))
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
- "#)
- .file("src/lib.rs", "pub fn foo() {}")
- .build();
-
- let p = project("local")
- .file("Cargo.toml", &format!(r#"
- [package]
- name = "local"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- bar = "0.2.0"
-
- [replace]
- "foo:0.1.0" = {{ git = '{}' }}
- "#, foo.url()))
- .file("src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr("\
-[UPDATING] registry `file://[..]`
-[UPDATING] git repository `[..]`
-[DOWNLOADING] bar v0.2.0 (registry [..])
-[COMPILING] foo v0.1.0 (file://[..])
-[COMPILING] bar v0.2.0
-[COMPILING] local v0.0.1 (file://[..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-
- assert_that(p.cargo("build"), execs().with_status(0).with_stdout(""));
-}
-
-#[test]
-fn persists_across_rebuilds() {
- Package::new("foo", "0.1.0").publish();
-
- let foo = git::repo(&paths::root().join("override"))
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
- "#)
- .file("src/lib.rs", "pub fn foo() {}")
- .build();
-
- let p = project("local")
- .file("Cargo.toml", &format!(r#"
- [package]
- name = "local"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- foo = "0.1.0"
-
- [replace]
- "foo:0.1.0" = {{ git = '{}' }}
- "#, foo.url()))
- .file("src/lib.rs", "
- extern crate foo;
- pub fn bar() {
- foo::foo();
- }
- ")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr("\
-[UPDATING] registry `file://[..]`
-[UPDATING] git repository `file://[..]`
-[COMPILING] foo v0.1.0 (file://[..])
-[COMPILING] local v0.0.1 (file://[..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stdout(""));
-}
-
-#[test]
-fn replace_registry_with_path() {
- Package::new("foo", "0.1.0").publish();
-
- let _ = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
- "#)
- .file("src/lib.rs", "pub fn foo() {}")
- .build();
-
- let p = project("local")
- .file("Cargo.toml", r#"
- [package]
- name = "local"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- foo = "0.1.0"
-
- [replace]
- "foo:0.1.0" = { path = "../foo" }
- "#)
- .file("src/lib.rs", "
- extern crate foo;
- pub fn bar() {
- foo::foo();
- }
- ")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr("\
-[UPDATING] registry `file://[..]`
-[COMPILING] foo v0.1.0 (file://[..])
-[COMPILING] local v0.0.1 (file://[..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-}
-
-#[test]
-fn use_a_spec_to_select() {
- Package::new("foo", "0.1.1")
- .file("src/lib.rs", "pub fn foo1() {}")
- .publish();
- Package::new("foo", "0.2.0").publish();
- Package::new("bar", "0.1.1")
- .dep("foo", "0.2")
- .file("src/lib.rs", "
- extern crate foo;
- pub fn bar() { foo::foo3(); }
- ")
- .publish();
-
- let foo = git::repo(&paths::root().join("override"))
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.2.0"
- authors = []
- "#)
- .file("src/lib.rs", "pub fn foo3() {}")
- .build();
-
- let p = project("local")
- .file("Cargo.toml", &format!(r#"
- [package]
- name = "local"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- bar = "0.1"
- foo = "0.1"
-
- [replace]
- "foo:0.2.0" = {{ git = '{}' }}
- "#, foo.url()))
- .file("src/lib.rs", "
- extern crate foo;
- extern crate bar;
-
- pub fn local() {
- foo::foo1();
- bar::bar();
- }
- ")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr("\
-[UPDATING] registry `file://[..]`
-[UPDATING] git repository `[..]`
-[DOWNLOADING] [..]
-[DOWNLOADING] [..]
-[COMPILING] [..]
-[COMPILING] [..]
-[COMPILING] [..]
-[COMPILING] local v0.0.1 (file://[..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-}
-
-#[test]
-fn override_adds_some_deps() {
- Package::new("foo", "0.1.1").publish();
- Package::new("bar", "0.1.0").publish();
-
- let foo = git::repo(&paths::root().join("override"))
- .file("Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.1.0"
- authors = []
-
- [dependencies]
- foo = "0.1"
- "#)
- .file("src/lib.rs", "")
- .build();
-
- let p = project("local")
- .file("Cargo.toml", &format!(r#"
- [package]
- name = "local"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- bar = "0.1"
-
- [replace]
- "bar:0.1.0" = {{ git = '{}' }}
- "#, foo.url()))
- .file("src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr("\
-[UPDATING] registry `file://[..]`
-[UPDATING] git repository `[..]`
-[DOWNLOADING] foo v0.1.1 (registry [..])
-[COMPILING] foo v0.1.1
-[COMPILING] bar v0.1.0 ([..])
-[COMPILING] local v0.0.1 (file://[..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-
- assert_that(p.cargo("build"), execs().with_status(0).with_stdout(""));
-
- Package::new("foo", "0.1.2").publish();
- assert_that(p.cargo("update").arg("-p").arg(&format!("{}#bar", foo.url())),
- execs().with_status(0).with_stderr("\
-[UPDATING] git repository `file://[..]`
-"));
- assert_that(p.cargo("update")
- .arg("-p")
- .arg("https://github.com/rust-lang/crates.io-index#bar"),
- execs().with_status(0).with_stderr("\
-[UPDATING] registry `file://[..]`
-"));
-
- assert_that(p.cargo("build"), execs().with_status(0).with_stdout(""));
-}
-
-#[test]
-fn locked_means_locked_yes_no_seriously_i_mean_locked() {
- // this in theory exercises #2041
- Package::new("foo", "0.1.0").publish();
- Package::new("foo", "0.2.0").publish();
- Package::new("bar", "0.1.0").publish();
-
- let foo = git::repo(&paths::root().join("override"))
- .file("Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.1.0"
- authors = []
-
- [dependencies]
- foo = "*"
- "#)
- .file("src/lib.rs", "")
- .build();
-
- let p = project("local")
- .file("Cargo.toml", &format!(r#"
- [package]
- name = "local"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- foo = "0.1"
- bar = "0.1"
-
- [replace]
- "bar:0.1.0" = {{ git = '{}' }}
- "#, foo.url()))
- .file("src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0));
-
- assert_that(p.cargo("build"), execs().with_status(0).with_stdout(""));
- assert_that(p.cargo("build"), execs().with_status(0).with_stdout(""));
-}
-
-#[test]
-fn override_wrong_name() {
- Package::new("foo", "0.1.0").publish();
-
- let foo = git::repo(&paths::root().join("override"))
- .file("Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.1.0"
- authors = []
- "#)
- .file("src/lib.rs", "")
- .build();
-
- let p = project("local")
- .file("Cargo.toml", &format!(r#"
- [package]
- name = "local"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- foo = "0.1"
-
- [replace]
- "foo:0.1.0" = {{ git = '{}' }}
- "#, foo.url()))
- .file("src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(101).with_stderr("\
-[UPDATING] registry [..]
-[UPDATING] git repository [..]
-error: no matching package for override `[..]foo:0.1.0` found
-location searched: file://[..]
-version required: = 0.1.0
-"));
-}
-
-#[test]
-fn override_with_nothing() {
- Package::new("foo", "0.1.0").publish();
-
- let foo = git::repo(&paths::root().join("override"))
- .file("src/lib.rs", "")
- .build();
-
- let p = project("local")
- .file("Cargo.toml", &format!(r#"
- [package]
- name = "local"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- foo = "0.1"
-
- [replace]
- "foo:0.1.0" = {{ git = '{}' }}
- "#, foo.url()))
- .file("src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(101).with_stderr("\
-[UPDATING] registry [..]
-[UPDATING] git repository [..]
-[ERROR] failed to load source for a dependency on `foo`
-
-Caused by:
- Unable to update file://[..]
-
-Caused by:
- Could not find Cargo.toml in `[..]`
-"));
-}
-
-#[test]
-fn override_wrong_version() {
- let p = project("local")
- .file("Cargo.toml", r#"
- [package]
- name = "local"
- version = "0.0.1"
- authors = []
-
- [replace]
- "foo:0.1.0" = { git = 'https://example.com', version = '0.2.0' }
- "#)
- .file("src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(101).with_stderr("\
-error: failed to parse manifest at `[..]`
-
-Caused by:
- replacements cannot specify a version requirement, but found one for `[..]foo:0.1.0`
-"));
-}
-
-#[test]
-fn multiple_specs() {
- Package::new("foo", "0.1.0").publish();
-
- let foo = git::repo(&paths::root().join("override"))
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
- "#)
- .file("src/lib.rs", "pub fn foo() {}")
- .build();
-
- let p = project("local")
- .file("Cargo.toml", &format!(r#"
- [package]
- name = "local"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- foo = "0.1.0"
-
- [replace]
- "foo:0.1.0" = {{ git = '{0}' }}
-
- [replace."https://github.com/rust-lang/crates.io-index#foo:0.1.0"]
- git = '{0}'
- "#, foo.url()))
- .file("src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(101).with_stderr("\
-[UPDATING] registry [..]
-[UPDATING] git repository [..]
-error: overlapping replacement specifications found:
-
- * [..]
- * [..]
-
-both specifications match: foo v0.1.0
-"));
-}
-
-#[test]
-fn test_override_dep() {
- Package::new("foo", "0.1.0").publish();
-
- let foo = git::repo(&paths::root().join("override"))
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
- "#)
- .file("src/lib.rs", "pub fn foo() {}")
- .build();
-
- let p = project("local")
- .file("Cargo.toml", &format!(r#"
- [package]
- name = "local"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- foo = "0.1.0"
-
- [replace]
- "foo:0.1.0" = {{ git = '{0}' }}
- "#, foo.url()))
- .file("src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("test").arg("-p").arg("foo"),
- execs().with_status(101)
- .with_stderr_contains("\
-error: There are multiple `foo` packages in your project, and the [..]
-Please re-run this command with [..]
- [..]#foo:0.1.0
- [..]#foo:0.1.0
-"));
-}
-
-#[test]
-fn update() {
- Package::new("foo", "0.1.0").publish();
-
- let foo = git::repo(&paths::root().join("override"))
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
- "#)
- .file("src/lib.rs", "pub fn foo() {}")
- .build();
-
- let p = project("local")
- .file("Cargo.toml", &format!(r#"
- [package]
- name = "local"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- foo = "0.1.0"
-
- [replace]
- "foo:0.1.0" = {{ git = '{0}' }}
- "#, foo.url()))
- .file("src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("generate-lockfile"),
- execs().with_status(0));
- assert_that(p.cargo("update"),
- execs().with_status(0)
- .with_stderr("\
-[UPDATING] registry `[..]`
-[UPDATING] git repository `[..]`
-"));
-}
-
-// local -> near -> far
-// near is overridden with itself
-#[test]
-fn no_override_self() {
- let deps = git::repo(&paths::root().join("override"))
-
- .file("far/Cargo.toml", r#"
- [package]
- name = "far"
- version = "0.1.0"
- authors = []
- "#)
- .file("far/src/lib.rs", "")
-
- .file("near/Cargo.toml", r#"
- [package]
- name = "near"
- version = "0.1.0"
- authors = []
-
- [dependencies]
- far = { path = "../far" }
- "#)
- .file("near/src/lib.rs", r#"
- #![no_std]
- pub extern crate far;
- "#)
- .build();
-
- let p = project("local")
- .file("Cargo.toml", &format!(r#"
- [package]
- name = "local"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- near = {{ git = '{0}' }}
-
- [replace]
- "near:0.1.0" = {{ git = '{0}' }}
- "#, deps.url()))
- .file("src/lib.rs", r#"
- #![no_std]
- pub extern crate near;
- "#)
- .build();
-
- assert_that(p.cargo("build").arg("--verbose"),
- execs().with_status(0));
-}
-
-#[test]
-fn broken_path_override_warns() {
- Package::new("foo", "0.1.0").publish();
- Package::new("foo", "0.2.0").publish();
-
- let p = project("local")
- .file("Cargo.toml", r#"
- [package]
- name = "local"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- a = { path = "a1" }
- "#)
- .file("src/lib.rs", "")
- .file("a1/Cargo.toml", r#"
- [package]
- name = "a"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- foo = "0.1"
- "#)
- .file("a1/src/lib.rs", "")
- .file("a2/Cargo.toml", r#"
- [package]
- name = "a"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- foo = "0.2"
- "#)
- .file("a2/src/lib.rs", "")
- .file(".cargo/config", r#"
- paths = ["a2"]
- "#)
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0)
- .with_stderr("\
-[UPDATING] [..]
-warning: path override for crate `a` has altered the original list of
-dependencies; the dependency on `foo` was either added or
-modified to not match the previously resolved version
-
-This is currently allowed but is known to produce buggy behavior with spurious
-recompiles and changes to the crate graph. Path overrides unfortunately were
-never intended to support this feature, so for now this message is just a
-warning. In the future, however, this message will become a hard error.
-
-To change the dependency graph via an override it's recommended to use the
-`[replace]` feature of Cargo instead of the path override feature. This is
-documented online at the url below for more information.
-
-http://doc.crates.io/specifying-dependencies.html#overriding-dependencies
-
-[DOWNLOADING] [..]
-[COMPILING] [..]
-[COMPILING] [..]
-[COMPILING] [..]
-[FINISHED] [..]
-"));
-}
-
-#[test]
-fn override_an_override() {
- Package::new("chrono", "0.2.0").dep("serde", "< 0.9").publish();
- Package::new("serde", "0.7.0")
- .file("src/lib.rs", "pub fn serde07() {}")
- .publish();
- Package::new("serde", "0.8.0")
- .file("src/lib.rs", "pub fn serde08() {}")
- .publish();
-
- let p = project("local")
- .file("Cargo.toml", r#"
- [package]
- name = "local"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- chrono = "0.2"
- serde = "0.8"
-
- [replace]
- "chrono:0.2.0" = { path = "chrono" }
- "serde:0.8.0" = { path = "serde" }
- "#)
- .file("Cargo.lock", r#"
- [[package]]
- name = "local"
- version = "0.0.1"
- dependencies = [
- "chrono 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
- ]
-
- [[package]]
- name = "chrono"
- version = "0.2.0"
- source = "registry+https://github.com/rust-lang/crates.io-index"
- replace = "chrono 0.2.0"
-
- [[package]]
- name = "chrono"
- version = "0.2.0"
- dependencies = [
- "serde 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
- ]
-
- [[package]]
- name = "serde"
- version = "0.7.0"
- source = "registry+https://github.com/rust-lang/crates.io-index"
-
- [[package]]
- name = "serde"
- version = "0.8.0"
- source = "registry+https://github.com/rust-lang/crates.io-index"
- replace = "serde 0.8.0"
-
- [[package]]
- name = "serde"
- version = "0.8.0"
- "#)
- .file("src/lib.rs", "
- extern crate chrono;
- extern crate serde;
-
- pub fn local() {
- chrono::chrono();
- serde::serde08_override();
- }
- ")
- .file("chrono/Cargo.toml", r#"
- [package]
- name = "chrono"
- version = "0.2.0"
- authors = []
-
- [dependencies]
- serde = "< 0.9"
- "#)
- .file("chrono/src/lib.rs", "
- extern crate serde;
- pub fn chrono() {
- serde::serde07();
- }
- ")
- .file("serde/Cargo.toml", r#"
- [package]
- name = "serde"
- version = "0.8.0"
- authors = []
- "#)
- .file("serde/src/lib.rs", "
- pub fn serde08_override() {}
- ")
- .build();
-
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(0));
-}
-
-#[test]
-fn overriding_nonexistent_no_spurious() {
- Package::new("foo", "0.1.0").dep("bar", "0.1").publish();
- Package::new("bar", "0.1.0").publish();
-
- let foo = git::repo(&paths::root().join("override"))
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
-
- [dependencies]
- bar = { path = "bar" }
- "#)
- .file("src/lib.rs", "pub fn foo() {}")
- .file("bar/Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.1.0"
- authors = []
- "#)
- .file("bar/src/lib.rs", "pub fn foo() {}")
- .build();
-
-
- let p = project("local")
- .file("Cargo.toml", &format!(r#"
- [package]
- name = "local"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- foo = "0.1.0"
-
- [replace]
- "foo:0.1.0" = {{ git = '{url}' }}
- "bar:0.1.0" = {{ git = '{url}' }}
- "#, url = foo.url()))
- .file("src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0));
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr("\
-[WARNING] package replacement is not used: [..]bar:0.1.0
-[FINISHED] [..]
-").with_stdout(""));
-}
-
-#[test]
-fn no_warnings_when_replace_is_used_in_another_workspace_member() {
- Package::new("foo", "0.1.0").publish();
- Package::new("bar", "0.1.0").publish();
-
- let p = project("ws")
- .file("Cargo.toml", r#"
- [workspace]
- members = [ "first_crate", "second_crate"]
-
- [replace]
- "foo:0.1.0" = { path = "local_foo" }"#)
- .file("first_crate/Cargo.toml", r#"
- [package]
- name = "first_crate"
- version = "0.1.0"
-
- [dependencies]
- foo = "0.1.0"
- "#)
- .file("first_crate/src/lib.rs", "")
- .file("second_crate/Cargo.toml", r#"
- [package]
- name = "second_crate"
- version = "0.1.0"
- "#)
- .file("second_crate/src/lib.rs", "")
- .file("local_foo/Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- "#)
- .file("local_foo/src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build").cwd(p.root().join("first_crate")),
- execs().with_status(0)
- .with_stdout("")
- .with_stderr("\
-[UPDATING] registry `[..]`
-[COMPILING] foo v0.1.0 ([..])
-[COMPILING] first_crate v0.1.0 ([..])
-[FINISHED] [..]"));
-
- assert_that(p.cargo("build").cwd(p.root().join("second_crate")),
- execs().with_status(0)
- .with_stdout("")
- .with_stderr("\
-[COMPILING] second_crate v0.1.0 ([..])
-[FINISHED] [..]"));
-}
-
-
-#[test]
-fn override_to_path_dep() {
- Package::new("foo", "0.1.0").dep("bar", "0.1").publish();
- Package::new("bar", "0.1.0").publish();
-
- let p = project("local")
- .file("Cargo.toml", r#"
- [package]
- name = "local"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- foo = "0.1.0"
- "#)
- .file("src/lib.rs", "")
- .file("foo/Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- bar = { path = "bar" }
- "#)
- .file("foo/src/lib.rs", "")
- .file("foo/bar/Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
- "#)
- .file("foo/bar/src/lib.rs", "")
- .file(".cargo/config", r#"
- paths = ["foo"]
- "#)
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0));
-}
-
-#[test]
-fn replace_to_path_dep() {
- Package::new("foo", "0.1.0").dep("bar", "0.1").publish();
- Package::new("bar", "0.1.0").publish();
-
- let p = project("local")
- .file("Cargo.toml", r#"
- [package]
- name = "local"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- foo = "0.1.0"
-
- [replace]
- "foo:0.1.0" = { path = "foo" }
- "#)
- .file("src/lib.rs", "extern crate foo;")
- .file("foo/Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
-
- [dependencies]
- bar = { path = "bar" }
- "#)
- .file("foo/src/lib.rs", "
- extern crate bar;
-
- pub fn foo() {
- bar::bar();
- }
- ")
- .file("foo/bar/Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.1.0"
- authors = []
- "#)
- .file("foo/bar/src/lib.rs", "pub fn bar() {}")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0));
-}
-
-#[test]
-fn paths_ok_with_optional() {
- Package::new("bar", "0.1.0").publish();
-
- let p = project("local")
- .file("Cargo.toml", r#"
- [package]
- name = "local"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- foo = { path = "foo" }
- "#)
- .file("src/lib.rs", "")
- .file("foo/Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
-
- [dependencies]
- bar = { version = "0.1", optional = true }
- "#)
- .file("foo/src/lib.rs", "")
- .file("foo2/Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
-
- [dependencies]
- bar = { version = "0.1", optional = true }
- "#)
- .file("foo2/src/lib.rs", "")
- .file(".cargo/config", r#"
- paths = ["foo2"]
- "#)
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr("\
-[COMPILING] foo v0.1.0 ([..]foo2)
-[COMPILING] local v0.0.1 ([..])
-[FINISHED] [..]
-"));
-}
-
-#[test]
-fn paths_add_optional_bad() {
- Package::new("bar", "0.1.0").publish();
-
- let p = project("local")
- .file("Cargo.toml", r#"
- [package]
- name = "local"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- foo = { path = "foo" }
- "#)
- .file("src/lib.rs", "")
- .file("foo/Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
- "#)
- .file("foo/src/lib.rs", "")
- .file("foo2/Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
-
- [dependencies]
- bar = { version = "0.1", optional = true }
- "#)
- .file("foo2/src/lib.rs", "")
- .file(".cargo/config", r#"
- paths = ["foo2"]
- "#)
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr_contains("\
-warning: path override for crate `foo` has altered the original list of
-dependencies; the dependency on `bar` was either added or\
-"));
-}
-
-#[test]
-fn override_with_default_feature() {
- Package::new("another", "0.1.0").publish();
- Package::new("another", "0.1.1")
- .dep("bar", "0.1")
- .publish();
- Package::new("bar", "0.1.0").publish();
-
- let p = project("local")
- .file("Cargo.toml", r#"
- [package]
- name = "local"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- bar = { path = "bar", default-features = false }
- another = "0.1"
- another2 = { path = "another2" }
-
- [replace]
- 'bar:0.1.0' = { path = "bar" }
- "#)
- .file("src/main.rs", r#"
- extern crate bar;
-
- fn main() {
- bar::bar();
- }
- "#)
- .file("bar/Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.1.0"
- authors = []
-
- [features]
- default = []
- "#)
- .file("bar/src/lib.rs", r#"
- #[cfg(feature = "default")]
- pub fn bar() {}
- "#)
- .file("another2/Cargo.toml", r#"
- [package]
- name = "another2"
- version = "0.1.0"
- authors = []
-
- [dependencies]
- bar = { version = "0.1", default-features = false }
- "#)
- .file("another2/src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("run"),
- execs().with_status(0));
-}
-
-#[test]
-fn override_plus_dep() {
- Package::new("bar", "0.1.0").publish();
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- bar = "0.1"
-
- [replace]
- 'bar:0.1.0' = { path = "bar" }
- "#)
- .file("src/lib.rs", "")
- .file("bar/Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.1.0"
- authors = []
-
- [dependencies]
- foo = { path = ".." }
- "#)
- .file("bar/src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(101).with_stderr_contains("\
-error: cyclic package dependency: [..]
-"));
-}
+++ /dev/null
-#[macro_use]
-extern crate cargotest;
-extern crate flate2;
-extern crate git2;
-extern crate hamcrest;
-extern crate tar;
-
-use std::fs::File;
-use std::io::prelude::*;
-use std::path::{Path, PathBuf};
-
-use cargotest::{cargo_process, process, ChannelChanger};
-use cargotest::support::{project, execs, paths, git, path2url, cargo_exe, registry};
-use cargotest::support::registry::Package;
-use flate2::read::GzDecoder;
-use hamcrest::{assert_that, existing_file, contains, equal_to};
-use tar::Archive;
-
-#[test]
-fn simple() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- exclude = ["*.txt"]
- license = "MIT"
- description = "foo"
- "#)
- .file("src/main.rs", r#"
- fn main() { println!("hello"); }
- "#)
- .file("src/bar.txt", "") // should be ignored when packaging
- .build();
-
- assert_that(p.cargo("package"),
- execs().with_status(0).with_stderr(&format!("\
-[WARNING] manifest has no documentation[..]
-See [..]
-[PACKAGING] foo v0.0.1 ({dir})
-[VERIFYING] foo v0.0.1 ({dir})
-[COMPILING] foo v0.0.1 ({dir}[..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-",
- dir = p.url())));
- assert_that(&p.root().join("target/package/foo-0.0.1.crate"), existing_file());
- assert_that(p.cargo("package").arg("-l"),
- execs().with_status(0).with_stdout("\
-Cargo.toml
-src[/]main.rs
-"));
- assert_that(p.cargo("package"),
- execs().with_status(0).with_stdout(""));
-
- let f = File::open(&p.root().join("target/package/foo-0.0.1.crate")).unwrap();
- let mut rdr = GzDecoder::new(f);
- let mut contents = Vec::new();
- rdr.read_to_end(&mut contents).unwrap();
- let mut ar = Archive::new(&contents[..]);
- for f in ar.entries().unwrap() {
- let f = f.unwrap();
- let fname = f.header().path_bytes();
- let fname = &*fname;
- assert!(fname == b"foo-0.0.1/Cargo.toml" ||
- fname == b"foo-0.0.1/Cargo.toml.orig" ||
- fname == b"foo-0.0.1/src/main.rs",
- "unexpected filename: {:?}", f.header().path())
- }
-}
-
-#[test]
-fn metadata_warning() {
- let p = project("all")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/main.rs", r#"
- fn main() {}
- "#)
- .build();
- assert_that(p.cargo("package"),
- execs().with_status(0).with_stderr(&format!("\
-warning: manifest has no description, license, license-file, documentation, \
-homepage or repository.
-See http://doc.crates.io/manifest.html#package-metadata for more info.
-[PACKAGING] foo v0.0.1 ({dir})
-[VERIFYING] foo v0.0.1 ({dir})
-[COMPILING] foo v0.0.1 ({dir}[..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-",
- dir = p.url())));
-
- let p = project("one")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- license = "MIT"
- "#)
- .file("src/main.rs", r#"
- fn main() {}
- "#)
- .build();
- assert_that(p.cargo("package"),
- execs().with_status(0).with_stderr(&format!("\
-warning: manifest has no description, documentation, homepage or repository.
-See http://doc.crates.io/manifest.html#package-metadata for more info.
-[PACKAGING] foo v0.0.1 ({dir})
-[VERIFYING] foo v0.0.1 ({dir})
-[COMPILING] foo v0.0.1 ({dir}[..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-",
- dir = p.url())));
-
- let p = project("all")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- license = "MIT"
- description = "foo"
- repository = "bar"
- "#)
- .file("src/main.rs", r#"
- fn main() {}
- "#)
- .build();
- assert_that(p.cargo("package"),
- execs().with_status(0).with_stderr(&format!("\
-[PACKAGING] foo v0.0.1 ({dir})
-[VERIFYING] foo v0.0.1 ({dir})
-[COMPILING] foo v0.0.1 ({dir}[..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-",
- dir = p.url())));
-}
-
-#[test]
-fn package_verbose() {
- let root = paths::root().join("all");
- let p = git::repo(&root)
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/main.rs", r#"
- fn main() {}
- "#)
- .file("a/Cargo.toml", r#"
- [project]
- name = "a"
- version = "0.0.1"
- authors = []
- "#)
- .file("a/src/lib.rs", "")
- .build();
- let mut cargo = cargo_process();
- cargo.cwd(p.root());
- assert_that(cargo.clone().arg("build"), execs().with_status(0));
-
- println!("package main repo");
- assert_that(cargo.clone().arg("package").arg("-v").arg("--no-verify"),
- execs().with_status(0).with_stderr("\
-[WARNING] manifest has no description[..]
-See http://doc.crates.io/manifest.html#package-metadata for more info.
-[PACKAGING] foo v0.0.1 ([..])
-[ARCHIVING] [..]
-[ARCHIVING] [..]
-"));
-
- println!("package sub-repo");
- assert_that(cargo.arg("package").arg("-v").arg("--no-verify")
- .cwd(p.root().join("a")),
- execs().with_status(0).with_stderr("\
-[WARNING] manifest has no description[..]
-See http://doc.crates.io/manifest.html#package-metadata for more info.
-[PACKAGING] a v0.0.1 ([..])
-[ARCHIVING] [..]
-[ARCHIVING] [..]
-"));
-}
-
-#[test]
-fn package_verification() {
- let p = project("all")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/main.rs", r#"
- fn main() {}
- "#)
- .build();
- assert_that(p.cargo("build"),
- execs().with_status(0));
- assert_that(p.cargo("package"),
- execs().with_status(0).with_stderr(&format!("\
-[WARNING] manifest has no description[..]
-See http://doc.crates.io/manifest.html#package-metadata for more info.
-[PACKAGING] foo v0.0.1 ({dir})
-[VERIFYING] foo v0.0.1 ({dir})
-[COMPILING] foo v0.0.1 ({dir}[..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-",
- dir = p.url())));
-}
-
-#[test]
-fn path_dependency_no_version() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- license = "MIT"
- description = "foo"
-
- [dependencies.bar]
- path = "bar"
- "#)
- .file("src/main.rs", "fn main() {}")
- .file("bar/Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
- "#)
- .file("bar/src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("package"),
- execs().with_status(101).with_stderr("\
-[WARNING] manifest has no documentation, homepage or repository.
-See http://doc.crates.io/manifest.html#package-metadata for more info.
-[ERROR] all path dependencies must have a version specified when packaging.
-dependency `bar` does not specify a version.
-"));
-}
-
-#[test]
-fn exclude() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- exclude = [
- "*.txt",
- # file in root
- "file_root_1", # NO_CHANGE (ignored)
- "/file_root_2", # CHANGING (packaged -> ignored)
- "file_root_3/", # NO_CHANGE (packaged)
- "file_root_4/*", # NO_CHANGE (packaged)
- "file_root_5/**", # NO_CHANGE (packaged)
- # file in sub-dir
- "file_deep_1", # CHANGING (packaged -> ignored)
- "/file_deep_2", # NO_CHANGE (packaged)
- "file_deep_3/", # NO_CHANGE (packaged)
- "file_deep_4/*", # NO_CHANGE (packaged)
- "file_deep_5/**", # NO_CHANGE (packaged)
- # dir in root
- "dir_root_1", # CHANGING (packaged -> ignored)
- "/dir_root_2", # CHANGING (packaged -> ignored)
- "dir_root_3/", # CHANGING (packaged -> ignored)
- "dir_root_4/*", # NO_CHANGE (ignored)
- "dir_root_5/**", # NO_CHANGE (ignored)
- # dir in sub-dir
- "dir_deep_1", # CHANGING (packaged -> ignored)
- "/dir_deep_2", # NO_CHANGE
- "dir_deep_3/", # CHANGING (packaged -> ignored)
- "dir_deep_4/*", # CHANGING (packaged -> ignored)
- "dir_deep_5/**", # CHANGING (packaged -> ignored)
- ]
- "#)
- .file("src/main.rs", r#"
- fn main() { println!("hello"); }
- "#)
- .file("bar.txt", "")
- .file("src/bar.txt", "")
- // file in root
- .file("file_root_1", "")
- .file("file_root_2", "")
- .file("file_root_3", "")
- .file("file_root_4", "")
- .file("file_root_5", "")
- // file in sub-dir
- .file("some_dir/file_deep_1", "")
- .file("some_dir/file_deep_2", "")
- .file("some_dir/file_deep_3", "")
- .file("some_dir/file_deep_4", "")
- .file("some_dir/file_deep_5", "")
- // dir in root
- .file("dir_root_1/some_dir/file", "")
- .file("dir_root_2/some_dir/file", "")
- .file("dir_root_3/some_dir/file", "")
- .file("dir_root_4/some_dir/file", "")
- .file("dir_root_5/some_dir/file", "")
- // dir in sub-dir
- .file("some_dir/dir_deep_1/some_dir/file", "")
- .file("some_dir/dir_deep_2/some_dir/file", "")
- .file("some_dir/dir_deep_3/some_dir/file", "")
- .file("some_dir/dir_deep_4/some_dir/file", "")
- .file("some_dir/dir_deep_5/some_dir/file", "")
- .build();
-
- assert_that(p.cargo("package").arg("--no-verify").arg("-v"),
- execs().with_status(0).with_stdout("").with_stderr("\
-[WARNING] manifest has no description[..]
-See http://doc.crates.io/manifest.html#package-metadata for more info.
-[PACKAGING] foo v0.0.1 ([..])
-[WARNING] [..] file `dir_root_1[/]some_dir[/]file` WILL be excluded [..]
-See [..]
-[WARNING] [..] file `dir_root_2[/]some_dir[/]file` WILL be excluded [..]
-See [..]
-[WARNING] [..] file `dir_root_3[/]some_dir[/]file` WILL be excluded [..]
-See [..]
-[WARNING] [..] file `some_dir[/]dir_deep_1[/]some_dir[/]file` WILL be excluded [..]
-See [..]
-[WARNING] [..] file `some_dir[/]dir_deep_3[/]some_dir[/]file` WILL be excluded [..]
-See [..]
-[WARNING] [..] file `some_dir[/]file_deep_1` WILL be excluded [..]
-See [..]
-[ARCHIVING] [..]
-[ARCHIVING] [..]
-[ARCHIVING] [..]
-[ARCHIVING] [..]
-[ARCHIVING] [..]
-[ARCHIVING] [..]
-[ARCHIVING] [..]
-[ARCHIVING] [..]
-[ARCHIVING] [..]
-[ARCHIVING] [..]
-[ARCHIVING] [..]
-[ARCHIVING] [..]
-[ARCHIVING] [..]
-[ARCHIVING] [..]
-[ARCHIVING] [..]
-[ARCHIVING] [..]
-[ARCHIVING] [..]
-[ARCHIVING] [..]
-"));
-
- assert_that(&p.root().join("target/package/foo-0.0.1.crate"), existing_file());
-
- assert_that(p.cargo("package").arg("-l"),
- execs().with_status(0).with_stdout("\
-Cargo.toml
-dir_root_1[/]some_dir[/]file
-dir_root_2[/]some_dir[/]file
-dir_root_3[/]some_dir[/]file
-file_root_3
-file_root_4
-file_root_5
-some_dir[/]dir_deep_1[/]some_dir[/]file
-some_dir[/]dir_deep_2[/]some_dir[/]file
-some_dir[/]dir_deep_3[/]some_dir[/]file
-some_dir[/]dir_deep_4[/]some_dir[/]file
-some_dir[/]dir_deep_5[/]some_dir[/]file
-some_dir[/]file_deep_1
-some_dir[/]file_deep_2
-some_dir[/]file_deep_3
-some_dir[/]file_deep_4
-some_dir[/]file_deep_5
-src[/]main.rs
-"));
-}
-
-#[test]
-fn include() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- exclude = ["*.txt"]
- include = ["foo.txt", "**/*.rs", "Cargo.toml"]
- "#)
- .file("foo.txt", "")
- .file("src/main.rs", r#"
- fn main() { println!("hello"); }
- "#)
- .file("src/bar.txt", "") // should be ignored when packaging
- .build();
-
- assert_that(p.cargo("package").arg("--no-verify").arg("-v"),
- execs().with_status(0).with_stderr("\
-[WARNING] manifest has no description[..]
-See http://doc.crates.io/manifest.html#package-metadata for more info.
-[PACKAGING] foo v0.0.1 ([..])
-[ARCHIVING] [..]
-[ARCHIVING] [..]
-[ARCHIVING] [..]
-"));
-}
-
-#[test]
-fn package_lib_with_bin() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/main.rs", r#"
- extern crate foo;
- fn main() {}
- "#)
- .file("src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("package").arg("-v"),
- execs().with_status(0));
-}
-
-#[test]
-fn package_git_submodule() {
- let project = git::new("foo", |project| {
- project.file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = ["foo@example.com"]
- license = "MIT"
- description = "foo"
- repository = "foo"
- "#)
- .file("src/lib.rs", "pub fn foo() {}")
- }).unwrap();
- let library = git::new("bar", |library| {
- library.file("Makefile", "all:")
- }).unwrap();
-
- let repository = git2::Repository::open(&project.root()).unwrap();
- let url = path2url(library.root()).to_string();
- git::add_submodule(&repository, &url, Path::new("bar"));
- git::commit(&repository);
-
- let repository = git2::Repository::open(&project.root().join("bar")).unwrap();
- repository.reset(&repository.revparse_single("HEAD").unwrap(),
- git2::ResetType::Hard, None).unwrap();
-
- assert_that(cargo_process().arg("package").cwd(project.root())
- .arg("--no-verify").arg("-v"),
- execs().with_status(0).with_stderr_contains("[ARCHIVING] bar/Makefile"));
-}
-
-#[test]
-fn no_duplicates_from_modified_tracked_files() {
- let root = paths::root().join("all");
- let p = git::repo(&root)
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/main.rs", r#"
- fn main() {}
- "#)
- .build();
- File::create(p.root().join("src/main.rs")).unwrap().write_all(br#"
- fn main() { println!("A change!"); }
- "#).unwrap();
- let mut cargo = cargo_process();
- cargo.cwd(p.root());
- assert_that(cargo.clone().arg("build"), execs().with_status(0));
- assert_that(cargo.arg("package").arg("--list"),
- execs().with_status(0).with_stdout("\
-Cargo.toml
-src/main.rs
-"));
-}
-
-#[test]
-fn ignore_nested() {
- let cargo_toml = r#"
- [project]
- name = "nested"
- version = "0.0.1"
- authors = []
- license = "MIT"
- description = "nested"
- "#;
- let main_rs = r#"
- fn main() { println!("hello"); }
- "#;
- let p = project("nested")
- .file("Cargo.toml", cargo_toml)
- .file("src/main.rs", main_rs)
- // If a project happens to contain a copy of itself, we should
- // ignore it.
- .file("a_dir/nested/Cargo.toml", cargo_toml)
- .file("a_dir/nested/src/main.rs", main_rs)
- .build();
-
- assert_that(p.cargo("package"),
- execs().with_status(0).with_stderr(&format!("\
-[WARNING] manifest has no documentation[..]
-See http://doc.crates.io/manifest.html#package-metadata for more info.
-[PACKAGING] nested v0.0.1 ({dir})
-[VERIFYING] nested v0.0.1 ({dir})
-[COMPILING] nested v0.0.1 ({dir}[..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-",
- dir = p.url())));
- assert_that(&p.root().join("target/package/nested-0.0.1.crate"), existing_file());
- assert_that(p.cargo("package").arg("-l"),
- execs().with_status(0).with_stdout("\
-Cargo.toml
-src[..]main.rs
-"));
- assert_that(p.cargo("package"),
- execs().with_status(0).with_stdout(""));
-
- let f = File::open(&p.root().join("target/package/nested-0.0.1.crate")).unwrap();
- let mut rdr = GzDecoder::new(f);
- let mut contents = Vec::new();
- rdr.read_to_end(&mut contents).unwrap();
- let mut ar = Archive::new(&contents[..]);
- for f in ar.entries().unwrap() {
- let f = f.unwrap();
- let fname = f.header().path_bytes();
- let fname = &*fname;
- assert!(fname == b"nested-0.0.1/Cargo.toml" ||
- fname == b"nested-0.0.1/Cargo.toml.orig" ||
- fname == b"nested-0.0.1/src/main.rs",
- "unexpected filename: {:?}", f.header().path())
- }
-}
-
-#[cfg(unix)] // windows doesn't allow these characters in filenames
-#[test]
-fn package_weird_characters() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/main.rs", r#"
- fn main() { println!("hello"); }
- "#)
- .file("src/:foo", "")
- .build();
-
- assert_that(p.cargo("package"),
- execs().with_status(101).with_stderr("\
-warning: [..]
-See [..]
-[PACKAGING] foo [..]
-[ERROR] failed to prepare local package for uploading
-
-Caused by:
- cannot package a filename with a special character `:`: src/:foo
-"));
-}
-
-#[test]
-fn repackage_on_source_change() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/main.rs", r#"
- fn main() { println!("hello"); }
- "#)
- .build();
-
- assert_that(p.cargo("package"),
- execs().with_status(0));
-
- // Add another source file
- let mut file = File::create(p.root().join("src").join("foo.rs")).unwrap_or_else(|e| {
- panic!("could not create file {}: {}", p.root().join("src/foo.rs").display(), e)
- });
-
- file.write_all(br#"
- fn main() { println!("foo"); }
- "#).unwrap();
- std::mem::drop(file);
-
- let mut pro = process(&cargo_exe());
- pro.arg("package").cwd(p.root());
-
- // Check that cargo rebuilds the tarball
- assert_that(pro, execs().with_status(0).with_stderr(&format!("\
-[WARNING] [..]
-See [..]
-[PACKAGING] foo v0.0.1 ({dir})
-[VERIFYING] foo v0.0.1 ({dir})
-[COMPILING] foo v0.0.1 ({dir}[..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-",
- dir = p.url())));
-
- // Check that the tarball contains the added file
- let f = File::open(&p.root().join("target/package/foo-0.0.1.crate")).unwrap();
- let mut rdr = GzDecoder::new(f);
- let mut contents = Vec::new();
- rdr.read_to_end(&mut contents).unwrap();
- let mut ar = Archive::new(&contents[..]);
- let entries = ar.entries().unwrap();
- let entry_paths = entries.map(|entry| {
- entry.unwrap().path().unwrap().into_owned()
- }).collect::<Vec<PathBuf>>();
- assert_that(&entry_paths, contains(vec![PathBuf::from("foo-0.0.1/src/foo.rs")]));
-}
-
-#[test]
-#[cfg(unix)]
-fn broken_symlink() {
- use std::os::unix::fs;
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- license = "MIT"
- description = 'foo'
- documentation = 'foo'
- homepage = 'foo'
- repository = 'foo'
- "#)
- .file("src/main.rs", r#"
- fn main() { println!("hello"); }
- "#)
- .build();
- t!(fs::symlink("nowhere", &p.root().join("src/foo.rs")));
-
- assert_that(p.cargo("package").arg("-v"),
- execs().with_status(101)
- .with_stderr_contains("\
-error: failed to prepare local package for uploading
-
-Caused by:
- failed to open for archiving: `[..]foo.rs`
-
-Caused by:
- [..]
-"));
-}
-
-#[test]
-fn do_not_package_if_repository_is_dirty() {
- let p = project("foo").build();
-
- // Create a Git repository containing a minimal Rust project.
- let _ = git::repo(&paths::root().join("foo"))
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- license = "MIT"
- description = "foo"
- documentation = "foo"
- homepage = "foo"
- repository = "foo"
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- // Modify Cargo.toml without committing the change.
- p.change_file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- license = "MIT"
- description = "foo"
- documentation = "foo"
- homepage = "foo"
- repository = "foo"
- # change
- "#);
-
- assert_that(p.cargo("package"),
- execs().with_status(101)
- .with_stderr("\
-error: 1 files in the working directory contain changes that were not yet \
-committed into git:
-
-Cargo.toml
-
-to proceed despite this, pass the `--allow-dirty` flag
-"));
-}
-
-#[test]
-fn generated_manifest() {
- Package::new("abc", "1.0.0").publish();
- Package::new("def", "1.0.0").publish();
- Package::new("ghi", "1.0.0").publish();
- let p = project("foo")
- .file("Cargo.toml", r#"
- cargo-features = ["alternative-registries"]
-
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- exclude = ["*.txt"]
- license = "MIT"
- description = "foo"
-
- [project.metadata]
- foo = 'bar'
-
- [workspace]
-
- [dependencies]
- bar = { path = "bar", version = "0.1" }
- def = { version = "1.0", registry = "alternative" }
- ghi = "1.0"
- abc = "1.0"
- "#)
- .file("src/main.rs", "")
- .file("bar/Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.1.0"
- authors = []
- "#)
- .file("bar/src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("package")
- .masquerade_as_nightly_cargo()
- .arg("--no-verify"),
- execs().with_status(0));
-
- let f = File::open(&p.root().join("target/package/foo-0.0.1.crate")).unwrap();
- let mut rdr = GzDecoder::new(f);
- let mut contents = Vec::new();
- rdr.read_to_end(&mut contents).unwrap();
- let mut ar = Archive::new(&contents[..]);
- let mut entry = ar.entries().unwrap()
- .map(|f| f.unwrap())
- .find(|e| e.path().unwrap().ends_with("Cargo.toml"))
- .unwrap();
- let mut contents = String::new();
- entry.read_to_string(&mut contents).unwrap();
- // BTreeMap makes the order of dependencies in the generated file deterministic
- // by sorting alphabetically
- assert_that(&contents[..], equal_to(
-&*format!(
-r#"# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
-#
-# When uploading crates to the registry Cargo will automatically
-# "normalize" Cargo.toml files for maximal compatibility
-# with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g. crates.io) dependencies
-#
-# If you believe there's an error in this file please file an
-# issue against the rust-lang/cargo repository. If you're
-# editing this file be aware that the upstream Cargo.toml
-# will likely look very different (and much more reasonable)
-
-cargo-features = ["alternative-registries"]
-
-[package]
-name = "foo"
-version = "0.0.1"
-authors = []
-exclude = ["*.txt"]
-description = "foo"
-license = "MIT"
-
-[package.metadata]
-foo = "bar"
-[dependencies.abc]
-version = "1.0"
-
-[dependencies.bar]
-version = "0.1"
-
-[dependencies.def]
-version = "1.0"
-registry-index = "{}"
-
-[dependencies.ghi]
-version = "1.0"
-"#,
- registry::alt_registry())));
-}
-
-#[test]
-fn ignore_workspace_specifier() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
-
- authors = []
-
- [workspace]
-
- [dependencies]
- bar = { path = "bar", version = "0.1" }
- "#)
- .file("src/main.rs", "")
- .file("bar/Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.1.0"
- authors = []
- workspace = ".."
- "#)
- .file("bar/src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("package").arg("--no-verify").cwd(p.root().join("bar")),
- execs().with_status(0));
-
- let f = File::open(&p.root().join("target/package/bar-0.1.0.crate")).unwrap();
- let mut rdr = GzDecoder::new(f);
- let mut contents = Vec::new();
- rdr.read_to_end(&mut contents).unwrap();
- let mut ar = Archive::new(&contents[..]);
- let mut entry = ar.entries().unwrap()
- .map(|f| f.unwrap())
- .find(|e| e.path().unwrap().ends_with("Cargo.toml"))
- .unwrap();
- let mut contents = String::new();
- entry.read_to_string(&mut contents).unwrap();
- assert_that(&contents[..], equal_to(
-r#"# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
-#
-# When uploading crates to the registry Cargo will automatically
-# "normalize" Cargo.toml files for maximal compatibility
-# with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g. crates.io) dependencies
-#
-# If you believe there's an error in this file please file an
-# issue against the rust-lang/cargo repository. If you're
-# editing this file be aware that the upstream Cargo.toml
-# will likely look very different (and much more reasonable)
-
-[package]
-name = "bar"
-version = "0.1.0"
-authors = []
-"#));
-}
-
-#[test]
-fn package_two_kinds_of_deps() {
- Package::new("other", "1.0.0").publish();
- Package::new("other1", "1.0.0").publish();
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- other = "1.0"
- other1 = { version = "1.0" }
- "#)
- .file("src/main.rs", "")
- .build();
-
- assert_that(p.cargo("package").arg("--no-verify"),
- execs().with_status(0));
-}
-
-#[test]
-fn test_epoch() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- cargo-features = ["epoch"]
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- rust = "2018"
- "#)
- .file("src/lib.rs", r#" "#)
- .build();
-
- assert_that(p.cargo("build").arg("-v")
- .masquerade_as_nightly_cargo(),
- execs()
- // -Zepoch is still in flux and we're not passing -Zunstable-options
- // from Cargo so it will probably error. Only partially match the output
- // until stuff stabilizes
- .with_stderr_contains(format!("\
-[COMPILING] foo v0.0.1 ({url})
-[RUNNING] `rustc --crate-name foo src[/]lib.rs --crate-type lib \
- --emit=dep-info,link -Zepoch=2018 -C debuginfo=2 \
- -C metadata=[..] \
- --out-dir [..] \
- -L dependency={dir}[/]target[/]debug[/]deps`
-", dir = p.root().display(), url = p.url())));
-}
-
-#[test]
-fn test_epoch_missing() {
- // no epoch = 2015
- let p = project("foo")
- .file("Cargo.toml", r#"
- cargo-features = ["epoch"]
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/lib.rs", r#" "#)
- .build();
-
- assert_that(p.cargo("build").arg("-v")
- .masquerade_as_nightly_cargo(),
- execs()
- // -Zepoch is still in flux and we're not passing -Zunstable-options
- // from Cargo so it will probably error. Only partially match the output
- // until stuff stabilizes
- .with_stderr_contains(format!("\
-[COMPILING] foo v0.0.1 ({url})
-[RUNNING] `rustc --crate-name foo src[/]lib.rs --crate-type lib \
- --emit=dep-info,link -Zepoch=2015 -C debuginfo=2 \
- -C metadata=[..] \
- --out-dir [..] \
- -L dependency={dir}[/]target[/]debug[/]deps`
-", dir = p.root().display(), url = p.url())));
-}
-
-#[test]
-fn test_epoch_malformed() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- cargo-features = ["epoch"]
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- rust = "chicken"
- "#)
- .file("src/lib.rs", r#" "#)
- .build();
-
- assert_that(p.cargo("build").arg("-v")
- .masquerade_as_nightly_cargo(),
- execs()
- .with_status(101)
- .with_stderr(format!("\
-error: failed to parse manifest at `[..]`
-
-Caused by:
- the `rust` key must be one of: `2015`, `2018`
-")));
-}
-
-
-#[test]
-fn test_epoch_nightly() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- rust = "2015"
- "#)
- .file("src/lib.rs", r#" "#)
- .build();
-
- assert_that(p.cargo("build").arg("-v")
- .masquerade_as_nightly_cargo(),
- execs()
- .with_status(101)
- .with_stderr(format!("\
-error: failed to parse manifest at `[..]`
-
-Caused by:
- epoches are unstable
-
-Caused by:
- feature `epoch` is required
-
-consider adding `cargo-features = [\"epoch\"]` to the manifest
-")));
-}
+++ /dev/null
-#[macro_use]
-extern crate cargotest;
-extern crate hamcrest;
-extern crate toml;
-
-use std::fs::{self, File};
-use std::io::{Read, Write};
-
-use cargotest::support::git;
-use cargotest::support::paths;
-use cargotest::support::registry::Package;
-use cargotest::support::{execs, project};
-use hamcrest::assert_that;
-
-#[test]
-fn replace() {
- Package::new("foo", "0.1.0").publish();
- Package::new("deep-foo", "0.1.0")
- .file("src/lib.rs", r#"
- extern crate foo;
- pub fn deep() {
- foo::foo();
- }
- "#)
- .dep("foo", "0.1.0")
- .publish();
-
- let p = project("bar")
- .file("Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- foo = "0.1.0"
- deep-foo = "0.1.0"
-
- [patch.crates-io]
- foo = { path = "foo" }
- "#)
- .file("src/lib.rs", "
- extern crate foo;
- extern crate deep_foo;
- pub fn bar() {
- foo::foo();
- deep_foo::deep();
- }
- ")
- .file("foo/Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
- "#)
- .file("foo/src/lib.rs", r#"
- pub fn foo() {}
- "#)
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr("\
-[UPDATING] registry `file://[..]`
-[DOWNLOADING] deep-foo v0.1.0 ([..])
-[COMPILING] foo v0.1.0 (file://[..])
-[COMPILING] deep-foo v0.1.0
-[COMPILING] bar v0.0.1 (file://[..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-
- assert_that(p.cargo("build"),//.env("RUST_LOG", "trace"),
- execs().with_status(0).with_stderr("[FINISHED] [..]"));
-}
-
-#[test]
-fn nonexistent() {
- Package::new("baz", "0.1.0").publish();
-
- let p = project("bar")
- .file("Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- foo = "0.1.0"
-
- [patch.crates-io]
- foo = { path = "foo" }
- "#)
- .file("src/lib.rs", "
- extern crate foo;
- pub fn bar() {
- foo::foo();
- }
- ")
- .file("foo/Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
- "#)
- .file("foo/src/lib.rs", r#"
- pub fn foo() {}
- "#)
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr("\
-[UPDATING] registry `file://[..]`
-[COMPILING] foo v0.1.0 (file://[..])
-[COMPILING] bar v0.0.1 (file://[..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr("[FINISHED] [..]"));
-}
-
-#[test]
-fn patch_git() {
- let foo = git::repo(&paths::root().join("override"))
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
- "#)
- .file("src/lib.rs", "")
- .build();
-
- let p = project("bar")
- .file("Cargo.toml", &format!(r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- foo = {{ git = '{}' }}
-
- [patch.'{0}']
- foo = {{ path = "foo" }}
- "#, foo.url()))
- .file("src/lib.rs", "
- extern crate foo;
- pub fn bar() {
- foo::foo();
- }
- ")
- .file("foo/Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
- "#)
- .file("foo/src/lib.rs", r#"
- pub fn foo() {}
- "#)
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr("\
-[UPDATING] git repository `file://[..]`
-[COMPILING] foo v0.1.0 (file://[..])
-[COMPILING] bar v0.0.1 (file://[..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr("[FINISHED] [..]"));
-}
-
-#[test]
-fn patch_to_git() {
- let foo = git::repo(&paths::root().join("override"))
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
- "#)
- .file("src/lib.rs", "pub fn foo() {}")
- .build();
-
- Package::new("foo", "0.1.0").publish();
-
- let p = project("bar")
- .file("Cargo.toml", &format!(r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- foo = "0.1"
-
- [patch.crates-io]
- foo = {{ git = '{}' }}
- "#, foo.url()))
- .file("src/lib.rs", "
- extern crate foo;
- pub fn bar() {
- foo::foo();
- }
- ")
- .build();
-
- assert_that(p.cargo("build"),//.env("RUST_LOG", "cargo=trace"),
- execs().with_status(0).with_stderr("\
-[UPDATING] git repository `file://[..]`
-[UPDATING] registry `file://[..]`
-[COMPILING] foo v0.1.0 (file://[..])
-[COMPILING] bar v0.0.1 (file://[..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr("[FINISHED] [..]"));
-}
-
-#[test]
-fn unused() {
- Package::new("foo", "0.1.0").publish();
-
- let p = project("bar")
- .file("Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- foo = "0.1.0"
-
- [patch.crates-io]
- foo = { path = "foo" }
- "#)
- .file("src/lib.rs", "")
- .file("foo/Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.2.0"
- authors = []
- "#)
- .file("foo/src/lib.rs", r#"
- not rust code
- "#)
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr("\
-[UPDATING] registry `file://[..]`
-[DOWNLOADING] foo v0.1.0 [..]
-[COMPILING] foo v0.1.0
-[COMPILING] bar v0.0.1 (file://[..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr("[FINISHED] [..]"));
-
- // unused patch should be in the lock file
- let mut lock = String::new();
- File::open(p.root().join("Cargo.lock")).unwrap()
- .read_to_string(&mut lock).unwrap();
- let toml: toml::Value = toml::from_str(&lock).unwrap();
- assert_eq!(toml["patch"]["unused"].as_array().unwrap().len(), 1);
- assert_eq!(toml["patch"]["unused"][0]["name"].as_str(), Some("foo"));
- assert_eq!(toml["patch"]["unused"][0]["version"].as_str(), Some("0.2.0"));
-}
-
-#[test]
-fn unused_git() {
- Package::new("foo", "0.1.0").publish();
-
- let foo = git::repo(&paths::root().join("override"))
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.2.0"
- authors = []
- "#)
- .file("src/lib.rs", "")
- .build();
-
- let p = project("bar")
- .file("Cargo.toml", &format!(r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- foo = "0.1"
-
- [patch.crates-io]
- foo = {{ git = '{}' }}
- "#, foo.url()))
- .file("src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr("\
-[UPDATING] git repository `file://[..]`
-[UPDATING] registry `file://[..]`
-[DOWNLOADING] foo v0.1.0 [..]
-[COMPILING] foo v0.1.0
-[COMPILING] bar v0.0.1 (file://[..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr("[FINISHED] [..]"));
-}
-
-#[test]
-fn add_patch() {
- Package::new("foo", "0.1.0").publish();
-
- let p = project("bar")
- .file("Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- foo = "0.1.0"
- "#)
- .file("src/lib.rs", "")
- .file("foo/Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
- "#)
- .file("foo/src/lib.rs", r#""#)
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr("\
-[UPDATING] registry `file://[..]`
-[DOWNLOADING] foo v0.1.0 [..]
-[COMPILING] foo v0.1.0
-[COMPILING] bar v0.0.1 (file://[..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr("[FINISHED] [..]"));
-
- t!(t!(File::create(p.root().join("Cargo.toml"))).write_all(br#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- foo = "0.1.0"
-
- [patch.crates-io]
- foo = { path = 'foo' }
- "#));
-
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr("\
-[COMPILING] foo v0.1.0 (file://[..])
-[COMPILING] bar v0.0.1 (file://[..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr("[FINISHED] [..]"));
-}
-
-#[test]
-fn add_ignored_patch() {
- Package::new("foo", "0.1.0").publish();
-
- let p = project("bar")
- .file("Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- foo = "0.1.0"
- "#)
- .file("src/lib.rs", "")
- .file("foo/Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.1"
- authors = []
- "#)
- .file("foo/src/lib.rs", r#""#)
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr("\
-[UPDATING] registry `file://[..]`
-[DOWNLOADING] foo v0.1.0 [..]
-[COMPILING] foo v0.1.0
-[COMPILING] bar v0.0.1 (file://[..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr("[FINISHED] [..]"));
-
- t!(t!(File::create(p.root().join("Cargo.toml"))).write_all(br#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- foo = "0.1.0"
-
- [patch.crates-io]
- foo = { path = 'foo' }
- "#));
-
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr("\
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr("[FINISHED] [..]"));
-}
-
-#[test]
-fn new_minor() {
- Package::new("foo", "0.1.0").publish();
-
- let p = project("bar")
- .file("Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- foo = "0.1.0"
-
- [patch.crates-io]
- foo = { path = 'foo' }
- "#)
- .file("src/lib.rs", "")
- .file("foo/Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.1"
- authors = []
- "#)
- .file("foo/src/lib.rs", r#""#)
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr("\
-[UPDATING] registry `file://[..]`
-[COMPILING] foo v0.1.1 [..]
-[COMPILING] bar v0.0.1 (file://[..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-}
-
-#[test]
-fn transitive_new_minor() {
- Package::new("foo", "0.1.0").publish();
-
- let p = project("bar")
- .file("Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- subdir = { path = 'subdir' }
-
- [patch.crates-io]
- foo = { path = 'foo' }
- "#)
- .file("src/lib.rs", "")
- .file("subdir/Cargo.toml", r#"
- [package]
- name = "subdir"
- version = "0.1.0"
- authors = []
-
- [dependencies]
- foo = '0.1.0'
- "#)
- .file("subdir/src/lib.rs", r#""#)
- .file("foo/Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.1"
- authors = []
- "#)
- .file("foo/src/lib.rs", r#""#)
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr("\
-[UPDATING] registry `file://[..]`
-[COMPILING] foo v0.1.1 [..]
-[COMPILING] subdir v0.1.0 [..]
-[COMPILING] bar v0.0.1 (file://[..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-}
-
-#[test]
-fn new_major() {
- Package::new("foo", "0.1.0").publish();
-
- let p = project("bar")
- .file("Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- foo = "0.2.0"
-
- [patch.crates-io]
- foo = { path = 'foo' }
- "#)
- .file("src/lib.rs", "")
- .file("foo/Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.2.0"
- authors = []
- "#)
- .file("foo/src/lib.rs", r#""#)
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr("\
-[UPDATING] registry `file://[..]`
-[COMPILING] foo v0.2.0 [..]
-[COMPILING] bar v0.0.1 (file://[..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-
- Package::new("foo", "0.2.0").publish();
- assert_that(p.cargo("update"),
- execs().with_status(0));
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr("\
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-
- t!(t!(File::create(p.root().join("Cargo.toml"))).write_all(br#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- foo = "0.2.0"
- "#));
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr("\
-[UPDATING] registry `file://[..]`
-[DOWNLOADING] foo v0.2.0 [..]
-[COMPILING] foo v0.2.0
-[COMPILING] bar v0.0.1 (file://[..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-}
-
-#[test]
-fn transitive_new_major() {
- Package::new("foo", "0.1.0").publish();
-
- let p = project("bar")
- .file("Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- subdir = { path = 'subdir' }
-
- [patch.crates-io]
- foo = { path = 'foo' }
- "#)
- .file("src/lib.rs", "")
- .file("subdir/Cargo.toml", r#"
- [package]
- name = "subdir"
- version = "0.1.0"
- authors = []
-
- [dependencies]
- foo = '0.2.0'
- "#)
- .file("subdir/src/lib.rs", r#""#)
- .file("foo/Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.2.0"
- authors = []
- "#)
- .file("foo/src/lib.rs", r#""#)
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr("\
-[UPDATING] registry `file://[..]`
-[COMPILING] foo v0.2.0 [..]
-[COMPILING] subdir v0.1.0 [..]
-[COMPILING] bar v0.0.1 (file://[..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-}
-
-#[test]
-fn remove_patch() {
- Package::new("foo", "0.1.0").publish();
- Package::new("bar", "0.1.0").publish();
-
- let p = project("bar")
- .file("Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- foo = "0.1"
-
- [patch.crates-io]
- foo = { path = 'foo' }
- bar = { path = 'bar' }
- "#)
- .file("src/lib.rs", "")
- .file("foo/Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
- "#)
- .file("foo/src/lib.rs", r#""#)
- .file("bar/Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.1.0"
- authors = []
- "#)
- .file("bar/src/lib.rs", r#""#)
- .build();
-
- // Generate a lock file where `bar` is unused
- assert_that(p.cargo("build"), execs().with_status(0));
- let mut lock_file1 = String::new();
- File::open(p.root().join("Cargo.lock")).unwrap()
- .read_to_string(&mut lock_file1).unwrap();
-
- // Remove `bar` and generate a new lock file form the old one
- File::create(p.root().join("Cargo.toml")).unwrap().write_all(r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- foo = "0.1"
-
- [patch.crates-io]
- foo = { path = 'foo' }
- "#.as_bytes()).unwrap();
- assert_that(p.cargo("build"), execs().with_status(0));
- let mut lock_file2 = String::new();
- File::open(p.root().join("Cargo.lock")).unwrap()
- .read_to_string(&mut lock_file2).unwrap();
-
- // Remove the lock file and build from scratch
- fs::remove_file(p.root().join("Cargo.lock")).unwrap();
- assert_that(p.cargo("build"), execs().with_status(0));
- let mut lock_file3 = String::new();
- File::open(p.root().join("Cargo.lock")).unwrap()
- .read_to_string(&mut lock_file3).unwrap();
-
- assert!(lock_file1.contains("bar"));
- assert_eq!(lock_file2, lock_file3);
- assert!(lock_file1 != lock_file2);
-}
-
-#[test]
-fn non_crates_io() {
- Package::new("foo", "0.1.0").publish();
-
- let p = project("bar")
- .file("Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
-
- [patch.some-other-source]
- foo = { path = 'foo' }
- "#)
- .file("src/lib.rs", "")
- .file("foo/Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
- "#)
- .file("foo/src/lib.rs", r#""#)
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(101)
- .with_stderr("\
-error: failed to parse manifest at `[..]`
-
-Caused by:
- invalid url `some-other-source`: relative URL without a base
-"));
-}
-
-#[test]
-fn replace_with_crates_io() {
- Package::new("foo", "0.1.0").publish();
-
- let p = project("bar")
- .file("Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
-
- [patch.crates-io]
- foo = "0.1"
- "#)
- .file("src/lib.rs", "")
- .file("foo/Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
- "#)
- .file("foo/src/lib.rs", r#""#)
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(101)
- .with_stderr("\
-[UPDATING] [..]
-error: failed to resolve patches for `[..]`
-
-Caused by:
- patch for `foo` in `[..]` points to the same source, but patches must point \
- to different sources
-"));
-}
-
-#[test]
-fn patch_in_virtual() {
- Package::new("foo", "0.1.0").publish();
-
- let p = project("bar")
- .file("Cargo.toml", r#"
- [workspace]
- members = ["bar"]
-
- [patch.crates-io]
- foo = { path = "foo" }
- "#)
- .file("foo/Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
- "#)
- .file("foo/src/lib.rs", r#""#)
- .file("bar/Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.1.0"
- authors = []
-
- [dependencies]
- foo = "0.1"
- "#)
- .file("bar/src/lib.rs", r#""#)
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0));
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr("\
-[FINISHED] [..]
-"));
-}
-
-#[test]
-fn patch_depends_on_another_patch() {
- Package::new("foo", "0.1.0")
- .file("src/lib.rs", "broken code")
- .publish();
-
- Package::new("bar", "0.1.0")
- .dep("foo", "0.1")
- .file("src/lib.rs", "broken code")
- .publish();
-
- let p = project("p")
- .file("Cargo.toml", r#"
- [package]
- name = "p"
- authors = []
- version = "0.1.0"
-
- [dependencies]
- foo = "0.1"
- bar = "0.1"
-
- [patch.crates-io]
- foo = { path = "foo" }
- bar = { path = "bar" }
- "#)
- .file("src/lib.rs", "")
- .file("foo/Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.1"
- authors = []
- "#)
- .file("foo/src/lib.rs", r#""#)
- .file("bar/Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.1.1"
- authors = []
-
- [dependencies]
- foo = "0.1"
- "#)
- .file("bar/src/lib.rs", r#""#)
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0));
-
- // Nothing should be rebuilt, no registry should be updated.
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr("\
-[FINISHED] [..]
-"));
-}
+++ /dev/null
-extern crate cargo;
-#[macro_use]
-extern crate cargotest;
-extern crate hamcrest;
-
-use std::fs::{self, File};
-use std::io::prelude::*;
-
-use cargo::util::process;
-use cargotest::sleep_ms;
-use cargotest::support::paths::{self, CargoPathExt};
-use cargotest::support::{project, execs, main_file};
-use cargotest::support::registry::Package;
-use hamcrest::{assert_that, existing_file};
-
-#[test]
-#[cfg(not(windows))] // I have no idea why this is failing spuriously on
- // Windows, for more info see #3466.
-fn cargo_compile_with_nested_deps_shorthand() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
-
- name = "foo"
- version = "0.5.0"
- authors = ["wycats@example.com"]
-
- [dependencies.bar]
-
- version = "0.5.0"
- path = "bar"
- "#)
- .file("src/main.rs",
- &main_file(r#""{}", bar::gimme()"#, &["bar"]))
- .file("bar/Cargo.toml", r#"
- [project]
-
- name = "bar"
- version = "0.5.0"
- authors = ["wycats@example.com"]
-
- [dependencies.baz]
-
- version = "0.5.0"
- path = "baz"
-
- [lib]
-
- name = "bar"
- "#)
- .file("bar/src/bar.rs", r#"
- extern crate baz;
-
- pub fn gimme() -> String {
- baz::gimme()
- }
- "#)
- .file("bar/baz/Cargo.toml", r#"
- [project]
-
- name = "baz"
- version = "0.5.0"
- authors = ["wycats@example.com"]
-
- [lib]
-
- name = "baz"
- "#)
- .file("bar/baz/src/baz.rs", r#"
- pub fn gimme() -> String {
- "test passed".to_string()
- }
- "#)
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0)
- .with_stderr(&format!("[COMPILING] baz v0.5.0 ({}/bar/baz)\n\
- [COMPILING] bar v0.5.0 ({}/bar)\n\
- [COMPILING] foo v0.5.0 ({})\n\
- [FINISHED] dev [unoptimized + debuginfo] target(s) \
- in [..]\n",
- p.url(),
- p.url(),
- p.url())));
-
- assert_that(&p.bin("foo"), existing_file());
-
- assert_that(process(&p.bin("foo")),
- execs().with_stdout("test passed\n").with_status(0));
-
- println!("cleaning");
- assert_that(p.cargo("clean").arg("-v"),
- execs().with_stdout("").with_status(0));
- println!("building baz");
- assert_that(p.cargo("build").arg("-p").arg("baz"),
- execs().with_status(0)
- .with_stderr(&format!("[COMPILING] baz v0.5.0 ({}/bar/baz)\n\
- [FINISHED] dev [unoptimized + debuginfo] target(s) \
- in [..]\n",
- p.url())));
- println!("building foo");
- assert_that(p.cargo("build")
- .arg("-p").arg("foo"),
- execs().with_status(0)
- .with_stderr(&format!("[COMPILING] bar v0.5.0 ({}/bar)\n\
- [COMPILING] foo v0.5.0 ({})\n\
- [FINISHED] dev [unoptimized + debuginfo] target(s) \
- in [..]\n",
- p.url(),
- p.url())));
-}
-
-#[test]
-fn cargo_compile_with_root_dev_deps() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
-
- name = "foo"
- version = "0.5.0"
- authors = ["wycats@example.com"]
-
- [dev-dependencies.bar]
-
- version = "0.5.0"
- path = "../bar"
-
- [[bin]]
- name = "foo"
- "#)
- .file("src/main.rs",
- &main_file(r#""{}", bar::gimme()"#, &["bar"]))
- .build();
- let _p2 = project("bar")
- .file("Cargo.toml", r#"
- [package]
-
- name = "bar"
- version = "0.5.0"
- authors = ["wycats@example.com"]
- "#)
- .file("src/lib.rs", r#"
- pub fn gimme() -> &'static str {
- "zoidberg"
- }
- "#)
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(101))
-}
-
-#[test]
-fn cargo_compile_with_root_dev_deps_with_testing() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
-
- name = "foo"
- version = "0.5.0"
- authors = ["wycats@example.com"]
-
- [dev-dependencies.bar]
-
- version = "0.5.0"
- path = "../bar"
-
- [[bin]]
- name = "foo"
- "#)
- .file("src/main.rs",
- &main_file(r#""{}", bar::gimme()"#, &["bar"]))
- .build();
- let _p2 = project("bar")
- .file("Cargo.toml", r#"
- [package]
-
- name = "bar"
- version = "0.5.0"
- authors = ["wycats@example.com"]
- "#)
- .file("src/lib.rs", r#"
- pub fn gimme() -> &'static str {
- "zoidberg"
- }
- "#)
- .build();
-
- assert_that(p.cargo("test"),
- execs().with_stderr("\
-[COMPILING] [..] v0.5.0 ([..])
-[COMPILING] [..] v0.5.0 ([..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] target[/]debug[/]deps[/]foo-[..][EXE]")
- .with_stdout_contains("running 0 tests"));
-}
-
-#[test]
-fn cargo_compile_with_transitive_dev_deps() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
-
- name = "foo"
- version = "0.5.0"
- authors = ["wycats@example.com"]
-
- [dependencies.bar]
-
- version = "0.5.0"
- path = "bar"
- "#)
- .file("src/main.rs",
- &main_file(r#""{}", bar::gimme()"#, &["bar"]))
- .file("bar/Cargo.toml", r#"
- [project]
-
- name = "bar"
- version = "0.5.0"
- authors = ["wycats@example.com"]
-
- [dev-dependencies.baz]
-
- git = "git://example.com/path/to/nowhere"
-
- [lib]
-
- name = "bar"
- "#)
- .file("bar/src/bar.rs", r#"
- pub fn gimme() -> &'static str {
- "zoidberg"
- }
- "#)
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_stderr(&format!("[COMPILING] bar v0.5.0 ({}/bar)\n\
- [COMPILING] foo v0.5.0 ({})\n\
- [FINISHED] dev [unoptimized + debuginfo] target(s) in \
- [..]\n",
- p.url(),
- p.url())));
-
- assert_that(&p.bin("foo"), existing_file());
-
- assert_that(process(&p.bin("foo")),
- execs().with_stdout("zoidberg\n"));
-}
-
-#[test]
-fn no_rebuild_dependency() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
-
- name = "foo"
- version = "0.5.0"
- authors = ["wycats@example.com"]
-
- [dependencies.bar]
- path = "bar"
- "#)
- .file("src/main.rs", r#"
- extern crate bar;
- fn main() { bar::bar() }
- "#)
- .file("bar/Cargo.toml", r#"
- [project]
-
- name = "bar"
- version = "0.5.0"
- authors = ["wycats@example.com"]
-
- [lib]
- name = "bar"
- "#)
- .file("bar/src/bar.rs", r#"
- pub fn bar() {}
- "#)
- .build();
- // First time around we should compile both foo and bar
- assert_that(p.cargo("build"),
- execs().with_stderr(&format!("[COMPILING] bar v0.5.0 ({}/bar)\n\
- [COMPILING] foo v0.5.0 ({})\n\
- [FINISHED] dev [unoptimized + debuginfo] target(s) \
- in [..]\n",
- p.url(),
- p.url())));
-
- sleep_ms(1000);
- p.change_file("src/main.rs", r#"
- extern crate bar;
- fn main() { bar::bar(); }
- "#);
- // Don't compile bar, but do recompile foo.
- assert_that(p.cargo("build"),
- execs().with_stderr("\
- [COMPILING] foo v0.5.0 ([..])\n\
- [FINISHED] dev [unoptimized + debuginfo] target(s) \
- in [..]\n"));
-}
-
-#[test]
-fn deep_dependencies_trigger_rebuild() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
-
- name = "foo"
- version = "0.5.0"
- authors = ["wycats@example.com"]
-
- [dependencies.bar]
- path = "bar"
- "#)
- .file("src/main.rs", r#"
- extern crate bar;
- fn main() { bar::bar() }
- "#)
- .file("bar/Cargo.toml", r#"
- [project]
-
- name = "bar"
- version = "0.5.0"
- authors = ["wycats@example.com"]
-
- [lib]
- name = "bar"
- [dependencies.baz]
- path = "../baz"
- "#)
- .file("bar/src/bar.rs", r#"
- extern crate baz;
- pub fn bar() { baz::baz() }
- "#)
- .file("baz/Cargo.toml", r#"
- [project]
-
- name = "baz"
- version = "0.5.0"
- authors = ["wycats@example.com"]
-
- [lib]
- name = "baz"
- "#)
- .file("baz/src/baz.rs", r#"
- pub fn baz() {}
- "#)
- .build();
- assert_that(p.cargo("build"),
- execs().with_stderr(&format!("[COMPILING] baz v0.5.0 ({}/baz)\n\
- [COMPILING] bar v0.5.0 ({}/bar)\n\
- [COMPILING] foo v0.5.0 ({})\n\
- [FINISHED] dev [unoptimized + debuginfo] target(s) \
- in [..]\n",
- p.url(),
- p.url(),
- p.url())));
- assert_that(p.cargo("build"),
- execs().with_stdout(""));
-
- // Make sure an update to baz triggers a rebuild of bar
- //
- // We base recompilation off mtime, so sleep for at least a second to ensure
- // that this write will change the mtime.
- sleep_ms(1000);
- File::create(&p.root().join("baz/src/baz.rs")).unwrap().write_all(br#"
- pub fn baz() { println!("hello!"); }
- "#).unwrap();
- assert_that(p.cargo("build"),
- execs().with_stderr(&format!("[COMPILING] baz v0.5.0 ({}/baz)\n\
- [COMPILING] bar v0.5.0 ({}/bar)\n\
- [COMPILING] foo v0.5.0 ({})\n\
- [FINISHED] dev [unoptimized + debuginfo] target(s) \
- in [..]\n",
- p.url(),
- p.url(),
- p.url())));
-
- // Make sure an update to bar doesn't trigger baz
- sleep_ms(1000);
- File::create(&p.root().join("bar/src/bar.rs")).unwrap().write_all(br#"
- extern crate baz;
- pub fn bar() { println!("hello!"); baz::baz(); }
- "#).unwrap();
- assert_that(p.cargo("build"),
- execs().with_stderr(&format!("[COMPILING] bar v0.5.0 ({}/bar)\n\
- [COMPILING] foo v0.5.0 ({})\n\
- [FINISHED] dev [unoptimized + debuginfo] target(s) \
- in [..]\n",
- p.url(),
- p.url())));
-
-}
-
-#[test]
-fn no_rebuild_two_deps() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
-
- name = "foo"
- version = "0.5.0"
- authors = ["wycats@example.com"]
-
- [dependencies.bar]
- path = "bar"
- [dependencies.baz]
- path = "baz"
- "#)
- .file("src/main.rs", r#"
- extern crate bar;
- fn main() { bar::bar() }
- "#)
- .file("bar/Cargo.toml", r#"
- [project]
-
- name = "bar"
- version = "0.5.0"
- authors = ["wycats@example.com"]
-
- [lib]
- name = "bar"
- [dependencies.baz]
- path = "../baz"
- "#)
- .file("bar/src/bar.rs", r#"
- pub fn bar() {}
- "#)
- .file("baz/Cargo.toml", r#"
- [project]
-
- name = "baz"
- version = "0.5.0"
- authors = ["wycats@example.com"]
-
- [lib]
- name = "baz"
- "#)
- .file("baz/src/baz.rs", r#"
- pub fn baz() {}
- "#)
- .build();
- assert_that(p.cargo("build"),
- execs().with_stderr(&format!("[COMPILING] baz v0.5.0 ({}/baz)\n\
- [COMPILING] bar v0.5.0 ({}/bar)\n\
- [COMPILING] foo v0.5.0 ({})\n\
- [FINISHED] dev [unoptimized + debuginfo] target(s) \
- in [..]\n",
- p.url(),
- p.url(),
- p.url())));
- assert_that(&p.bin("foo"), existing_file());
- assert_that(p.cargo("build"),
- execs().with_stdout(""));
- assert_that(&p.bin("foo"), existing_file());
-}
-
-#[test]
-fn nested_deps_recompile() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
-
- name = "foo"
- version = "0.5.0"
- authors = ["wycats@example.com"]
-
- [dependencies.bar]
-
- version = "0.5.0"
- path = "src/bar"
- "#)
- .file("src/main.rs",
- &main_file(r#""{}", bar::gimme()"#, &["bar"]))
- .file("src/bar/Cargo.toml", r#"
- [project]
-
- name = "bar"
- version = "0.5.0"
- authors = ["wycats@example.com"]
-
- [lib]
-
- name = "bar"
- "#)
- .file("src/bar/src/bar.rs", "pub fn gimme() -> i32 { 92 }")
- .build();
- let bar = p.url();
-
- assert_that(p.cargo("build"),
- execs().with_stderr(&format!("[COMPILING] bar v0.5.0 ({}/src/bar)\n\
- [COMPILING] foo v0.5.0 ({})\n\
- [FINISHED] dev [unoptimized + debuginfo] target(s) \
- in [..]\n",
- bar,
- p.url())));
- sleep_ms(1000);
-
- File::create(&p.root().join("src/main.rs")).unwrap().write_all(br#"
- fn main() {}
- "#).unwrap();
-
- // This shouldn't recompile `bar`
- assert_that(p.cargo("build"),
- execs().with_stderr(&format!("[COMPILING] foo v0.5.0 ({})\n\
- [FINISHED] dev [unoptimized + debuginfo] target(s) \
- in [..]\n",
- p.url())));
-}
-
-#[test]
-fn error_message_for_missing_manifest() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
-
- name = "foo"
- version = "0.5.0"
- authors = ["wycats@example.com"]
-
- [dependencies.bar]
-
- path = "src/bar"
- "#)
- .file("src/lib.rs", "")
- .file("src/bar/not-a-manifest", "")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(101)
- .with_stderr("\
-[ERROR] failed to load source for a dependency on `bar`
-
-Caused by:
- Unable to update file://[..]
-
-Caused by:
- failed to read `[..]bar[/]Cargo.toml`
-
-Caused by:
- [..] (os error [..])
-"));
-
-}
-
-#[test]
-fn override_relative() {
- let bar = project("bar")
- .file("Cargo.toml", r#"
- [package]
-
- name = "bar"
- version = "0.5.0"
- authors = ["wycats@example.com"]
- "#)
- .file("src/lib.rs", "")
- .build();
-
- fs::create_dir(&paths::root().join(".cargo")).unwrap();
- File::create(&paths::root().join(".cargo/config")).unwrap()
- .write_all(br#"paths = ["bar"]"#).unwrap();
-
- let p = project("foo")
- .file("Cargo.toml", &format!(r#"
- [package]
-
- name = "foo"
- version = "0.5.0"
- authors = ["wycats@example.com"]
-
- [dependencies.bar]
- path = '{}'
- "#, bar.root().display()))
- .file("src/lib.rs", "")
- .build();
- assert_that(p.cargo("build").arg("-v"), execs().with_status(0));
-
-}
-
-#[test]
-fn override_self() {
- let bar = project("bar")
- .file("Cargo.toml", r#"
- [package]
-
- name = "bar"
- version = "0.5.0"
- authors = ["wycats@example.com"]
- "#)
- .file("src/lib.rs", "")
- .build();
-
- let p = project("foo");
- let root = p.root().clone();
- let p = p
- .file(".cargo/config", &format!(r#"
- paths = ['{}']
- "#, root.display()))
- .file("Cargo.toml", &format!(r#"
- [package]
-
- name = "foo"
- version = "0.5.0"
- authors = ["wycats@example.com"]
-
- [dependencies.bar]
- path = '{}'
-
- "#, bar.root().display()))
- .file("src/lib.rs", "")
- .file("src/main.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("build"), execs().with_status(0));
-}
-
-#[test]
-fn override_path_dep() {
- let bar = project("bar")
- .file("p1/Cargo.toml", r#"
- [package]
- name = "p1"
- version = "0.5.0"
- authors = []
-
- [dependencies.p2]
- path = "../p2"
- "#)
- .file("p1/src/lib.rs", "")
- .file("p2/Cargo.toml", r#"
- [package]
- name = "p2"
- version = "0.5.0"
- authors = []
- "#)
- .file("p2/src/lib.rs", "")
- .build();
-
- let p = project("foo")
- .file(".cargo/config", &format!(r#"
- paths = ['{}', '{}']
- "#, bar.root().join("p1").display(),
- bar.root().join("p2").display()))
- .file("Cargo.toml", &format!(r#"
- [package]
-
- name = "foo"
- version = "0.5.0"
- authors = ["wycats@example.com"]
-
- [dependencies.p2]
- path = '{}'
-
- "#, bar.root().join("p2").display()))
- .file("src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(0));
-
-}
-
-#[test]
-fn path_dep_build_cmd() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
-
- name = "foo"
- version = "0.5.0"
- authors = ["wycats@example.com"]
-
- [dependencies.bar]
-
- version = "0.5.0"
- path = "bar"
- "#)
- .file("src/main.rs",
- &main_file(r#""{}", bar::gimme()"#, &["bar"]))
- .file("bar/Cargo.toml", r#"
- [project]
-
- name = "bar"
- version = "0.5.0"
- authors = ["wycats@example.com"]
- build = "build.rs"
-
- [lib]
- name = "bar"
- path = "src/bar.rs"
- "#)
- .file("bar/build.rs", r#"
- use std::fs;
- fn main() {
- fs::copy("src/bar.rs.in", "src/bar.rs").unwrap();
- }
- "#)
- .file("bar/src/bar.rs.in", r#"
- pub fn gimme() -> i32 { 0 }
- "#).build();
- p.root().join("bar").move_into_the_past();
-
- assert_that(p.cargo("build"),
- execs().with_stderr(&format!("[COMPILING] bar v0.5.0 ({}/bar)\n\
- [COMPILING] foo v0.5.0 ({})\n\
- [FINISHED] dev [unoptimized + debuginfo] target(s) in \
- [..]\n",
- p.url(),
- p.url())));
-
- assert_that(&p.bin("foo"), existing_file());
-
- assert_that(process(&p.bin("foo")),
- execs().with_stdout("0\n"));
-
- // Touching bar.rs.in should cause the `build` command to run again.
- {
- let file = fs::File::create(&p.root().join("bar/src/bar.rs.in"));
- file.unwrap().write_all(br#"pub fn gimme() -> i32 { 1 }"#).unwrap();
- }
-
- assert_that(p.cargo("build"),
- execs().with_stderr(&format!("[COMPILING] bar v0.5.0 ({}/bar)\n\
- [COMPILING] foo v0.5.0 ({})\n\
- [FINISHED] dev [unoptimized + debuginfo] target(s) in \
- [..]\n",
- p.url(),
- p.url())));
-
- assert_that(process(&p.bin("foo")),
- execs().with_stdout("1\n"));
-}
-
-#[test]
-fn dev_deps_no_rebuild_lib() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.5.0"
- authors = []
-
- [dev-dependencies.bar]
- path = "bar"
-
- [lib]
- name = "foo"
- doctest = false
- "#)
- .file("src/lib.rs", r#"
- #[cfg(test)] #[allow(unused_extern_crates)] extern crate bar;
- #[cfg(not(test))] pub fn foo() { env!("FOO"); }
- "#)
- .file("bar/Cargo.toml", r#"
- [package]
-
- name = "bar"
- version = "0.5.0"
- authors = ["wycats@example.com"]
- "#)
- .file("bar/src/lib.rs", "pub fn bar() {}")
- .build();
- assert_that(p.cargo("build")
- .env("FOO", "bar"),
- execs().with_status(0)
- .with_stderr(&format!("[COMPILING] foo v0.5.0 ({})\n\
- [FINISHED] dev [unoptimized + debuginfo] target(s) \
- in [..]\n",
- p.url())));
-
- assert_that(p.cargo("test"),
- execs().with_status(0)
- .with_stderr(&format!("\
-[COMPILING] [..] v0.5.0 ({url}[..])
-[COMPILING] [..] v0.5.0 ({url}[..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] target[/]debug[/]deps[/]foo-[..][EXE]", url = p.url()))
- .with_stdout_contains("running 0 tests"));
-}
-
-#[test]
-fn custom_target_no_rebuild() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.5.0"
- authors = []
- [dependencies]
- a = { path = "a" }
- [workspace]
- members = ["a", "b"]
- "#)
- .file("src/lib.rs", "")
- .file("a/Cargo.toml", r#"
- [project]
- name = "a"
- version = "0.5.0"
- authors = []
- "#)
- .file("a/src/lib.rs", "")
- .file("b/Cargo.toml", r#"
- [project]
- name = "b"
- version = "0.5.0"
- authors = []
- [dependencies]
- a = { path = "../a" }
- "#)
- .file("b/src/lib.rs", "")
- .build();
- assert_that(p.cargo("build"),
- execs().with_status(0)
- .with_stderr("\
-[COMPILING] a v0.5.0 ([..])
-[COMPILING] foo v0.5.0 ([..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-
- t!(fs::rename(p.root().join("target"), p.root().join("target_moved")));
- assert_that(p.cargo("build")
- .arg("--manifest-path=b/Cargo.toml")
- .env("CARGO_TARGET_DIR", "target_moved"),
- execs().with_status(0)
- .with_stderr("\
-[COMPILING] b v0.5.0 ([..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-}
-
-#[test]
-fn override_and_depend() {
- let p = project("foo")
- .file("a/a1/Cargo.toml", r#"
- [project]
- name = "a1"
- version = "0.5.0"
- authors = []
- [dependencies]
- a2 = { path = "../a2" }
- "#)
- .file("a/a1/src/lib.rs", "")
- .file("a/a2/Cargo.toml", r#"
- [project]
- name = "a2"
- version = "0.5.0"
- authors = []
- "#)
- .file("a/a2/src/lib.rs", "")
- .file("b/Cargo.toml", r#"
- [project]
- name = "b"
- version = "0.5.0"
- authors = []
- [dependencies]
- a1 = { path = "../a/a1" }
- a2 = { path = "../a/a2" }
- "#)
- .file("b/src/lib.rs", "")
- .file("b/.cargo/config", r#"
- paths = ["../a"]
- "#)
- .build();
- assert_that(p.cargo("build").cwd(p.root().join("b")),
- execs().with_status(0)
- .with_stderr("\
-[COMPILING] a2 v0.5.0 ([..])
-[COMPILING] a1 v0.5.0 ([..])
-[COMPILING] b v0.5.0 ([..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-}
-
-#[test]
-fn missing_path_dependency() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "a"
- version = "0.5.0"
- authors = []
- "#)
- .file("src/lib.rs", "")
- .file(".cargo/config", r#"
- paths = ["../whoa-this-does-not-exist"]
- "#)
- .build();
- assert_that(p.cargo("build"),
- execs().with_status(101)
- .with_stderr("\
-[ERROR] failed to update path override `[..]../whoa-this-does-not-exist` \
-(defined in `[..]`)
-
-Caused by:
- failed to read directory `[..]`
-
-Caused by:
- [..] (os error [..])
-"));
-}
-
-#[test]
-fn invalid_path_dep_in_workspace_with_lockfile() {
- Package::new("bar", "1.0.0").publish();
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "top"
- version = "0.5.0"
- authors = []
-
- [workspace]
-
- [dependencies]
- foo = { path = "foo" }
- "#)
- .file("src/lib.rs", "")
- .file("foo/Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.5.0"
- authors = []
-
- [dependencies]
- bar = "*"
- "#)
- .file("foo/src/lib.rs", "")
- .build();
-
- // Generate a lock file
- assert_that(p.cargo("build"), execs().with_status(0));
-
- // Change the dependency on `bar` to an invalid path
- File::create(&p.root().join("foo/Cargo.toml")).unwrap().write_all(br#"
- [project]
- name = "foo"
- version = "0.5.0"
- authors = []
-
- [dependencies]
- bar = { path = "" }
- "#).unwrap();
-
- // Make sure we get a nice error. In the past this actually stack
- // overflowed!
- assert_that(p.cargo("build"),
- execs().with_status(101)
- .with_stderr("\
-error: no matching package named `bar` found
-location searched: [..]
-required by package `foo v0.5.0 ([..])`
-"));
-}
-
-#[test]
-fn workspace_produces_rlib() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "top"
- version = "0.5.0"
- authors = []
-
- [workspace]
-
- [dependencies]
- foo = { path = "foo" }
- "#)
- .file("src/lib.rs", "")
- .file("foo/Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.5.0"
- authors = []
- "#)
- .file("foo/src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build"), execs().with_status(0));
-
- assert_that(&p.root().join("target/debug/libtop.rlib"), existing_file());
- assert_that(&p.root().join("target/debug/libfoo.rlib"), existing_file());
-
-}
-
-#[test]
-fn thin_lto_works() {
- if !cargotest::is_nightly() {
- return
- }
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "top"
- version = "0.5.0"
- authors = []
-
- [profile.release]
- lto = 'thin'
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("build").arg("--release").arg("-v"),
- execs().with_stderr("\
-[COMPILING] top [..]
-[RUNNING] `rustc [..] -C lto=thin [..]`
-[FINISHED] [..]
-"));
-}
+++ /dev/null
-extern crate cargotest;
-extern crate hamcrest;
-
-use std::fs;
-use std::env;
-
-use cargotest::{is_nightly, rustc_host};
-use cargotest::support::{project, execs};
-use hamcrest::assert_that;
-
-#[test]
-fn plugin_to_the_max() {
- if !is_nightly() { return }
-
- let foo = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [lib]
- name = "foo_lib"
-
- [dependencies.bar]
- path = "../bar"
- "#)
- .file("src/main.rs", r#"
- #![feature(plugin)]
- #![plugin(bar)]
- extern crate foo_lib;
-
- fn main() { foo_lib::foo(); }
- "#)
- .file("src/foo_lib.rs", r#"
- #![feature(plugin)]
- #![plugin(bar)]
-
- pub fn foo() {}
- "#)
- .build();
- let _bar = project("bar")
- .file("Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
-
- [lib]
- name = "bar"
- plugin = true
-
- [dependencies.baz]
- path = "../baz"
- "#)
- .file("src/lib.rs", r#"
- #![feature(plugin_registrar, rustc_private)]
-
- extern crate rustc_plugin;
- extern crate baz;
-
- use rustc_plugin::Registry;
-
- #[plugin_registrar]
- pub fn foo(_reg: &mut Registry) {
- println!("{}", baz::baz());
- }
- "#)
- .build();
- let _baz = project("baz")
- .file("Cargo.toml", r#"
- [package]
- name = "baz"
- version = "0.0.1"
- authors = []
-
- [lib]
- name = "baz"
- crate_type = ["dylib"]
- "#)
- .file("src/lib.rs", "pub fn baz() -> i32 { 1 }")
- .build();
-
- assert_that(foo.cargo("build"),
- execs().with_status(0));
- assert_that(foo.cargo("doc"),
- execs().with_status(0));
-}
-
-#[test]
-fn plugin_with_dynamic_native_dependency() {
- if !is_nightly() { return }
-
- let workspace = project("ws")
- .file("Cargo.toml", r#"
- [workspace]
- members = ["builder", "foo"]
- "#)
- .build();
-
- let build = project("ws/builder")
- .file("Cargo.toml", r#"
- [package]
- name = "builder"
- version = "0.0.1"
- authors = []
-
- [lib]
- name = "builder"
- crate-type = ["dylib"]
- "#)
- .file("src/lib.rs", r#"
- #[no_mangle]
- pub extern fn foo() {}
- "#)
- .build();
-
- let foo = project("ws/foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies.bar]
- path = "bar"
- "#)
- .file("src/main.rs", r#"
- #![feature(plugin)]
- #![plugin(bar)]
-
- fn main() {}
- "#)
- .file("bar/Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
- build = 'build.rs'
-
- [lib]
- name = "bar"
- plugin = true
- "#)
- .file("bar/build.rs", r#"
- use std::path::PathBuf;
- use std::env;
-
- fn main() {
- let src = PathBuf::from(env::var("SRC").unwrap());
- println!("cargo:rustc-flags=-L {}/deps", src.parent().unwrap().display());
- }
- "#)
- .file("bar/src/lib.rs", r#"
- #![feature(plugin_registrar, rustc_private)]
- extern crate rustc_plugin;
-
- use rustc_plugin::Registry;
-
- #[cfg_attr(not(target_env = "msvc"), link(name = "builder"))]
- #[cfg_attr(target_env = "msvc", link(name = "builder.dll"))]
- extern { fn foo(); }
-
- #[plugin_registrar]
- pub fn bar(_reg: &mut Registry) {
- unsafe { foo() }
- }
- "#)
- .build();
-
- assert_that(build.cargo("build"),
- execs().with_status(0));
-
- let src = workspace.root().join("target/debug");
- let lib = fs::read_dir(&src).unwrap().map(|s| s.unwrap().path()).find(|lib| {
- let lib = lib.file_name().unwrap().to_str().unwrap();
- lib.starts_with(env::consts::DLL_PREFIX) &&
- lib.ends_with(env::consts::DLL_SUFFIX)
- }).unwrap();
-
- assert_that(foo.cargo("build").env("SRC", &lib).arg("-v"),
- execs().with_status(0));
-}
-
-#[test]
-fn plugin_integration() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- build = "build.rs"
-
- [lib]
- name = "foo"
- plugin = true
- doctest = false
- "#)
- .file("build.rs", "fn main() {}")
- .file("src/lib.rs", "")
- .file("tests/it_works.rs", "")
- .build();
-
- assert_that(p.cargo("test").arg("-v"),
- execs().with_status(0));
-}
-
-#[test]
-fn doctest_a_plugin() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- bar = { path = "bar" }
- "#)
- .file("src/lib.rs", r#"
- #[macro_use]
- extern crate bar;
- "#)
- .file("bar/Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
-
- [lib]
- name = "bar"
- plugin = true
- "#)
- .file("bar/src/lib.rs", r#"
- pub fn bar() {}
- "#)
- .build();
-
- assert_that(p.cargo("test").arg("-v"),
- execs().with_status(0));
-}
-
-// See #1515
-#[test]
-fn native_plugin_dependency_with_custom_ar_linker() {
- let target = rustc_host();
-
- let _foo = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [lib]
- plugin = true
- "#)
- .file("src/lib.rs", "")
- .build();
-
- let bar = project("bar")
- .file("Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
-
- [dependencies.foo]
- path = "../foo"
- "#)
- .file("src/lib.rs", "")
- .file(".cargo/config", &format!(r#"
- [target.{}]
- ar = "nonexistent-ar"
- linker = "nonexistent-linker"
- "#, target))
- .build();
-
- assert_that(bar.cargo("build").arg("--verbose"),
- execs().with_stderr_contains("\
-[COMPILING] foo v0.0.1 ([..])
-[RUNNING] `rustc [..] -C ar=nonexistent-ar -C linker=nonexistent-linker [..]`
-[ERROR] [..]linker[..]
-"));
-}
-
-#[test]
-fn panic_abort_plugins() {
- if !is_nightly() {
- return
- }
-
- let p = project("bar")
- .file("Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
-
- [profile.dev]
- panic = 'abort'
-
- [dependencies]
- foo = { path = "foo" }
- "#)
- .file("src/lib.rs", "")
- .file("foo/Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [lib]
- plugin = true
- "#)
- .file("foo/src/lib.rs", r#"
- #![feature(rustc_private)]
- extern crate syntax;
- "#)
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0));
-}
-
-#[test]
-fn shared_panic_abort_plugins() {
- if !is_nightly() {
- return
- }
-
- let p = project("top")
- .file("Cargo.toml", r#"
- [package]
- name = "top"
- version = "0.0.1"
- authors = []
-
- [profile.dev]
- panic = 'abort'
-
- [dependencies]
- foo = { path = "foo" }
- bar = { path = "bar" }
- "#)
- .file("src/lib.rs", "
- extern crate bar;
- ")
- .file("foo/Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [lib]
- plugin = true
-
- [dependencies]
- bar = { path = "../bar" }
- "#)
- .file("foo/src/lib.rs", r#"
- #![feature(rustc_private)]
- extern crate syntax;
- extern crate bar;
- "#)
- .file("bar/Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
- "#)
- .file("bar/src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0));
-}
+++ /dev/null
-extern crate cargotest;
-extern crate hamcrest;
-
-use cargotest::is_nightly;
-use cargotest::support::{project, execs};
-use hamcrest::assert_that;
-
-#[test]
-fn probe_cfg_before_crate_type_discovery() {
- if !is_nightly() {
- return;
- }
-
- let client = project("client")
- .file("Cargo.toml", r#"
- [package]
- name = "client"
- version = "0.0.1"
- authors = []
-
- [target.'cfg(not(stage300))'.dependencies.noop]
- path = "../noop"
- "#)
- .file("src/main.rs", r#"
- #![feature(proc_macro)]
-
- #[macro_use]
- extern crate noop;
-
- #[derive(Noop)]
- struct X;
-
- fn main() {}
- "#)
- .build();
- let _noop = project("noop")
- .file("Cargo.toml", r#"
- [package]
- name = "noop"
- version = "0.0.1"
- authors = []
-
- [lib]
- proc-macro = true
- "#)
- .file("src/lib.rs", r#"
- #![feature(proc_macro, proc_macro_lib)]
-
- extern crate proc_macro;
- use proc_macro::TokenStream;
-
- #[proc_macro_derive(Noop)]
- pub fn noop(_input: TokenStream) -> TokenStream {
- "".parse().unwrap()
- }
- "#)
- .build();
-
- assert_that(client.cargo("build"),
- execs().with_status(0));
-}
-
-#[test]
-fn noop() {
- if !is_nightly() {
- return;
- }
-
- let client = project("client")
- .file("Cargo.toml", r#"
- [package]
- name = "client"
- version = "0.0.1"
- authors = []
-
- [dependencies.noop]
- path = "../noop"
- "#)
- .file("src/main.rs", r#"
- #![feature(proc_macro)]
-
- #[macro_use]
- extern crate noop;
-
- #[derive(Noop)]
- struct X;
-
- fn main() {}
- "#)
- .build();
- let _noop = project("noop")
- .file("Cargo.toml", r#"
- [package]
- name = "noop"
- version = "0.0.1"
- authors = []
-
- [lib]
- proc-macro = true
- "#)
- .file("src/lib.rs", r#"
- #![feature(proc_macro, proc_macro_lib)]
-
- extern crate proc_macro;
- use proc_macro::TokenStream;
-
- #[proc_macro_derive(Noop)]
- pub fn noop(_input: TokenStream) -> TokenStream {
- "".parse().unwrap()
- }
- "#)
- .build();
-
- assert_that(client.cargo("build"),
- execs().with_status(0));
- assert_that(client.cargo("build"),
- execs().with_status(0));
-}
-
-#[test]
-fn impl_and_derive() {
- if !is_nightly() {
- return;
- }
-
- let client = project("client")
- .file("Cargo.toml", r#"
- [package]
- name = "client"
- version = "0.0.1"
- authors = []
-
- [dependencies.transmogrify]
- path = "../transmogrify"
- "#)
- .file("src/main.rs", r#"
- #![feature(proc_macro)]
-
- #[macro_use]
- extern crate transmogrify;
-
- trait ImplByTransmogrify {
- fn impl_by_transmogrify(&self) -> bool;
- }
-
- #[derive(Transmogrify, Debug)]
- struct X { success: bool }
-
- fn main() {
- let x = X::new();
- assert!(x.impl_by_transmogrify());
- println!("{:?}", x);
- }
- "#)
- .build();
- let _transmogrify = project("transmogrify")
- .file("Cargo.toml", r#"
- [package]
- name = "transmogrify"
- version = "0.0.1"
- authors = []
-
- [lib]
- proc-macro = true
- "#)
- .file("src/lib.rs", r#"
- #![feature(proc_macro, proc_macro_lib)]
-
- extern crate proc_macro;
- use proc_macro::TokenStream;
-
- #[proc_macro_derive(Transmogrify)]
- #[doc(hidden)]
- pub fn transmogrify(input: TokenStream) -> TokenStream {
- "
- impl X {
- fn new() -> Self {
- X { success: true }
- }
- }
-
- impl ImplByTransmogrify for X {
- fn impl_by_transmogrify(&self) -> bool {
- true
- }
- }
- ".parse().unwrap()
- }
- "#)
- .build();
-
- assert_that(client.cargo("build"),
- execs().with_status(0));
- assert_that(client.cargo("run"),
- execs().with_status(0).with_stdout("X { success: true }"));
-}
-
-#[test]
-fn plugin_and_proc_macro() {
- if !is_nightly() {
- return;
- }
-
- let questionable = project("questionable")
- .file("Cargo.toml", r#"
- [package]
- name = "questionable"
- version = "0.0.1"
- authors = []
-
- [lib]
- plugin = true
- proc-macro = true
- "#)
- .file("src/lib.rs", r#"
- #![feature(plugin_registrar, rustc_private)]
- #![feature(proc_macro, proc_macro_lib)]
-
- extern crate rustc_plugin;
- use rustc_plugin::Registry;
-
- extern crate proc_macro;
- use proc_macro::TokenStream;
-
- #[plugin_registrar]
- pub fn plugin_registrar(reg: &mut Registry) {}
-
- #[proc_macro_derive(Questionable)]
- pub fn questionable(input: TokenStream) -> TokenStream {
- input
- }
- "#)
- .build();
-
- let msg = " lib.plugin and lib.proc-macro cannot both be true";
- assert_that(questionable.cargo("build"),
- execs().with_status(101).with_stderr_contains(msg));
-}
-
-#[test]
-fn proc_macro_doctest() {
- if !is_nightly() {
- return
- }
- let foo = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
- [lib]
- proc-macro = true
- "#)
- .file("src/lib.rs", r#"
-#![feature(proc_macro, proc_macro_lib)]
-#![crate_type = "proc-macro"]
-
-extern crate proc_macro;
-
-use proc_macro::TokenStream;
-
-/// ```
-/// assert!(true);
-/// ```
-#[proc_macro_derive(Bar)]
-pub fn derive(_input: TokenStream) -> TokenStream {
- "".parse().unwrap()
-}
-
-#[test]
-fn a() {
- assert!(true);
-}
-"#)
- .build();
-
- assert_that(foo.cargo("test"),
- execs().with_status(0)
- .with_stdout_contains("test a ... ok")
- .with_stdout_contains_n("test [..] ... ok", 2));
-}
+++ /dev/null
-extern crate cargotest;
-extern crate hamcrest;
-
-use std::env;
-
-use cargotest::is_nightly;
-use cargotest::support::{project, execs};
-use hamcrest::assert_that;
-
-#[test]
-fn profile_overrides() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
-
- name = "test"
- version = "0.0.0"
- authors = []
-
- [profile.dev]
- opt-level = 1
- debug = false
- rpath = true
- "#)
- .file("src/lib.rs", "")
- .build();
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(0).with_stderr(&format!("\
-[COMPILING] test v0.0.0 ({url})
-[RUNNING] `rustc --crate-name test src[/]lib.rs --crate-type lib \
- --emit=dep-info,link \
- -C opt-level=1 \
- -C debug-assertions=on \
- -C metadata=[..] \
- -C rpath \
- --out-dir [..] \
- -L dependency={dir}[/]target[/]debug[/]deps`
-[FINISHED] dev [optimized] target(s) in [..]
-",
-dir = p.root().display(),
-url = p.url(),
-)));
-}
-
-#[test]
-fn opt_level_override_0() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
-
- name = "test"
- version = "0.0.0"
- authors = []
-
- [profile.dev]
- opt-level = 0
- "#)
- .file("src/lib.rs", "")
- .build();
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(0).with_stderr(&format!("\
-[COMPILING] test v0.0.0 ({url})
-[RUNNING] `rustc --crate-name test src[/]lib.rs --crate-type lib \
- --emit=dep-info,link \
- -C debuginfo=2 \
- -C metadata=[..] \
- --out-dir [..] \
- -L dependency={dir}[/]target[/]debug[/]deps`
-[FINISHED] [..] target(s) in [..]
-",
-dir = p.root().display(),
-url = p.url()
-)));
-}
-
-#[test]
-fn debug_override_1() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "test"
- version = "0.0.0"
- authors = []
-
- [profile.dev]
- debug = 1
- "#)
- .file("src/lib.rs", "")
- .build();
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(0).with_stderr(&format!("\
-[COMPILING] test v0.0.0 ({url})
-[RUNNING] `rustc --crate-name test src[/]lib.rs --crate-type lib \
- --emit=dep-info,link \
- -C debuginfo=1 \
- -C metadata=[..] \
- --out-dir [..] \
- -L dependency={dir}[/]target[/]debug[/]deps`
-[FINISHED] [..] target(s) in [..]
-",
-dir = p.root().display(),
-url = p.url()
-)));
-}
-
-fn check_opt_level_override(profile_level: &str, rustc_level: &str) {
- let p = project("foo")
- .file("Cargo.toml", &format!(r#"
- [package]
-
- name = "test"
- version = "0.0.0"
- authors = []
-
- [profile.dev]
- opt-level = {level}
- "#, level = profile_level))
- .file("src/lib.rs", "")
- .build();
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(0).with_stderr(&format!("\
-[COMPILING] test v0.0.0 ({url})
-[RUNNING] `rustc --crate-name test src[/]lib.rs --crate-type lib \
- --emit=dep-info,link \
- -C opt-level={level} \
- -C debuginfo=2 \
- -C debug-assertions=on \
- -C metadata=[..] \
- --out-dir [..] \
- -L dependency={dir}[/]target[/]debug[/]deps`
-[FINISHED] [..] target(s) in [..]
-",
-dir = p.root().display(),
-url = p.url(),
-level = rustc_level
-)));
-}
-
-#[test]
-fn opt_level_overrides() {
- if !is_nightly() { return }
-
- for &(profile_level, rustc_level) in &[
- ("1", "1"),
- ("2", "2"),
- ("3", "3"),
- ("\"s\"", "s"),
- ("\"z\"", "z"),
- ] {
- check_opt_level_override(profile_level, rustc_level)
- }
-}
-
-#[test]
-fn top_level_overrides_deps() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
-
- name = "test"
- version = "0.0.0"
- authors = []
-
- [profile.release]
- opt-level = 1
- debug = true
-
- [dependencies.foo]
- path = "foo"
- "#)
- .file("src/lib.rs", "")
- .file("foo/Cargo.toml", r#"
- [package]
-
- name = "foo"
- version = "0.0.0"
- authors = []
-
- [profile.release]
- opt-level = 0
- debug = false
-
- [lib]
- name = "foo"
- crate_type = ["dylib", "rlib"]
- "#)
- .file("foo/src/lib.rs", "")
- .build();
- assert_that(p.cargo("build").arg("-v").arg("--release"),
- execs().with_status(0).with_stderr(&format!("\
-[COMPILING] foo v0.0.0 ({url}/foo)
-[RUNNING] `rustc --crate-name foo foo[/]src[/]lib.rs \
- --crate-type dylib --crate-type rlib \
- --emit=dep-info,link \
- -C prefer-dynamic \
- -C opt-level=1 \
- -C debuginfo=2 \
- -C metadata=[..] \
- --out-dir {dir}[/]target[/]release[/]deps \
- -L dependency={dir}[/]target[/]release[/]deps`
-[COMPILING] test v0.0.0 ({url})
-[RUNNING] `rustc --crate-name test src[/]lib.rs --crate-type lib \
- --emit=dep-info,link \
- -C opt-level=1 \
- -C debuginfo=2 \
- -C metadata=[..] \
- --out-dir [..] \
- -L dependency={dir}[/]target[/]release[/]deps \
- --extern foo={dir}[/]target[/]release[/]deps[/]\
- {prefix}foo[..]{suffix} \
- --extern foo={dir}[/]target[/]release[/]deps[/]libfoo.rlib`
-[FINISHED] release [optimized + debuginfo] target(s) in [..]
-",
- dir = p.root().display(),
- url = p.url(),
- prefix = env::consts::DLL_PREFIX,
- suffix = env::consts::DLL_SUFFIX)));
-}
-
-#[test]
-fn profile_in_non_root_manifest_triggers_a_warning() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.1.0"
- authors = []
-
- [workspace]
- members = ["bar"]
-
- [profile.dev]
- debug = false
- "#)
- .file("src/main.rs", "fn main() {}")
- .file("bar/Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.1.0"
- authors = []
- workspace = ".."
-
- [profile.dev]
- opt-level = 1
- "#)
- .file("bar/src/main.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("build").cwd(p.root().join("bar")).arg("-v"),
- execs().with_status(0).with_stderr("\
-[WARNING] profiles for the non root package will be ignored, specify profiles at the workspace root:
-package: [..]
-workspace: [..]
-[COMPILING] bar v0.1.0 ([..])
-[RUNNING] `rustc [..]`
-[FINISHED] dev [unoptimized] target(s) in [..]"));
-}
-
-#[test]
-fn profile_in_virtual_manifest_works() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [workspace]
- members = ["bar"]
-
- [profile.dev]
- opt-level = 1
- debug = false
- "#)
- .file("src/main.rs", "fn main() {}")
- .file("bar/Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.1.0"
- authors = []
- workspace = ".."
- "#)
- .file("bar/src/main.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("build").cwd(p.root().join("bar")).arg("-v"),
- execs().with_status(0).with_stderr("\
-[COMPILING] bar v0.1.0 ([..])
-[RUNNING] `rustc [..]`
-[FINISHED] dev [optimized] target(s) in [..]"));
-}
+++ /dev/null
-extern crate cargotest;
-extern crate flate2;
-extern crate hamcrest;
-extern crate tar;
-
-use std::io::prelude::*;
-use std::fs::{self, File};
-use std::io::SeekFrom;
-
-use cargotest::ChannelChanger;
-use cargotest::support::git::repo;
-use cargotest::support::paths;
-use cargotest::support::{project, execs, publish};
-use flate2::read::GzDecoder;
-use hamcrest::assert_that;
-use tar::Archive;
-
-#[test]
-fn simple() {
- publish::setup();
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- license = "MIT"
- description = "foo"
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("publish").arg("--no-verify")
- .arg("--index").arg(publish::registry().to_string()),
- execs().with_status(0).with_stderr(&format!("\
-[UPDATING] registry `{reg}`
-[WARNING] manifest has no documentation, [..]
-See [..]
-[PACKAGING] foo v0.0.1 ({dir})
-[UPLOADING] foo v0.0.1 ({dir})
-",
- dir = p.url(),
- reg = publish::registry())));
-
- let mut f = File::open(&publish::upload_path().join("api/v1/crates/new")).unwrap();
- // Skip the metadata payload and the size of the tarball
- let mut sz = [0; 4];
- assert_eq!(f.read(&mut sz).unwrap(), 4);
- let sz = ((sz[0] as u32) << 0) |
- ((sz[1] as u32) << 8) |
- ((sz[2] as u32) << 16) |
- ((sz[3] as u32) << 24);
- f.seek(SeekFrom::Current(sz as i64 + 4)).unwrap();
-
- // Verify the tarball
- let mut rdr = GzDecoder::new(f);
- assert_eq!(rdr.header().unwrap().filename().unwrap(), b"foo-0.0.1.crate");
- let mut contents = Vec::new();
- rdr.read_to_end(&mut contents).unwrap();
- let mut ar = Archive::new(&contents[..]);
- for file in ar.entries().unwrap() {
- let file = file.unwrap();
- let fname = file.header().path_bytes();
- let fname = &*fname;
- assert!(fname == b"foo-0.0.1/Cargo.toml" ||
- fname == b"foo-0.0.1/Cargo.toml.orig" ||
- fname == b"foo-0.0.1/src/main.rs",
- "unexpected filename: {:?}", file.header().path());
- }
-}
-
-#[test]
-fn old_token_location() {
- publish::setup();
-
- // publish::setup puts a token in this file.
- fs::remove_file(paths::root().join(".cargo/config")).unwrap();
-
- let credentials = paths::root().join("home/.cargo/credentials");
- File::create(credentials)
- .unwrap()
- .write_all(br#"
- token = "api-token"
- "#)
- .unwrap();
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- license = "MIT"
- description = "foo"
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("publish").arg("--no-verify")
- .arg("--index").arg(publish::registry().to_string()),
- execs().with_status(0).with_stderr(&format!("\
-[UPDATING] registry `{reg}`
-[WARNING] manifest has no documentation, [..]
-See [..]
-[PACKAGING] foo v0.0.1 ({dir})
-[UPLOADING] foo v0.0.1 ({dir})
-",
- dir = p.url(),
- reg = publish::registry())));
-
- let mut f = File::open(&publish::upload_path().join("api/v1/crates/new")).unwrap();
- // Skip the metadata payload and the size of the tarball
- let mut sz = [0; 4];
- assert_eq!(f.read(&mut sz).unwrap(), 4);
- let sz = ((sz[0] as u32) << 0) |
- ((sz[1] as u32) << 8) |
- ((sz[2] as u32) << 16) |
- ((sz[3] as u32) << 24);
- f.seek(SeekFrom::Current(sz as i64 + 4)).unwrap();
-
- // Verify the tarball
- let mut rdr = GzDecoder::new(f);
- assert_eq!(rdr.header().unwrap().filename().unwrap(), b"foo-0.0.1.crate");
- let mut contents = Vec::new();
- rdr.read_to_end(&mut contents).unwrap();
- let mut ar = Archive::new(&contents[..]);
- for file in ar.entries().unwrap() {
- let file = file.unwrap();
- let fname = file.header().path_bytes();
- let fname = &*fname;
- assert!(fname == b"foo-0.0.1/Cargo.toml" ||
- fname == b"foo-0.0.1/Cargo.toml.orig" ||
- fname == b"foo-0.0.1/src/main.rs",
- "unexpected filename: {:?}", file.header().path());
- }
-}
-
-// TODO: Deprecated
-// remove once it has been decided --host can be removed
-#[test]
-fn simple_with_host() {
- publish::setup();
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- license = "MIT"
- description = "foo"
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("publish").arg("--no-verify")
- .arg("--host").arg(publish::registry().to_string()),
- execs().with_status(0).with_stderr(&format!("\
-[WARNING] The flag '--host' is no longer valid.
-
-Previous versions of Cargo accepted this flag, but it is being
-deprecated. The flag is being renamed to 'index', as the flag
-wants the location of the index to which to publish. Please
-use '--index' instead.
-
-This will soon become a hard error, so it's either recommended
-to update to a fixed version or contact the upstream maintainer
-about this warning.
-[UPDATING] registry `{reg}`
-[WARNING] manifest has no documentation, [..]
-See [..]
-[PACKAGING] foo v0.0.1 ({dir})
-[UPLOADING] foo v0.0.1 ({dir})
-",
- dir = p.url(),
- reg = publish::registry())));
-
- let mut f = File::open(&publish::upload_path().join("api/v1/crates/new")).unwrap();
- // Skip the metadata payload and the size of the tarball
- let mut sz = [0; 4];
- assert_eq!(f.read(&mut sz).unwrap(), 4);
- let sz = ((sz[0] as u32) << 0) |
- ((sz[1] as u32) << 8) |
- ((sz[2] as u32) << 16) |
- ((sz[3] as u32) << 24);
- f.seek(SeekFrom::Current(sz as i64 + 4)).unwrap();
-
- // Verify the tarball
- let mut rdr = GzDecoder::new(f);
- assert_eq!(rdr.header().unwrap().filename().unwrap(), "foo-0.0.1.crate".as_bytes());
- let mut contents = Vec::new();
- rdr.read_to_end(&mut contents).unwrap();
- let mut ar = Archive::new(&contents[..]);
- for file in ar.entries().unwrap() {
- let file = file.unwrap();
- let fname = file.header().path_bytes();
- let fname = &*fname;
- assert!(fname == b"foo-0.0.1/Cargo.toml" ||
- fname == b"foo-0.0.1/Cargo.toml.orig" ||
- fname == b"foo-0.0.1/src/main.rs",
- "unexpected filename: {:?}", file.header().path());
- }
-}
-
-// TODO: Deprecated
-// remove once it has been decided --host can be removed
-#[test]
-fn simple_with_index_and_host() {
- publish::setup();
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- license = "MIT"
- description = "foo"
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("publish").arg("--no-verify")
- .arg("--index").arg(publish::registry().to_string())
- .arg("--host").arg(publish::registry().to_string()),
- execs().with_status(0).with_stderr(&format!("\
-[WARNING] The flag '--host' is no longer valid.
-
-Previous versions of Cargo accepted this flag, but it is being
-deprecated. The flag is being renamed to 'index', as the flag
-wants the location of the index to which to publish. Please
-use '--index' instead.
-
-This will soon become a hard error, so it's either recommended
-to update to a fixed version or contact the upstream maintainer
-about this warning.
-[UPDATING] registry `{reg}`
-[WARNING] manifest has no documentation, [..]
-See [..]
-[PACKAGING] foo v0.0.1 ({dir})
-[UPLOADING] foo v0.0.1 ({dir})
-",
- dir = p.url(),
- reg = publish::registry())));
-
- let mut f = File::open(&publish::upload_path().join("api/v1/crates/new")).unwrap();
- // Skip the metadata payload and the size of the tarball
- let mut sz = [0; 4];
- assert_eq!(f.read(&mut sz).unwrap(), 4);
- let sz = ((sz[0] as u32) << 0) |
- ((sz[1] as u32) << 8) |
- ((sz[2] as u32) << 16) |
- ((sz[3] as u32) << 24);
- f.seek(SeekFrom::Current(sz as i64 + 4)).unwrap();
-
- // Verify the tarball
- let mut rdr = GzDecoder::new(f);
- assert_eq!(rdr.header().unwrap().filename().unwrap(), "foo-0.0.1.crate".as_bytes());
- let mut contents = Vec::new();
- rdr.read_to_end(&mut contents).unwrap();
- let mut ar = Archive::new(&contents[..]);
- for file in ar.entries().unwrap() {
- let file = file.unwrap();
- let fname = file.header().path_bytes();
- let fname = &*fname;
- assert!(fname == b"foo-0.0.1/Cargo.toml" ||
- fname == b"foo-0.0.1/Cargo.toml.orig" ||
- fname == b"foo-0.0.1/src/main.rs",
- "unexpected filename: {:?}", file.header().path());
- }
-}
-
-#[test]
-fn git_deps() {
- publish::setup();
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- license = "MIT"
- description = "foo"
-
- [dependencies.foo]
- git = "git://path/to/nowhere"
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("publish").arg("-v").arg("--no-verify")
- .arg("--index").arg(publish::registry().to_string()),
- execs().with_status(101).with_stderr("\
-[UPDATING] registry [..]
-[ERROR] crates cannot be published to crates.io with dependencies sourced from \
-a repository\neither publish `foo` as its own crate on crates.io and \
-specify a crates.io version as a dependency or pull it into this \
-repository and specify it with a path and version\n\
-(crate `foo` has repository path `git://path/to/nowhere`)\
-"));
-}
-
-#[test]
-fn path_dependency_no_version() {
- publish::setup();
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- license = "MIT"
- description = "foo"
-
- [dependencies.bar]
- path = "bar"
- "#)
- .file("src/main.rs", "fn main() {}")
- .file("bar/Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
- "#)
- .file("bar/src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("publish")
- .arg("--index").arg(publish::registry().to_string()),
- execs().with_status(101).with_stderr("\
-[UPDATING] registry [..]
-[ERROR] all path dependencies must have a version specified when publishing.
-dependency `bar` does not specify a version
-"));
-}
-
-#[test]
-fn unpublishable_crate() {
- publish::setup();
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- license = "MIT"
- description = "foo"
- publish = false
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("publish")
- .arg("--index").arg(publish::registry().to_string()),
- execs().with_status(101).with_stderr("\
-[ERROR] some crates cannot be published.
-`foo` is marked as unpublishable
-"));
-}
-
-#[test]
-fn dont_publish_dirty() {
- publish::setup();
- let p = project("foo")
- .file("bar", "")
- .build();
-
- let _ = repo(&paths::root().join("foo"))
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- license = "MIT"
- description = "foo"
- documentation = "foo"
- homepage = "foo"
- repository = "foo"
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("publish")
- .arg("--index").arg(publish::registry().to_string()),
- execs().with_status(101).with_stderr("\
-[UPDATING] registry `[..]`
-error: 1 files in the working directory contain changes that were not yet \
-committed into git:
-
-bar
-
-to proceed despite this, pass the `--allow-dirty` flag
-"));
-}
-
-#[test]
-fn publish_clean() {
- publish::setup();
-
- let p = project("foo").build();
-
- let _ = repo(&paths::root().join("foo"))
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- license = "MIT"
- description = "foo"
- documentation = "foo"
- homepage = "foo"
- repository = "foo"
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("publish")
- .arg("--index").arg(publish::registry().to_string()),
- execs().with_status(0));
-}
-
-#[test]
-fn publish_in_sub_repo() {
- publish::setup();
-
- let p = project("foo")
- .file("baz", "")
- .build();
-
- let _ = repo(&paths::root().join("foo"))
- .file("bar/Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- license = "MIT"
- description = "foo"
- documentation = "foo"
- homepage = "foo"
- repository = "foo"
- "#)
- .file("bar/src/main.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("publish").cwd(p.root().join("bar"))
- .arg("--index").arg(publish::registry().to_string()),
- execs().with_status(0));
-}
-
-#[test]
-fn publish_when_ignored() {
- publish::setup();
-
- let p = project("foo")
- .file("baz", "")
- .build();
-
- let _ = repo(&paths::root().join("foo"))
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- license = "MIT"
- description = "foo"
- documentation = "foo"
- homepage = "foo"
- repository = "foo"
- "#)
- .file("src/main.rs", "fn main() {}")
- .file(".gitignore", "baz")
- .build();
-
- assert_that(p.cargo("publish")
- .arg("--index").arg(publish::registry().to_string()),
- execs().with_status(0));
-}
-
-#[test]
-fn ignore_when_crate_ignored() {
- publish::setup();
-
- let p = project("foo")
- .file("bar/baz", "")
- .build();
-
- let _ = repo(&paths::root().join("foo"))
- .file(".gitignore", "bar")
- .nocommit_file("bar/Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- license = "MIT"
- description = "foo"
- documentation = "foo"
- homepage = "foo"
- repository = "foo"
- "#)
- .nocommit_file("bar/src/main.rs", "fn main() {}");
- assert_that(p.cargo("publish").cwd(p.root().join("bar"))
- .arg("--index").arg(publish::registry().to_string()),
- execs().with_status(0));
-}
-
-#[test]
-fn new_crate_rejected() {
- publish::setup();
-
- let p = project("foo")
- .file("baz", "")
- .build();
-
- let _ = repo(&paths::root().join("foo"))
- .nocommit_file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- license = "MIT"
- description = "foo"
- documentation = "foo"
- homepage = "foo"
- repository = "foo"
- "#)
- .nocommit_file("src/main.rs", "fn main() {}");
- assert_that(p.cargo("publish")
- .arg("--index").arg(publish::registry().to_string()),
- execs().with_status(101));
-}
-
-#[test]
-fn dry_run() {
- publish::setup();
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- license = "MIT"
- description = "foo"
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("publish").arg("--dry-run")
- .arg("--index").arg(publish::registry().to_string()),
- execs().with_status(0).with_stderr(&format!("\
-[UPDATING] registry `[..]`
-[WARNING] manifest has no documentation, [..]
-See [..]
-[PACKAGING] foo v0.0.1 ({dir})
-[VERIFYING] foo v0.0.1 ({dir})
-[COMPILING] foo v0.0.1 [..]
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[UPLOADING] foo v0.0.1 ({dir})
-[WARNING] aborting upload due to dry run
-",
- dir = p.url())));
-
- // Ensure the API request wasn't actually made
- assert!(!publish::upload_path().join("api/v1/crates/new").exists());
-}
-
-#[test]
-fn block_publish_feature_not_enabled() {
- publish::setup();
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- license = "MIT"
- description = "foo"
- publish = [
- "test"
- ]
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("publish").masquerade_as_nightly_cargo()
- .arg("--registry").arg("alternative").arg("-Zunstable-options"),
- execs().with_status(101).with_stderr("\
-error: failed to parse manifest at `[..]`
-
-Caused by:
- the `publish` manifest key is unstable for anything other than a value of true or false
-
-Caused by:
- feature `alternative-registries` is required
-
-consider adding `cargo-features = [\"alternative-registries\"]` to the manifest
-"));
-}
-
-#[test]
-fn registry_not_in_publish_list() {
- publish::setup();
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- cargo-features = ["alternative-registries"]
-
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- license = "MIT"
- description = "foo"
- publish = [
- "test"
- ]
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("publish").masquerade_as_nightly_cargo()
- .arg("--registry").arg("alternative").arg("-Zunstable-options"),
- execs().with_status(101).with_stderr("\
-[ERROR] some crates cannot be published.
-`foo` is marked as unpublishable
-"));
-}
-
-#[test]
-fn publish_empty_list() {
- publish::setup();
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- cargo-features = ["alternative-registries"]
-
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- license = "MIT"
- description = "foo"
- publish = []
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("publish").masquerade_as_nightly_cargo()
- .arg("--registry").arg("alternative").arg("-Zunstable-options"),
- execs().with_status(101).with_stderr("\
-[ERROR] some crates cannot be published.
-`foo` is marked as unpublishable
-"));
-}
-
-#[test]
-fn publish_allowed_registry() {
- publish::setup();
-
- let p = project("foo").build();
-
- let _ = repo(&paths::root().join("foo"))
- .file("Cargo.toml", r#"
- cargo-features = ["alternative-registries"]
-
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- license = "MIT"
- description = "foo"
- documentation = "foo"
- homepage = "foo"
- publish = ["alternative"]
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("publish").masquerade_as_nightly_cargo()
- .arg("--registry").arg("alternative").arg("-Zunstable-options"),
- execs().with_status(0));
-}
-
-#[test]
-fn block_publish_no_registry() {
- publish::setup();
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- cargo-features = ["alternative-registries"]
-
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- license = "MIT"
- description = "foo"
- publish = []
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("publish").masquerade_as_nightly_cargo()
- .arg("--registry").arg("alternative")
- .arg("-Zunstable-options"),
- execs().with_status(101).with_stderr("\
-[ERROR] some crates cannot be published.
-`foo` is marked as unpublishable
-"));
-}
+++ /dev/null
-extern crate cargotest;
-extern crate hamcrest;
-
-use cargotest::support::{project, execs, main_file, basic_bin_manifest};
-use hamcrest::{assert_that};
-
-static MANIFEST_OUTPUT: &'static str = r#"
-{
- "name":"foo",
- "version":"0.5.0",
- "id":"foo[..]0.5.0[..](path+file://[..]/foo)",
- "license": null,
- "license_file": null,
- "description": null,
- "source":null,
- "dependencies":[],
- "targets":[{
- "kind":["bin"],
- "crate_types":["bin"],
- "name":"foo",
- "src_path":"[..][/]foo[/]src[/]foo.rs"
- }],
- "features":{},
- "manifest_path":"[..]Cargo.toml"
-}"#;
-
-#[test]
-fn cargo_read_manifest_path_to_cargo_toml_relative() {
- let p = project("foo")
- .file("Cargo.toml", &basic_bin_manifest("foo"))
- .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
- .build();
-
- assert_that(p.cargo("read-manifest")
- .arg("--manifest-path").arg("foo/Cargo.toml")
- .cwd(p.root().parent().unwrap()),
- execs().with_status(0)
- .with_json(MANIFEST_OUTPUT));
-}
-
-#[test]
-fn cargo_read_manifest_path_to_cargo_toml_absolute() {
- let p = project("foo")
- .file("Cargo.toml", &basic_bin_manifest("foo"))
- .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
- .build();
-
- assert_that(p.cargo("read-manifest")
- .arg("--manifest-path").arg(p.root().join("Cargo.toml"))
- .cwd(p.root().parent().unwrap()),
- execs().with_status(0)
- .with_json(MANIFEST_OUTPUT));
-}
-
-#[test]
-fn cargo_read_manifest_path_to_cargo_toml_parent_relative() {
- let p = project("foo")
- .file("Cargo.toml", &basic_bin_manifest("foo"))
- .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
- .build();
-
- assert_that(p.cargo("read-manifest")
- .arg("--manifest-path").arg("foo")
- .cwd(p.root().parent().unwrap()),
- execs().with_status(101)
- .with_stderr("[ERROR] the manifest-path must be \
- a path to a Cargo.toml file"));
-}
-
-#[test]
-fn cargo_read_manifest_path_to_cargo_toml_parent_absolute() {
- let p = project("foo")
- .file("Cargo.toml", &basic_bin_manifest("foo"))
- .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
- .build();
-
- assert_that(p.cargo("read-manifest")
- .arg("--manifest-path").arg(p.root())
- .cwd(p.root().parent().unwrap()),
- execs().with_status(101)
- .with_stderr("[ERROR] the manifest-path must be \
- a path to a Cargo.toml file"));
-}
-
-#[test]
-fn cargo_read_manifest_cwd() {
- let p = project("foo")
- .file("Cargo.toml", &basic_bin_manifest("foo"))
- .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
- .build();
-
- assert_that(p.cargo("read-manifest")
- .cwd(p.root()),
- execs().with_status(0)
- .with_json(MANIFEST_OUTPUT));
-}
+++ /dev/null
-#[macro_use]
-extern crate cargotest;
-extern crate hamcrest;
-extern crate url;
-
-use std::fs::{self, File};
-use std::io::prelude::*;
-use std::path::PathBuf;
-
-use cargotest::cargo_process;
-use cargotest::support::git;
-use cargotest::support::paths::{self, CargoPathExt};
-use cargotest::support::registry::{self, Package};
-use cargotest::support::{project, execs};
-use hamcrest::assert_that;
-use url::Url;
-
-fn registry_path() -> PathBuf { paths::root().join("registry") }
-fn registry() -> Url { Url::from_file_path(&*registry_path()).ok().unwrap() }
-
-#[test]
-fn simple() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- bar = ">= 0.0.0"
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- Package::new("bar", "0.0.1").publish();
-
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr(&format!("\
-[UPDATING] registry `{reg}`
-[DOWNLOADING] bar v0.0.1 (registry `file://[..]`)
-[COMPILING] bar v0.0.1
-[COMPILING] foo v0.0.1 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] secs
-",
- dir = p.url(),
- reg = registry::registry())));
-
- assert_that(p.cargo("clean"), execs().with_status(0));
-
- // Don't download a second time
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr(&format!("\
-[COMPILING] bar v0.0.1
-[COMPILING] foo v0.0.1 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] secs
-",
- dir = p.url())));
-}
-
-#[test]
-fn deps() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- bar = ">= 0.0.0"
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- Package::new("baz", "0.0.1").publish();
- Package::new("bar", "0.0.1").dep("baz", "*").publish();
-
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr(&format!("\
-[UPDATING] registry `{reg}`
-[DOWNLOADING] [..] v0.0.1 (registry `file://[..]`)
-[DOWNLOADING] [..] v0.0.1 (registry `file://[..]`)
-[COMPILING] baz v0.0.1
-[COMPILING] bar v0.0.1
-[COMPILING] foo v0.0.1 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] secs
-",
- dir = p.url(),
- reg = registry::registry())));
-}
-
-#[test]
-fn nonexistent() {
- Package::new("init", "0.0.1").publish();
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- nonexistent = ">= 0.0.0"
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(101).with_stderr("\
-[UPDATING] registry [..]
-error: no matching package named `nonexistent` found
-location searched: registry [..]
-required by package `foo v0.0.1 ([..])`
-"));
-}
-
-#[test]
-fn wrong_version() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- foo = ">= 1.0.0"
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- Package::new("foo", "0.0.1").publish();
- Package::new("foo", "0.0.2").publish();
-
- assert_that(p.cargo("build"),
- execs().with_status(101).with_stderr_contains("\
-error: no matching version `>= 1.0.0` found for package `foo`
-location searched: registry [..]
-versions found: 0.0.2, 0.0.1
-required by package `foo v0.0.1 ([..])`
-"));
-
- Package::new("foo", "0.0.3").publish();
- Package::new("foo", "0.0.4").publish();
-
- assert_that(p.cargo("build"),
- execs().with_status(101).with_stderr_contains("\
-error: no matching version `>= 1.0.0` found for package `foo`
-location searched: registry [..]
-versions found: 0.0.4, 0.0.3, 0.0.2, ...
-required by package `foo v0.0.1 ([..])`
-"));
-}
-
-#[test]
-fn bad_cksum() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- bad-cksum = ">= 0.0.0"
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- let pkg = Package::new("bad-cksum", "0.0.1");
- pkg.publish();
- t!(File::create(&pkg.archive_dst()));
-
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(101).with_stderr("\
-[UPDATING] registry [..]
-[DOWNLOADING] bad-cksum [..]
-[ERROR] unable to get packages from source
-
-Caused by:
- failed to download replaced source registry `https://[..]`
-
-Caused by:
- failed to verify the checksum of `bad-cksum v0.0.1 (registry `file://[..]`)`
-"));
-}
-
-#[test]
-fn update_registry() {
- Package::new("init", "0.0.1").publish();
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- notyet = ">= 0.0.0"
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(101).with_stderr_contains("\
-error: no matching package named `notyet` found
-location searched: registry `[..]`
-required by package `foo v0.0.1 ([..])`
-"));
-
- Package::new("notyet", "0.0.1").publish();
-
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr(&format!("\
-[UPDATING] registry `{reg}`
-[DOWNLOADING] notyet v0.0.1 (registry `file://[..]`)
-[COMPILING] notyet v0.0.1
-[COMPILING] foo v0.0.1 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] secs
-",
- dir = p.url(),
- reg = registry::registry())));
-}
-
-#[test]
-fn package_with_path_deps() {
- Package::new("init", "0.0.1").publish();
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- license = "MIT"
- description = "foo"
- repository = "bar"
-
- [dependencies.notyet]
- version = "0.0.1"
- path = "notyet"
- "#)
- .file("src/main.rs", "fn main() {}")
- .file("notyet/Cargo.toml", r#"
- [package]
- name = "notyet"
- version = "0.0.1"
- authors = []
- "#)
- .file("notyet/src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("package").arg("-v"),
- execs().with_status(101).with_stderr_contains("\
-[ERROR] failed to verify package tarball
-
-Caused by:
- no matching package named `notyet` found
-location searched: registry [..]
-required by package `foo v0.0.1 ([..])`
-"));
-
- Package::new("notyet", "0.0.1").publish();
-
- assert_that(p.cargo("package"),
- execs().with_status(0).with_stderr(format!("\
-[PACKAGING] foo v0.0.1 ({dir})
-[VERIFYING] foo v0.0.1 ({dir})
-[UPDATING] registry `[..]`
-[DOWNLOADING] notyet v0.0.1 (registry `file://[..]`)
-[COMPILING] notyet v0.0.1
-[COMPILING] foo v0.0.1 ({dir}[..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] secs
-", dir = p.url())));
-}
-
-#[test]
-fn lockfile_locks() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- bar = "*"
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- Package::new("bar", "0.0.1").publish();
-
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr(&format!("\
-[UPDATING] registry `[..]`
-[DOWNLOADING] bar v0.0.1 (registry `file://[..]`)
-[COMPILING] bar v0.0.1
-[COMPILING] foo v0.0.1 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] secs
-",
- dir = p.url())));
-
- p.root().move_into_the_past();
- Package::new("bar", "0.0.2").publish();
-
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stdout(""));
-}
-
-#[test]
-fn lockfile_locks_transitively() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- bar = "*"
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- Package::new("baz", "0.0.1").publish();
- Package::new("bar", "0.0.1").dep("baz", "*").publish();
-
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr(&format!("\
-[UPDATING] registry `[..]`
-[DOWNLOADING] [..] v0.0.1 (registry `file://[..]`)
-[DOWNLOADING] [..] v0.0.1 (registry `file://[..]`)
-[COMPILING] baz v0.0.1
-[COMPILING] bar v0.0.1
-[COMPILING] foo v0.0.1 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] secs
-",
- dir = p.url())));
-
- p.root().move_into_the_past();
- Package::new("baz", "0.0.2").publish();
- Package::new("bar", "0.0.2").dep("baz", "*").publish();
-
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stdout(""));
-}
-
-#[test]
-fn yanks_are_not_used() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- bar = "*"
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- Package::new("baz", "0.0.1").publish();
- Package::new("baz", "0.0.2").yanked(true).publish();
- Package::new("bar", "0.0.1").dep("baz", "*").publish();
- Package::new("bar", "0.0.2").dep("baz", "*").yanked(true).publish();
-
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr(&format!("\
-[UPDATING] registry `[..]`
-[DOWNLOADING] [..] v0.0.1 (registry `file://[..]`)
-[DOWNLOADING] [..] v0.0.1 (registry `file://[..]`)
-[COMPILING] baz v0.0.1
-[COMPILING] bar v0.0.1
-[COMPILING] foo v0.0.1 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] secs
-",
- dir = p.url())));
-}
-
-#[test]
-fn relying_on_a_yank_is_bad() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- bar = "*"
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- Package::new("baz", "0.0.1").publish();
- Package::new("baz", "0.0.2").yanked(true).publish();
- Package::new("bar", "0.0.1").dep("baz", "=0.0.2").publish();
-
- assert_that(p.cargo("build"),
- execs().with_status(101).with_stderr_contains("\
-error: no matching version `= 0.0.2` found for package `baz`
-location searched: registry `[..]`
-versions found: 0.0.1
-required by package `bar v0.0.1`
-"));
-}
-
-#[test]
-fn yanks_in_lockfiles_are_ok() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- bar = "*"
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- Package::new("bar", "0.0.1").publish();
-
- assert_that(p.cargo("build"),
- execs().with_status(0));
-
- registry::registry_path().join("3").rm_rf();
-
- Package::new("bar", "0.0.1").yanked(true).publish();
-
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stdout(""));
-
- assert_that(p.cargo("update"),
- execs().with_status(101).with_stderr_contains("\
-error: no matching package named `bar` found
-location searched: registry [..]
-required by package `foo v0.0.1 ([..])`
-"));
-}
-
-#[test]
-fn update_with_lockfile_if_packages_missing() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- bar = "*"
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- Package::new("bar", "0.0.1").publish();
- assert_that(p.cargo("build"),
- execs().with_status(0));
- p.root().move_into_the_past();
-
- paths::home().join(".cargo/registry").rm_rf();
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr("\
-[UPDATING] registry `[..]`
-[DOWNLOADING] bar v0.0.1 (registry `file://[..]`)
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] secs
-"));
-}
-
-#[test]
-fn update_lockfile() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- bar = "*"
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- println!("0.0.1");
- Package::new("bar", "0.0.1").publish();
- assert_that(p.cargo("build"),
- execs().with_status(0));
-
- Package::new("bar", "0.0.2").publish();
- Package::new("bar", "0.0.3").publish();
- paths::home().join(".cargo/registry").rm_rf();
- println!("0.0.2 update");
- assert_that(p.cargo("update")
- .arg("-p").arg("bar").arg("--precise").arg("0.0.2"),
- execs().with_status(0).with_stderr("\
-[UPDATING] registry `[..]`
-[UPDATING] bar v0.0.1 -> v0.0.2
-"));
-
- println!("0.0.2 build");
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr(&format!("\
-[DOWNLOADING] [..] v0.0.2 (registry `file://[..]`)
-[COMPILING] bar v0.0.2
-[COMPILING] foo v0.0.1 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] secs
-",
- dir = p.url())));
-
- println!("0.0.3 update");
- assert_that(p.cargo("update")
- .arg("-p").arg("bar"),
- execs().with_status(0).with_stderr("\
-[UPDATING] registry `[..]`
-[UPDATING] bar v0.0.2 -> v0.0.3
-"));
-
- println!("0.0.3 build");
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr(&format!("\
-[DOWNLOADING] [..] v0.0.3 (registry `file://[..]`)
-[COMPILING] bar v0.0.3
-[COMPILING] foo v0.0.1 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] secs
-",
- dir = p.url())));
-
- println!("new dependencies update");
- Package::new("bar", "0.0.4").dep("spam", "0.2.5").publish();
- Package::new("spam", "0.2.5").publish();
- assert_that(p.cargo("update")
- .arg("-p").arg("bar"),
- execs().with_status(0).with_stderr("\
-[UPDATING] registry `[..]`
-[UPDATING] bar v0.0.3 -> v0.0.4
-[ADDING] spam v0.2.5
-"));
-
- println!("new dependencies update");
- Package::new("bar", "0.0.5").publish();
- assert_that(p.cargo("update")
- .arg("-p").arg("bar"),
- execs().with_status(0).with_stderr("\
-[UPDATING] registry `[..]`
-[UPDATING] bar v0.0.4 -> v0.0.5
-[REMOVING] spam v0.2.5
-"));
-}
-
-#[test]
-fn update_offline(){
- use cargotest::ChannelChanger;
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- bar = "*"
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
- assert_that(p.cargo("update").masquerade_as_nightly_cargo().arg("-Zoffline"),
- execs().with_status(101).
- with_stderr("error: you can't update in the offline mode[..]"));
-}
-
-#[test]
-fn dev_dependency_not_used() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- bar = "*"
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- Package::new("baz", "0.0.1").publish();
- Package::new("bar", "0.0.1").dev_dep("baz", "*").publish();
-
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr(&format!("\
-[UPDATING] registry `[..]`
-[DOWNLOADING] [..] v0.0.1 (registry `file://[..]`)
-[COMPILING] bar v0.0.1
-[COMPILING] foo v0.0.1 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] secs
-",
- dir = p.url())));
-}
-
-#[test]
-fn login_with_no_cargo_dir() {
- let home = paths::home().join("new-home");
- t!(fs::create_dir(&home));
- assert_that(cargo_process().arg("login").arg("foo").arg("-v"),
- execs().with_status(0));
-}
-
-#[test]
-fn login_with_differently_sized_token() {
- // Verify that the configuration file gets properly trunchated.
- let home = paths::home().join("new-home");
- t!(fs::create_dir(&home));
- assert_that(cargo_process().arg("login").arg("lmaolmaolmao").arg("-v"),
- execs().with_status(0));
- assert_that(cargo_process().arg("login").arg("lmao").arg("-v"),
- execs().with_status(0));
- assert_that(cargo_process().arg("login").arg("lmaolmaolmao").arg("-v"),
- execs().with_status(0));
-}
-
-#[test]
-fn bad_license_file() {
- Package::new("foo", "1.0.0").publish();
- let p = project("all")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- license-file = "foo"
- description = "bar"
- repository = "baz"
- "#)
- .file("src/main.rs", r#"
- fn main() {}
- "#)
- .build();
- assert_that(p.cargo("publish")
- .arg("-v")
- .arg("--index").arg(registry().to_string()),
- execs().with_status(101)
- .with_stderr_contains("\
-[ERROR] the license file `foo` does not exist"));
-}
-
-#[test]
-fn updating_a_dep() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies.a]
- path = "a"
- "#)
- .file("src/main.rs", "fn main() {}")
- .file("a/Cargo.toml", r#"
- [project]
- name = "a"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- bar = "*"
- "#)
- .file("a/src/lib.rs", "")
- .build();
-
- Package::new("bar", "0.0.1").publish();
-
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr(&format!("\
-[UPDATING] registry `[..]`
-[DOWNLOADING] bar v0.0.1 (registry `file://[..]`)
-[COMPILING] bar v0.0.1
-[COMPILING] a v0.0.1 ({dir}/a)
-[COMPILING] foo v0.0.1 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] secs
-",
- dir = p.url())));
-
- t!(t!(File::create(&p.root().join("a/Cargo.toml"))).write_all(br#"
- [project]
- name = "a"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- bar = "0.1.0"
- "#));
- Package::new("bar", "0.1.0").publish();
-
- println!("second");
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr(&format!("\
-[UPDATING] registry `[..]`
-[DOWNLOADING] bar v0.1.0 (registry `file://[..]`)
-[COMPILING] bar v0.1.0
-[COMPILING] a v0.0.1 ({dir}/a)
-[COMPILING] foo v0.0.1 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] secs
-",
- dir = p.url())));
-}
-
-#[test]
-fn git_and_registry_dep() {
- let b = git::repo(&paths::root().join("b"))
- .file("Cargo.toml", r#"
- [project]
- name = "b"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- a = "0.0.1"
- "#)
- .file("src/lib.rs", "")
- .build();
- let p = project("foo")
- .file("Cargo.toml", &format!(r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- a = "0.0.1"
-
- [dependencies.b]
- git = '{}'
- "#, b.url()))
- .file("src/main.rs", "fn main() {}")
- .build();
-
- Package::new("a", "0.0.1").publish();
-
- p.root().move_into_the_past();
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr(&format!("\
-[UPDATING] [..]
-[UPDATING] [..]
-[DOWNLOADING] a v0.0.1 (registry `file://[..]`)
-[COMPILING] a v0.0.1
-[COMPILING] b v0.0.1 ([..])
-[COMPILING] foo v0.0.1 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] secs
-",
- dir = p.url())));
- p.root().move_into_the_past();
-
- println!("second");
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stdout(""));
-}
-
-#[test]
-fn update_publish_then_update() {
- // First generate a Cargo.lock and a clone of the registry index at the
- // "head" of the current registry.
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.5.0"
- authors = []
-
- [dependencies]
- a = "0.1.0"
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
- Package::new("a", "0.1.0").publish();
- assert_that(p.cargo("build"),
- execs().with_status(0));
-
- // Next, publish a new package and back up the copy of the registry we just
- // created.
- Package::new("a", "0.1.1").publish();
- let registry = paths::home().join(".cargo/registry");
- let backup = paths::root().join("registry-backup");
- t!(fs::rename(®istry, &backup));
-
- // Generate a Cargo.lock with the newer version, and then move the old copy
- // of the registry back into place.
- let p2 = project("foo2")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.5.0"
- authors = []
-
- [dependencies]
- a = "0.1.1"
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
- assert_that(p2.cargo("build"),
- execs().with_status(0));
- registry.rm_rf();
- t!(fs::rename(&backup, ®istry));
- t!(fs::rename(p2.root().join("Cargo.lock"), p.root().join("Cargo.lock")));
-
- // Finally, build the first project again (with our newer Cargo.lock) which
- // should force an update of the old registry, download the new crate, and
- // then build everything again.
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr(&format!("\
-[UPDATING] [..]
-[DOWNLOADING] a v0.1.1 (registry `file://[..]`)
-[COMPILING] a v0.1.1
-[COMPILING] foo v0.5.0 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] secs
-",
- dir = p.url())));
-
-}
-
-#[test]
-fn fetch_downloads() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.5.0"
- authors = []
-
- [dependencies]
- a = "0.1.0"
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- Package::new("a", "0.1.0").publish();
-
- assert_that(p.cargo("fetch"),
- execs().with_status(0)
- .with_stderr("\
-[UPDATING] registry `[..]`
-[DOWNLOADING] a v0.1.0 (registry [..])
-"));
-}
-
-#[test]
-fn update_transitive_dependency() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.5.0"
- authors = []
-
- [dependencies]
- a = "0.1.0"
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- Package::new("a", "0.1.0").dep("b", "*").publish();
- Package::new("b", "0.1.0").publish();
-
- assert_that(p.cargo("fetch"),
- execs().with_status(0));
-
- Package::new("b", "0.1.1").publish();
-
- assert_that(p.cargo("update").arg("-pb"),
- execs().with_status(0)
- .with_stderr("\
-[UPDATING] registry `[..]`
-[UPDATING] b v0.1.0 -> v0.1.1
-"));
-
- assert_that(p.cargo("build"),
- execs().with_status(0)
- .with_stderr("\
-[DOWNLOADING] b v0.1.1 (registry `file://[..]`)
-[COMPILING] b v0.1.1
-[COMPILING] a v0.1.0
-[COMPILING] foo v0.5.0 ([..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] secs
-"));
-}
-
-#[test]
-fn update_backtracking_ok() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.5.0"
- authors = []
-
- [dependencies]
- webdriver = "0.1"
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- Package::new("webdriver", "0.1.0").dep("hyper", "0.6").publish();
- Package::new("hyper", "0.6.5").dep("openssl", "0.1")
- .dep("cookie", "0.1")
- .publish();
- Package::new("cookie", "0.1.0").dep("openssl", "0.1").publish();
- Package::new("openssl", "0.1.0").publish();
-
- assert_that(p.cargo("generate-lockfile"),
- execs().with_status(0));
-
- Package::new("openssl", "0.1.1").publish();
- Package::new("hyper", "0.6.6").dep("openssl", "0.1.1")
- .dep("cookie", "0.1.0")
- .publish();
-
- assert_that(p.cargo("update").arg("-p").arg("hyper"),
- execs().with_status(0)
- .with_stderr("\
-[UPDATING] registry `[..]`
-"));
-}
-
-#[test]
-fn update_multiple_packages() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.5.0"
- authors = []
-
- [dependencies]
- a = "*"
- b = "*"
- c = "*"
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- Package::new("a", "0.1.0").publish();
- Package::new("b", "0.1.0").publish();
- Package::new("c", "0.1.0").publish();
-
- assert_that(p.cargo("fetch"),
- execs().with_status(0));
-
- Package::new("a", "0.1.1").publish();
- Package::new("b", "0.1.1").publish();
- Package::new("c", "0.1.1").publish();
-
- assert_that(p.cargo("update").arg("-pa").arg("-pb"),
- execs().with_status(0)
- .with_stderr("\
-[UPDATING] registry `[..]`
-[UPDATING] a v0.1.0 -> v0.1.1
-[UPDATING] b v0.1.0 -> v0.1.1
-"));
-
- assert_that(p.cargo("update").arg("-pb").arg("-pc"),
- execs().with_status(0)
- .with_stderr("\
-[UPDATING] registry `[..]`
-[UPDATING] c v0.1.0 -> v0.1.1
-"));
-
- assert_that(p.cargo("build"),
- execs().with_status(0)
- .with_stderr_contains("\
-[DOWNLOADING] a v0.1.1 (registry `file://[..]`)")
- .with_stderr_contains("\
-[DOWNLOADING] b v0.1.1 (registry `file://[..]`)")
- .with_stderr_contains("\
-[DOWNLOADING] c v0.1.1 (registry `file://[..]`)")
- .with_stderr_contains("\
-[COMPILING] a v0.1.1")
- .with_stderr_contains("\
-[COMPILING] b v0.1.1")
- .with_stderr_contains("\
-[COMPILING] c v0.1.1")
- .with_stderr_contains("\
-[COMPILING] foo v0.5.0 ([..])"));
-}
-
-#[test]
-fn bundled_crate_in_registry() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.5.0"
- authors = []
-
- [dependencies]
- bar = "0.1"
- baz = "0.1"
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- Package::new("bar", "0.1.0").publish();
- Package::new("baz", "0.1.0")
- .dep("bar", "0.1.0")
- .file("Cargo.toml", r#"
- [package]
- name = "baz"
- version = "0.1.0"
- authors = []
-
- [dependencies]
- bar = { path = "bar", version = "0.1.0" }
- "#)
- .file("src/lib.rs", "")
- .file("bar/Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.1.0"
- authors = []
- "#)
- .file("bar/src/lib.rs", "")
- .publish();
-
- assert_that(p.cargo("run"), execs().with_status(0));
-}
-
-#[test]
-fn update_same_prefix_oh_my_how_was_this_a_bug() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "ugh"
- version = "0.5.0"
- authors = []
-
- [dependencies]
- foo = "0.1"
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- Package::new("foobar", "0.2.0").publish();
- Package::new("foo", "0.1.0")
- .dep("foobar", "0.2.0")
- .publish();
-
- assert_that(p.cargo("generate-lockfile"), execs().with_status(0));
- assert_that(p.cargo("update").arg("-pfoobar").arg("--precise=0.2.0"),
- execs().with_status(0));
-}
-
-#[test]
-fn use_semver() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.5.0"
- authors = []
-
- [dependencies]
- foo = "1.2.3-alpha.0"
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- Package::new("foo", "1.2.3-alpha.0").publish();
-
- assert_that(p.cargo("build"), execs().with_status(0));
-}
-
-#[test]
-fn only_download_relevant() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.5.0"
- authors = []
-
- [target.foo.dependencies]
- foo = "*"
- [dev-dependencies]
- bar = "*"
- [dependencies]
- baz = "*"
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- Package::new("foo", "0.1.0").publish();
- Package::new("bar", "0.1.0").publish();
- Package::new("baz", "0.1.0").publish();
-
- assert_that(p.cargo("build"),
- execs().with_status(0).with_stderr("\
-[UPDATING] registry `[..]`
-[DOWNLOADING] baz v0.1.0 ([..])
-[COMPILING] baz v0.1.0
-[COMPILING] bar v0.5.0 ([..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] secs
-"));
-}
-
-#[test]
-fn resolve_and_backtracking() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.5.0"
- authors = []
-
- [dependencies]
- foo = "*"
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- Package::new("foo", "0.1.1")
- .feature_dep("bar", "0.1", &["a", "b"])
- .publish();
- Package::new("foo", "0.1.0").publish();
-
- assert_that(p.cargo("build"),
- execs().with_status(0));
-}
-
-#[test]
-fn upstream_warnings_on_extra_verbose() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.5.0"
- authors = []
-
- [dependencies]
- foo = "*"
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- Package::new("foo", "0.1.0")
- .file("src/lib.rs", "fn unused() {}")
- .publish();
-
- assert_that(p.cargo("build").arg("-vv"),
- execs().with_status(0).with_stderr_contains("\
-[..]warning: function is never used[..]
-"));
-}
-
-#[test]
-fn disallow_network() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.5.0"
- authors = []
-
- [dependencies]
- foo = "*"
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("build").arg("--frozen"),
- execs().with_status(101).with_stderr("\
-error: failed to load source for a dependency on `foo`
-
-Caused by:
- Unable to update registry [..]
-
-Caused by:
- attempting to make an HTTP request, but --frozen was specified
-"));
-}
-
-#[test]
-fn add_dep_dont_update_registry() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.5.0"
- authors = []
-
- [dependencies]
- baz = { path = "baz" }
- "#)
- .file("src/main.rs", "fn main() {}")
- .file("baz/Cargo.toml", r#"
- [project]
- name = "baz"
- version = "0.5.0"
- authors = []
-
- [dependencies]
- remote = "0.3"
- "#)
- .file("baz/src/lib.rs", "")
- .build();
-
- Package::new("remote", "0.3.4").publish();
-
- assert_that(p.cargo("build"), execs().with_status(0));
-
- t!(t!(File::create(p.root().join("Cargo.toml"))).write_all(br#"
- [project]
- name = "bar"
- version = "0.5.0"
- authors = []
-
- [dependencies]
- baz = { path = "baz" }
- remote = "0.3"
- "#));
-
- assert_that(p.cargo("build"),
- execs().with_status(0)
- .with_stderr("\
-[COMPILING] bar v0.5.0 ([..])
-[FINISHED] [..]
-"));
-}
-
-#[test]
-fn bump_version_dont_update_registry() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.5.0"
- authors = []
-
- [dependencies]
- baz = { path = "baz" }
- "#)
- .file("src/main.rs", "fn main() {}")
- .file("baz/Cargo.toml", r#"
- [project]
- name = "baz"
- version = "0.5.0"
- authors = []
-
- [dependencies]
- remote = "0.3"
- "#)
- .file("baz/src/lib.rs", "")
- .build();
-
- Package::new("remote", "0.3.4").publish();
-
- assert_that(p.cargo("build"), execs().with_status(0));
-
- t!(t!(File::create(p.root().join("Cargo.toml"))).write_all(br#"
- [project]
- name = "bar"
- version = "0.6.0"
- authors = []
-
- [dependencies]
- baz = { path = "baz" }
- "#));
-
- assert_that(p.cargo("build"),
- execs().with_status(0)
- .with_stderr("\
-[COMPILING] bar v0.6.0 ([..])
-[FINISHED] [..]
-"));
-}
-
-#[test]
-fn old_version_req() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.5.0"
- authors = []
-
- [dependencies]
- remote = "0.2*"
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- Package::new("remote", "0.2.0").publish();
-
- assert_that(p.cargo("build"),
- execs().with_status(0)
- .with_stderr("\
-warning: parsed version requirement `0.2*` is no longer valid
-
-Previous versions of Cargo accepted this malformed requirement,
-but it is being deprecated. This was found when parsing the manifest
-of bar 0.5.0, and the correct version requirement is `0.2.*`.
-
-This will soon become a hard error, so it's either recommended to
-update to a fixed version or contact the upstream maintainer about
-this warning.
-
-warning: parsed version requirement `0.2*` is no longer valid
-
-Previous versions of Cargo accepted this malformed requirement,
-but it is being deprecated. This was found when parsing the manifest
-of bar 0.5.0, and the correct version requirement is `0.2.*`.
-
-This will soon become a hard error, so it's either recommended to
-update to a fixed version or contact the upstream maintainer about
-this warning.
-
-[UPDATING] [..]
-[DOWNLOADING] [..]
-[COMPILING] [..]
-[COMPILING] [..]
-[FINISHED] [..]
-"));
-}
-
-#[test]
-fn old_version_req_upstream() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.5.0"
- authors = []
-
- [dependencies]
- remote = "0.3"
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- Package::new("remote", "0.3.0")
- .file("Cargo.toml", r#"
- [project]
- name = "remote"
- version = "0.3.0"
- authors = []
-
- [dependencies]
- bar = "0.2*"
- "#)
- .file("src/lib.rs", "")
- .publish();
- Package::new("bar", "0.2.0").publish();
-
- assert_that(p.cargo("build"),
- execs().with_status(0)
- .with_stderr("\
-[UPDATING] [..]
-[DOWNLOADING] [..]
-warning: parsed version requirement `0.2*` is no longer valid
-
-Previous versions of Cargo accepted this malformed requirement,
-but it is being deprecated. This was found when parsing the manifest
-of remote 0.3.0, and the correct version requirement is `0.2.*`.
-
-This will soon become a hard error, so it's either recommended to
-update to a fixed version or contact the upstream maintainer about
-this warning.
-
-[COMPILING] [..]
-[COMPILING] [..]
-[FINISHED] [..]
-"));
-}
-
-#[test]
-fn toml_lies_but_index_is_truth() {
- Package::new("foo", "0.2.0").publish();
- Package::new("bar", "0.3.0")
- .dep("foo", "0.2.0")
- .file("Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.3.0"
- authors = []
-
- [dependencies]
- foo = "0.1.0"
- "#)
- .file("src/lib.rs", "extern crate foo;")
- .publish();
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.5.0"
- authors = []
-
- [dependencies]
- bar = "0.3"
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(0));
-}
-
-#[test]
-fn vv_prints_warnings() {
- Package::new("foo", "0.2.0")
- .file("src/lib.rs", r#"
- #![deny(warnings)]
-
- fn foo() {} // unused function
- "#)
- .publish();
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "fo"
- version = "0.5.0"
- authors = []
-
- [dependencies]
- foo = "0.2"
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("build").arg("-vv"),
- execs().with_status(0));
-}
-
-#[test]
-fn bad_and_or_malicious_packages_rejected() {
- Package::new("foo", "0.2.0")
- .extra_file("foo-0.1.0/src/lib.rs", "")
- .publish();
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "fo"
- version = "0.5.0"
- authors = []
-
- [dependencies]
- foo = "0.2"
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("build").arg("-vv"),
- execs().with_status(101)
- .with_stderr("\
-[UPDATING] [..]
-[DOWNLOADING] [..]
-error: unable to get packages from source
-
-Caused by:
- failed to download [..]
-
-Caused by:
- failed to unpack [..]
-
-Caused by:
- [..] contains a file at \"foo-0.1.0/src/lib.rs\" which isn't under \"foo-0.2.0\"
-"));
-}
+++ /dev/null
-extern crate cargotest;
-extern crate hamcrest;
-
-use cargotest::is_nightly;
-use cargotest::install::{cargo_home, has_installed_exe};
-use cargotest::support::{project, execs};
-use hamcrest::{assert_that, existing_file, not};
-
-#[test]
-fn build_bin_default_features() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [features]
- default = ["a"]
- a = []
-
- [[bin]]
- name = "foo"
- required-features = ["a"]
- "#)
- .file("src/main.rs", r#"
- extern crate foo;
-
- #[cfg(feature = "a")]
- fn test() {
- foo::foo();
- }
-
- fn main() {}
- "#)
- .file("src/lib.rs", r#"
- #[cfg(feature = "a")]
- pub fn foo() {}
- "#)
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0));
- assert_that(&p.bin("foo"), existing_file());
-
- assert_that(p.cargo("build").arg("--no-default-features"),
- execs().with_status(0));
-
- assert_that(p.cargo("build").arg("--bin=foo"),
- execs().with_status(0));
- assert_that(&p.bin("foo"), existing_file());
-
- assert_that(p.cargo("build").arg("--bin=foo").arg("--no-default-features"),
- execs().with_status(101).with_stderr("\
-error: target `foo` requires the features: `a`
-Consider enabling them by passing e.g. `--features=\"a\"`
-"));
-}
-
-#[test]
-fn build_bin_arg_features() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [features]
- a = []
-
- [[bin]]
- name = "foo"
- required-features = ["a"]
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("build").arg("--features").arg("a"),
- execs().with_status(0));
- assert_that(&p.bin("foo"), existing_file());
-}
-
-#[test]
-fn build_bin_multiple_required_features() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [features]
- default = ["a", "b"]
- a = []
- b = ["a"]
- c = []
-
- [[bin]]
- name = "foo_1"
- path = "src/foo_1.rs"
- required-features = ["b", "c"]
-
- [[bin]]
- name = "foo_2"
- path = "src/foo_2.rs"
- required-features = ["a"]
- "#)
- .file("src/foo_1.rs", "fn main() {}")
- .file("src/foo_2.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0));
-
- assert_that(&p.bin("foo_1"), not(existing_file()));
- assert_that(&p.bin("foo_2"), existing_file());
-
- assert_that(p.cargo("build").arg("--features").arg("c"),
- execs().with_status(0));
-
- assert_that(&p.bin("foo_1"), existing_file());
- assert_that(&p.bin("foo_2"), existing_file());
-
- assert_that(p.cargo("build").arg("--no-default-features"),
- execs().with_status(0));
-}
-
-#[test]
-fn build_example_default_features() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [features]
- default = ["a"]
- a = []
-
- [[example]]
- name = "foo"
- required-features = ["a"]
- "#)
- .file("examples/foo.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("build").arg("--example=foo"),
- execs().with_status(0));
- assert_that(&p.bin("examples/foo"), existing_file());
-
- assert_that(p.cargo("build").arg("--example=foo").arg("--no-default-features"),
- execs().with_status(101).with_stderr("\
-error: target `foo` requires the features: `a`
-Consider enabling them by passing e.g. `--features=\"a\"`
-"));
-}
-
-#[test]
-fn build_example_arg_features() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [features]
- a = []
-
- [[example]]
- name = "foo"
- required-features = ["a"]
- "#)
- .file("examples/foo.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("build").arg("--example=foo").arg("--features").arg("a"),
- execs().with_status(0));
- assert_that(&p.bin("examples/foo"), existing_file());
-}
-
-#[test]
-fn build_example_multiple_required_features() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [features]
- default = ["a", "b"]
- a = []
- b = ["a"]
- c = []
-
- [[example]]
- name = "foo_1"
- required-features = ["b", "c"]
-
- [[example]]
- name = "foo_2"
- required-features = ["a"]
- "#)
- .file("examples/foo_1.rs", "fn main() {}")
- .file("examples/foo_2.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("build").arg("--example=foo_1"),
- execs().with_status(101).with_stderr("\
-error: target `foo_1` requires the features: `b`, `c`
-Consider enabling them by passing e.g. `--features=\"b c\"`
-"));
- assert_that(p.cargo("build").arg("--example=foo_2"),
- execs().with_status(0));
-
- assert_that(&p.bin("examples/foo_1"), not(existing_file()));
- assert_that(&p.bin("examples/foo_2"), existing_file());
-
- assert_that(p.cargo("build").arg("--example=foo_1")
- .arg("--features").arg("c"),
- execs().with_status(0));
- assert_that(p.cargo("build").arg("--example=foo_2")
- .arg("--features").arg("c"),
- execs().with_status(0));
-
- assert_that(&p.bin("examples/foo_1"), existing_file());
- assert_that(&p.bin("examples/foo_2"), existing_file());
-
- assert_that(p.cargo("build").arg("--example=foo_1")
- .arg("--no-default-features"),
- execs().with_status(101).with_stderr("\
-error: target `foo_1` requires the features: `b`, `c`
-Consider enabling them by passing e.g. `--features=\"b c\"`
-"));
- assert_that(p.cargo("build").arg("--example=foo_2")
- .arg("--no-default-features"),
- execs().with_status(101).with_stderr("\
-error: target `foo_2` requires the features: `a`
-Consider enabling them by passing e.g. `--features=\"a\"`
-"));
-}
-
-#[test]
-fn test_default_features() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [features]
- default = ["a"]
- a = []
-
- [[test]]
- name = "foo"
- required-features = ["a"]
- "#)
- .file("tests/foo.rs", "#[test]\nfn test() {}")
- .build();
-
- assert_that(p.cargo("test"),
- execs().with_status(0).with_stderr(format!("\
-[COMPILING] foo v0.0.1 ({})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] target[/]debug[/]deps[/]foo-[..][EXE]", p.url()))
- .with_stdout_contains("test test ... ok"));
-
- assert_that(p.cargo("test").arg("--no-default-features"),
- execs().with_status(0).with_stderr(format!("\
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]"))
- .with_stdout(""));
-
- assert_that(p.cargo("test").arg("--test=foo"),
- execs().with_status(0).with_stderr(format!("\
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] target[/]debug[/]deps[/]foo-[..][EXE]"))
- .with_stdout_contains("test test ... ok"));
-
- assert_that(p.cargo("test").arg("--test=foo").arg("--no-default-features"),
- execs().with_status(101).with_stderr("\
-error: target `foo` requires the features: `a`
-Consider enabling them by passing e.g. `--features=\"a\"`
-"));
-}
-
-#[test]
-fn test_arg_features() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [features]
- a = []
-
- [[test]]
- name = "foo"
- required-features = ["a"]
- "#)
- .file("tests/foo.rs", "#[test]\nfn test() {}")
- .build();
-
- assert_that(p.cargo("test").arg("--features").arg("a"),
- execs().with_status(0).with_stderr(format!("\
-[COMPILING] foo v0.0.1 ({})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] target[/]debug[/]deps[/]foo-[..][EXE]", p.url()))
- .with_stdout_contains("test test ... ok"));
-}
-
-#[test]
-fn test_multiple_required_features() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [features]
- default = ["a", "b"]
- a = []
- b = ["a"]
- c = []
-
- [[test]]
- name = "foo_1"
- required-features = ["b", "c"]
-
- [[test]]
- name = "foo_2"
- required-features = ["a"]
- "#)
- .file("tests/foo_1.rs", "#[test]\nfn test() {}")
- .file("tests/foo_2.rs", "#[test]\nfn test() {}")
- .build();
-
- assert_that(p.cargo("test"),
- execs().with_status(0).with_stderr(format!("\
-[COMPILING] foo v0.0.1 ({})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] target[/]debug[/]deps[/]foo_2-[..][EXE]", p.url()))
- .with_stdout_contains("test test ... ok"));
-
- assert_that(p.cargo("test").arg("--features").arg("c"),
- execs().with_status(0).with_stderr(format!("\
-[COMPILING] foo v0.0.1 ({})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] target[/]debug[/]deps[/]foo_1-[..][EXE]
-[RUNNING] target[/]debug[/]deps[/]foo_2-[..][EXE]", p.url()))
- .with_stdout_contains_n("test test ... ok", 2));
-
- assert_that(p.cargo("test").arg("--no-default-features"),
- execs().with_status(0).with_stderr(format!("\
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]"))
- .with_stdout(""));
-}
-
-#[test]
-fn bench_default_features() {
- if !is_nightly() {
- return;
- }
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [features]
- default = ["a"]
- a = []
-
- [[bench]]
- name = "foo"
- required-features = ["a"]
- "#)
- .file("benches/foo.rs", r#"
- #![feature(test)]
- extern crate test;
-
- #[bench]
- fn bench(_: &mut test::Bencher) {
- }"#)
- .build();
-
- assert_that(p.cargo("bench"),
- execs().with_status(0).with_stderr(format!("\
-[COMPILING] foo v0.0.1 ({})
-[FINISHED] release [optimized] target(s) in [..]
-[RUNNING] target[/]release[/]deps[/]foo-[..][EXE]", p.url()))
- .with_stdout_contains("test bench ... bench: [..]"));
-
- assert_that(p.cargo("bench").arg("--no-default-features"),
- execs().with_status(0).with_stderr(format!("\
-[FINISHED] release [optimized] target(s) in [..]"))
- .with_stdout(""));
-
- assert_that(p.cargo("bench").arg("--bench=foo"),
- execs().with_status(0).with_stderr(format!("\
-[FINISHED] release [optimized] target(s) in [..]
-[RUNNING] target[/]release[/]deps[/]foo-[..][EXE]"))
- .with_stdout_contains("test bench ... bench: [..]"));
-
- assert_that(p.cargo("bench").arg("--bench=foo").arg("--no-default-features"),
- execs().with_status(101).with_stderr("\
-error: target `foo` requires the features: `a`
-Consider enabling them by passing e.g. `--features=\"a\"`
-"));
-}
-
-#[test]
-fn bench_arg_features() {
- if !is_nightly() {
- return;
- }
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [features]
- a = []
-
- [[bench]]
- name = "foo"
- required-features = ["a"]
- "#)
- .file("benches/foo.rs", r#"
- #![feature(test)]
- extern crate test;
-
- #[bench]
- fn bench(_: &mut test::Bencher) {
- }"#)
- .build();
-
- assert_that(p.cargo("bench").arg("--features").arg("a"),
- execs().with_status(0).with_stderr(format!("\
-[COMPILING] foo v0.0.1 ({})
-[FINISHED] release [optimized] target(s) in [..]
-[RUNNING] target[/]release[/]deps[/]foo-[..][EXE]", p.url()))
- .with_stdout_contains("test bench ... bench: [..]"));
-}
-
-#[test]
-fn bench_multiple_required_features() {
- if !is_nightly() {
- return;
- }
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [features]
- default = ["a", "b"]
- a = []
- b = ["a"]
- c = []
-
- [[bench]]
- name = "foo_1"
- required-features = ["b", "c"]
-
- [[bench]]
- name = "foo_2"
- required-features = ["a"]
- "#)
- .file("benches/foo_1.rs", r#"
- #![feature(test)]
- extern crate test;
-
- #[bench]
- fn bench(_: &mut test::Bencher) {
- }"#)
- .file("benches/foo_2.rs", r#"
- #![feature(test)]
- extern crate test;
-
- #[bench]
- fn bench(_: &mut test::Bencher) {
- }"#)
- .build();
-
- assert_that(p.cargo("bench"),
- execs().with_status(0).with_stderr(format!("\
-[COMPILING] foo v0.0.1 ({})
-[FINISHED] release [optimized] target(s) in [..]
-[RUNNING] target[/]release[/]deps[/]foo_2-[..][EXE]", p.url()))
- .with_stdout_contains("test bench ... bench: [..]"));
-
- assert_that(p.cargo("bench").arg("--features").arg("c"),
- execs().with_status(0).with_stderr(format!("\
-[COMPILING] foo v0.0.1 ({})
-[FINISHED] release [optimized] target(s) in [..]
-[RUNNING] target[/]release[/]deps[/]foo_1-[..][EXE]
-[RUNNING] target[/]release[/]deps[/]foo_2-[..][EXE]", p.url()))
- .with_stdout_contains_n("test bench ... bench: [..]", 2));
-
- assert_that(p.cargo("bench").arg("--no-default-features"),
- execs().with_status(0).with_stderr(format!("\
-[FINISHED] release [optimized] target(s) in [..]"))
- .with_stdout(""));
-}
-
-#[test]
-fn install_default_features() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [features]
- default = ["a"]
- a = []
-
- [[bin]]
- name = "foo"
- required-features = ["a"]
-
- [[example]]
- name = "foo"
- required-features = ["a"]
- "#)
- .file("src/main.rs", "fn main() {}")
- .file("examples/foo.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("install"),
- execs().with_status(0));
- assert_that(cargo_home(), has_installed_exe("foo"));
- assert_that(p.cargo("uninstall").arg("foo"),
- execs().with_status(0));
-
- assert_that(p.cargo("install").arg("--no-default-features"),
- execs().with_status(101).with_stderr(format!("\
-[INSTALLING] foo v0.0.1 ([..])
-[FINISHED] release [optimized] target(s) in [..]
-[ERROR] no binaries are available for install using the selected features
-")));
- assert_that(cargo_home(), not(has_installed_exe("foo")));
-
- assert_that(p.cargo("install").arg("--bin=foo"),
- execs().with_status(0));
- assert_that(cargo_home(), has_installed_exe("foo"));
- assert_that(p.cargo("uninstall").arg("foo"),
- execs().with_status(0));
-
- assert_that(p.cargo("install").arg("--bin=foo").arg("--no-default-features"),
- execs().with_status(101).with_stderr(format!("\
-[INSTALLING] foo v0.0.1 ([..])
-[ERROR] failed to compile `foo v0.0.1 ([..])`, intermediate artifacts can be found at \
- `[..]target`
-
-Caused by:
- target `foo` requires the features: `a`
-Consider enabling them by passing e.g. `--features=\"a\"`
-")));
- assert_that(cargo_home(), not(has_installed_exe("foo")));
-
- assert_that(p.cargo("install").arg("--example=foo"),
- execs().with_status(0));
- assert_that(cargo_home(), has_installed_exe("foo"));
- assert_that(p.cargo("uninstall").arg("foo"),
- execs().with_status(0));
-
- assert_that(p.cargo("install").arg("--example=foo").arg("--no-default-features"),
- execs().with_status(101).with_stderr(format!("\
-[INSTALLING] foo v0.0.1 ([..])
-[ERROR] failed to compile `foo v0.0.1 ([..])`, intermediate artifacts can be found at \
- `[..]target`
-
-Caused by:
- target `foo` requires the features: `a`
-Consider enabling them by passing e.g. `--features=\"a\"`
-")));
- assert_that(cargo_home(), not(has_installed_exe("foo")));
-}
-
-#[test]
-fn install_arg_features() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [features]
- a = []
-
- [[bin]]
- name = "foo"
- required-features = ["a"]
- "#)
- .file("src/main.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("install").arg("--features").arg("a"),
- execs().with_status(0));
- assert_that(cargo_home(), has_installed_exe("foo"));
- assert_that(p.cargo("uninstall").arg("foo"),
- execs().with_status(0));
-}
-
-#[test]
-fn install_multiple_required_features() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [features]
- default = ["a", "b"]
- a = []
- b = ["a"]
- c = []
-
- [[bin]]
- name = "foo_1"
- path = "src/foo_1.rs"
- required-features = ["b", "c"]
-
- [[bin]]
- name = "foo_2"
- path = "src/foo_2.rs"
- required-features = ["a"]
- "#)
- .file("src/foo_1.rs", "fn main() {}")
- .file("src/foo_2.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("install"),
- execs().with_status(0));
- assert_that(cargo_home(), not(has_installed_exe("foo_1")));
- assert_that(cargo_home(), has_installed_exe("foo_2"));
- assert_that(p.cargo("uninstall").arg("foo"),
- execs().with_status(0));
-
- assert_that(p.cargo("install").arg("--features").arg("c"),
- execs().with_status(0));
- assert_that(cargo_home(), has_installed_exe("foo_1"));
- assert_that(cargo_home(), has_installed_exe("foo_2"));
- assert_that(p.cargo("uninstall").arg("foo"),
- execs().with_status(0));
-
- assert_that(p.cargo("install").arg("--no-default-features"),
- execs().with_status(101).with_stderr("\
-[INSTALLING] foo v0.0.1 ([..])
-[FINISHED] release [optimized] target(s) in [..]
-[ERROR] no binaries are available for install using the selected features
-"));
- assert_that(cargo_home(), not(has_installed_exe("foo_1")));
- assert_that(cargo_home(), not(has_installed_exe("foo_2")));
-}
-
-#[test]
-fn dep_feature_in_toml() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- bar = { path = "bar", features = ["a"] }
-
- [[bin]]
- name = "foo"
- required-features = ["bar/a"]
-
- [[example]]
- name = "foo"
- required-features = ["bar/a"]
-
- [[test]]
- name = "foo"
- required-features = ["bar/a"]
-
- [[bench]]
- name = "foo"
- required-features = ["bar/a"]
- "#)
- .file("src/main.rs", "fn main() {}")
- .file("examples/foo.rs", "fn main() {}")
- .file("tests/foo.rs", "#[test]\nfn test() {}")
- .file("benches/foo.rs", r#"
- #![feature(test)]
- extern crate test;
-
- #[bench]
- fn bench(_: &mut test::Bencher) {
- }"#)
- .file("bar/Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.0.1"
- authors = []
-
- [features]
- a = []
- "#)
- .file("bar/src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0));
-
- // bin
- assert_that(p.cargo("build").arg("--bin=foo"),
- execs().with_status(0));
- assert_that(&p.bin("foo"), existing_file());
-
- // example
- assert_that(p.cargo("build").arg("--example=foo"),
- execs().with_status(0));
- assert_that(&p.bin("examples/foo"), existing_file());
-
- // test
- assert_that(p.cargo("test").arg("--test=foo"),
- execs().with_status(0).with_stderr(format!("\
-[COMPILING] foo v0.0.1 ({})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] target[/]debug[/]deps[/]foo-[..][EXE]", p.url()))
- .with_stdout_contains("test test ... ok"));
-
- // bench
- if is_nightly() {
- assert_that(p.cargo("bench").arg("--bench=foo"),
- execs().with_status(0).with_stderr(format!("\
-[COMPILING] bar v0.0.1 ({0}/bar)
-[COMPILING] foo v0.0.1 ({0})
-[FINISHED] release [optimized] target(s) in [..]
-[RUNNING] target[/]release[/]deps[/]foo-[..][EXE]", p.url()))
- .with_stdout_contains("test bench ... bench: [..]"));
- }
-
- // install
- assert_that(p.cargo("install"),
- execs().with_status(0));
- assert_that(cargo_home(), has_installed_exe("foo"));
- assert_that(p.cargo("uninstall").arg("foo"),
- execs().with_status(0));
-}
-
-#[test]
-fn dep_feature_in_cmd_line() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- bar = { path = "bar" }
-
- [[bin]]
- name = "foo"
- required-features = ["bar/a"]
-
- [[example]]
- name = "foo"
- required-features = ["bar/a"]
-
- [[test]]
- name = "foo"
- required-features = ["bar/a"]
-
- [[bench]]
- name = "foo"
- required-features = ["bar/a"]
- "#)
- .file("src/main.rs", "fn main() {}")
- .file("examples/foo.rs", "fn main() {}")
- .file("tests/foo.rs", "#[test]\nfn test() {}")
- .file("benches/foo.rs", r#"
- #![feature(test)]
- extern crate test;
-
- #[bench]
- fn bench(_: &mut test::Bencher) {
- }"#)
- .file("bar/Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.0.1"
- authors = []
-
- [features]
- a = []
- "#)
- .file("bar/src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0));
-
- // bin
- assert_that(p.cargo("build").arg("--bin=foo"),
- execs().with_status(101).with_stderr("\
-error: target `foo` requires the features: `bar/a`
-Consider enabling them by passing e.g. `--features=\"bar/a\"`
-"));
-
- assert_that(p.cargo("build").arg("--bin=foo").arg("--features").arg("bar/a"),
- execs().with_status(0));
- assert_that(&p.bin("foo"), existing_file());
-
- // example
- assert_that(p.cargo("build").arg("--example=foo"),
- execs().with_status(101).with_stderr("\
-error: target `foo` requires the features: `bar/a`
-Consider enabling them by passing e.g. `--features=\"bar/a\"`
-"));
-
- assert_that(p.cargo("build").arg("--example=foo").arg("--features").arg("bar/a"),
- execs().with_status(0));
- assert_that(&p.bin("examples/foo"), existing_file());
-
- // test
- assert_that(p.cargo("test"),
- execs().with_status(0).with_stderr(format!("\
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]"))
- .with_stdout(""));
-
- assert_that(p.cargo("test").arg("--test=foo").arg("--features").arg("bar/a"),
- execs().with_status(0).with_stderr(format!("\
-[COMPILING] foo v0.0.1 ({})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] target[/]debug[/]deps[/]foo-[..][EXE]", p.url()))
- .with_stdout_contains("test test ... ok"));
-
- // bench
- if is_nightly() {
- assert_that(p.cargo("bench"),
- execs().with_status(0).with_stderr(format!("\
-[FINISHED] release [optimized] target(s) in [..]"))
- .with_stdout(""));
-
- assert_that(p.cargo("bench").arg("--bench=foo").arg("--features").arg("bar/a"),
- execs().with_status(0).with_stderr(format!("\
-[COMPILING] bar v0.0.1 ({0}/bar)
-[COMPILING] foo v0.0.1 ({0})
-[FINISHED] release [optimized] target(s) in [..]
-[RUNNING] target[/]release[/]deps[/]foo-[..][EXE]", p.url()))
- .with_stdout_contains("test bench ... bench: [..]"));
- }
-
- // install
- assert_that(p.cargo("install"),
- execs().with_status(101).with_stderr(format!("\
-[INSTALLING] foo v0.0.1 ([..])
-[FINISHED] release [optimized] target(s) in [..]
-[ERROR] no binaries are available for install using the selected features
-")));
- assert_that(cargo_home(), not(has_installed_exe("foo")));
-
- assert_that(p.cargo("install").arg("--features").arg("bar/a"),
- execs().with_status(0));
- assert_that(cargo_home(), has_installed_exe("foo"));
- assert_that(p.cargo("uninstall").arg("foo"),
- execs().with_status(0));
-}
-
-#[test]
-fn test_skips_compiling_bin_with_missing_required_features() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [features]
- a = []
-
- [[bin]]
- name = "bin_foo"
- path = "src/bin/foo.rs"
- required-features = ["a"]
- "#)
- .file("src/bin/foo.rs", "extern crate bar; fn main() {}")
- .file("tests/foo.rs", "")
- .file("benches/foo.rs", "")
- .build();
-
- assert_that(p.cargo("test"),
- execs().with_status(0).with_stderr(format!("\
-[COMPILING] foo v0.0.1 ({})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] target[/]debug[/]deps[/]foo-[..][EXE]", p.url()))
- .with_stdout_contains("running 0 tests"));
-
- assert_that(p.cargo("test").arg("--features").arg("a").arg("-j").arg("1"),
- execs().with_status(101).with_stderr_contains(format!("\
-[COMPILING] foo v0.0.1 ({})
-error[E0463]: can't find crate for `bar`", p.url())));
-
- if is_nightly() {
- assert_that(p.cargo("bench"),
- execs().with_status(0).with_stderr(format!("\
-[COMPILING] foo v0.0.1 ({})
-[FINISHED] release [optimized] target(s) in [..]
-[RUNNING] target[/]release[/]deps[/]foo-[..][EXE]", p.url()))
- .with_stdout_contains("running 0 tests"));
-
- assert_that(p.cargo("bench").arg("--features").arg("a").arg("-j").arg("1"),
- execs().with_status(101).with_stderr_contains(format!("\
-[COMPILING] foo v0.0.1 ({})
-error[E0463]: can't find crate for `bar`", p.url())));
- }
-}
-
-#[test]
-fn run_default() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [features]
- default = []
- a = []
-
- [[bin]]
- name = "foo"
- required-features = ["a"]
- "#)
- .file("src/lib.rs", "")
- .file("src/main.rs", "extern crate foo; fn main() {}")
- .build();
-
- assert_that(p.cargo("run"),
- execs().with_status(101).with_stderr("\
-error: target `foo` requires the features: `a`
-Consider enabling them by passing e.g. `--features=\"a\"`
-"));
-
- assert_that(p.cargo("run").arg("--features").arg("a"),
- execs().with_status(0));
-}
-
-#[test]
-fn run_default_multiple_required_features() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [features]
- default = ["a"]
- a = []
- b = []
-
- [[bin]]
- name = "foo1"
- path = "src/foo1.rs"
- required-features = ["a"]
-
- [[bin]]
- name = "foo2"
- path = "src/foo2.rs"
- required-features = ["b"]
- "#)
- .file("src/lib.rs", "")
- .file("src/foo1.rs", "extern crate foo; fn main() {}")
- .file("src/foo2.rs", "extern crate foo; fn main() {}")
- .build();
-
- assert_that(p.cargo("run"),
- execs().with_status(101).with_stderr("\
-error: `cargo run` requires that a project only have one executable; \
-use the `--bin` option to specify which one to run\navailable binaries: foo1, foo2"));
-}
+++ /dev/null
-#![deny(warnings)]
-
-extern crate hamcrest;
-extern crate cargo;
-
-use std::collections::BTreeMap;
-
-use hamcrest::{assert_that, equal_to, contains, not};
-
-use cargo::core::source::{SourceId, GitReference};
-use cargo::core::dependency::Kind::{self, Development};
-use cargo::core::{Dependency, PackageId, Summary, Registry};
-use cargo::util::{CargoResult, ToUrl};
-use cargo::core::resolver::{self, Method};
-
-fn resolve(pkg: &PackageId, deps: Vec<Dependency>, registry: &[Summary])
- -> CargoResult<Vec<PackageId>>
-{
- struct MyRegistry<'a>(&'a [Summary]);
- impl<'a> Registry for MyRegistry<'a> {
- fn query(&mut self,
- dep: &Dependency,
- f: &mut FnMut(Summary)) -> CargoResult<()> {
- for summary in self.0.iter() {
- if dep.matches(summary) {
- f(summary.clone());
- }
- }
- Ok(())
- }
- fn supports_checksums(&self) -> bool { false }
- fn requires_precise(&self) -> bool { false }
- }
- let mut registry = MyRegistry(registry);
- let summary = Summary::new(pkg.clone(), deps, BTreeMap::new()).unwrap();
- let method = Method::Everything;
- let resolve = resolver::resolve(&[(summary, method)], &[], &mut registry, None, false)?;
- let res = resolve.iter().cloned().collect();
- Ok(res)
-}
-
-trait ToDep {
- fn to_dep(self) -> Dependency;
-}
-
-impl ToDep for &'static str {
- fn to_dep(self) -> Dependency {
- let url = "http://example.com".to_url().unwrap();
- let source_id = SourceId::for_registry(&url).unwrap();
- Dependency::parse_no_deprecated(self, Some("1.0.0"), &source_id).unwrap()
- }
-}
-
-impl ToDep for Dependency {
- fn to_dep(self) -> Dependency {
- self
- }
-}
-
-trait ToPkgId {
- fn to_pkgid(&self) -> PackageId;
-}
-
-impl ToPkgId for &'static str {
- fn to_pkgid(&self) -> PackageId {
- PackageId::new(*self, "1.0.0", ®istry_loc()).unwrap()
- }
-}
-
-impl ToPkgId for (&'static str, &'static str) {
- fn to_pkgid(&self) -> PackageId {
- let (name, vers) = *self;
- PackageId::new(name, vers, ®istry_loc()).unwrap()
- }
-}
-
-impl ToPkgId for (&'static str, String) {
- fn to_pkgid(&self) -> PackageId {
- let (name, ref vers) = *self;
- PackageId::new(name, vers, ®istry_loc()).unwrap()
- }
-}
-
-macro_rules! pkg {
- ($pkgid:expr => [$($deps:expr),+]) => ({
- let d: Vec<Dependency> = vec![$($deps.to_dep()),+];
-
- Summary::new($pkgid.to_pkgid(), d, BTreeMap::new()).unwrap()
- });
-
- ($pkgid:expr) => (
- Summary::new($pkgid.to_pkgid(), Vec::new(), BTreeMap::new()).unwrap()
- )
-}
-
-fn registry_loc() -> SourceId {
- let remote = "http://example.com".to_url().unwrap();
- SourceId::for_registry(&remote).unwrap()
-}
-
-fn pkg(name: &str) -> Summary {
- Summary::new(pkg_id(name), Vec::new(), BTreeMap::new()).unwrap()
-}
-
-fn pkg_id(name: &str) -> PackageId {
- PackageId::new(name, "1.0.0", ®istry_loc()).unwrap()
-}
-
-fn pkg_id_loc(name: &str, loc: &str) -> PackageId {
- let remote = loc.to_url();
- let master = GitReference::Branch("master".to_string());
- let source_id = SourceId::for_git(&remote.unwrap(), master).unwrap();
-
- PackageId::new(name, "1.0.0", &source_id).unwrap()
-}
-
-fn pkg_loc(name: &str, loc: &str) -> Summary {
- Summary::new(pkg_id_loc(name, loc), Vec::new(), BTreeMap::new()).unwrap()
-}
-
-fn dep(name: &str) -> Dependency { dep_req(name, "1.0.0") }
-fn dep_req(name: &str, req: &str) -> Dependency {
- let url = "http://example.com".to_url().unwrap();
- let source_id = SourceId::for_registry(&url).unwrap();
- Dependency::parse_no_deprecated(name, Some(req), &source_id).unwrap()
-}
-
-fn dep_loc(name: &str, location: &str) -> Dependency {
- let url = location.to_url().unwrap();
- let master = GitReference::Branch("master".to_string());
- let source_id = SourceId::for_git(&url, master).unwrap();
- Dependency::parse_no_deprecated(name, Some("1.0.0"), &source_id).unwrap()
-}
-fn dep_kind(name: &str, kind: Kind) -> Dependency {
- dep(name).set_kind(kind).clone()
-}
-
-fn registry(pkgs: Vec<Summary>) -> Vec<Summary> {
- pkgs
-}
-
-fn names<P: ToPkgId>(names: &[P]) -> Vec<PackageId> {
- names.iter().map(|name| name.to_pkgid()).collect()
-}
-
-fn loc_names(names: &[(&'static str, &'static str)]) -> Vec<PackageId> {
- names.iter()
- .map(|&(name, loc)| pkg_id_loc(name, loc)).collect()
-}
-
-#[test]
-fn test_resolving_empty_dependency_list() {
- let res = resolve(&pkg_id("root"), Vec::new(),
- ®istry(vec![])).unwrap();
-
- assert_that(&res, equal_to(&names(&["root"])));
-}
-
-#[test]
-fn test_resolving_only_package() {
- let reg = registry(vec![pkg("foo")]);
- let res = resolve(&pkg_id("root"), vec![dep("foo")], ®);
-
- assert_that(&res.unwrap(), contains(names(&["root", "foo"])).exactly());
-}
-
-#[test]
-fn test_resolving_one_dep() {
- let reg = registry(vec![pkg("foo"), pkg("bar")]);
- let res = resolve(&pkg_id("root"), vec![dep("foo")], ®);
-
- assert_that(&res.unwrap(), contains(names(&["root", "foo"])).exactly());
-}
-
-#[test]
-fn test_resolving_multiple_deps() {
- let reg = registry(vec![pkg!("foo"), pkg!("bar"), pkg!("baz")]);
- let res = resolve(&pkg_id("root"), vec![dep("foo"), dep("baz")],
- ®).unwrap();
-
- assert_that(&res, contains(names(&["root", "foo", "baz"])).exactly());
-}
-
-#[test]
-fn test_resolving_transitive_deps() {
- let reg = registry(vec![pkg!("foo"), pkg!("bar" => ["foo"])]);
- let res = resolve(&pkg_id("root"), vec![dep("bar")], ®).unwrap();
-
- assert_that(&res, contains(names(&["root", "foo", "bar"])));
-}
-
-#[test]
-fn test_resolving_common_transitive_deps() {
- let reg = registry(vec![pkg!("foo" => ["bar"]), pkg!("bar")]);
- let res = resolve(&pkg_id("root"), vec![dep("foo"), dep("bar")],
- ®).unwrap();
-
- assert_that(&res, contains(names(&["root", "foo", "bar"])));
-}
-
-#[test]
-fn test_resolving_with_same_name() {
- let list = vec![pkg_loc("foo", "http://first.example.com"),
- pkg_loc("bar", "http://second.example.com")];
-
- let reg = registry(list);
- let res = resolve(&pkg_id("root"),
- vec![dep_loc("foo", "http://first.example.com"),
- dep_loc("bar", "http://second.example.com")],
- ®);
-
- let mut names = loc_names(&[("foo", "http://first.example.com"),
- ("bar", "http://second.example.com")]);
-
- names.push(pkg_id("root"));
-
- assert_that(&res.unwrap(), contains(names).exactly());
-}
-
-#[test]
-fn test_resolving_with_dev_deps() {
- let reg = registry(vec![
- pkg!("foo" => ["bar", dep_kind("baz", Development)]),
- pkg!("baz" => ["bat", dep_kind("bam", Development)]),
- pkg!("bar"),
- pkg!("bat")
- ]);
-
- let res = resolve(&pkg_id("root"),
- vec![dep("foo"), dep_kind("baz", Development)],
- ®).unwrap();
-
- assert_that(&res, contains(names(&["root", "foo", "bar", "baz"])));
-}
-
-#[test]
-fn resolving_with_many_versions() {
- let reg = registry(vec![
- pkg!(("foo", "1.0.1")),
- pkg!(("foo", "1.0.2")),
- ]);
-
- let res = resolve(&pkg_id("root"), vec![dep("foo")], ®).unwrap();
-
- assert_that(&res, contains(names(&[("root", "1.0.0"),
- ("foo", "1.0.2")])));
-}
-
-#[test]
-fn resolving_with_specific_version() {
- let reg = registry(vec![
- pkg!(("foo", "1.0.1")),
- pkg!(("foo", "1.0.2")),
- ]);
-
- let res = resolve(&pkg_id("root"), vec![dep_req("foo", "=1.0.1")],
- ®).unwrap();
-
- assert_that(&res, contains(names(&[("root", "1.0.0"),
- ("foo", "1.0.1")])));
-}
-
-#[test]
-fn test_resolving_maximum_version_with_transitive_deps() {
- let reg = registry(vec![
- pkg!(("util", "1.2.2")),
- pkg!(("util", "1.0.0")),
- pkg!(("util", "1.1.1")),
- pkg!("foo" => [dep_req("util", "1.0.0")]),
- pkg!("bar" => [dep_req("util", ">=1.0.1")]),
- ]);
-
- let res = resolve(&pkg_id("root"), vec![dep_req("foo", "1.0.0"), dep_req("bar", "1.0.0")],
- ®).unwrap();
-
- assert_that(&res, contains(names(&[("root", "1.0.0"),
- ("foo", "1.0.0"),
- ("bar", "1.0.0"),
- ("util", "1.2.2")])));
- assert_that(&res, not(contains(names(&[("util", "1.0.1")]))));
- assert_that(&res, not(contains(names(&[("util", "1.1.1")]))));
-}
-
-#[test]
-fn resolving_incompat_versions() {
- let reg = registry(vec![
- pkg!(("foo", "1.0.1")),
- pkg!(("foo", "1.0.2")),
- pkg!("bar" => [dep_req("foo", "=1.0.2")]),
- ]);
-
- assert!(resolve(&pkg_id("root"), vec![
- dep_req("foo", "=1.0.1"),
- dep("bar"),
- ], ®).is_err());
-}
-
-#[test]
-fn resolving_backtrack() {
- let reg = registry(vec![
- pkg!(("foo", "1.0.2") => [dep("bar")]),
- pkg!(("foo", "1.0.1") => [dep("baz")]),
- pkg!("bar" => [dep_req("foo", "=2.0.2")]),
- pkg!("baz"),
- ]);
-
- let res = resolve(&pkg_id("root"), vec![
- dep_req("foo", "^1"),
- ], ®).unwrap();
-
- assert_that(&res, contains(names(&[("root", "1.0.0"),
- ("foo", "1.0.1"),
- ("baz", "1.0.0")])));
-}
-
-#[test]
-fn resolving_allows_multiple_compatible_versions() {
- let reg = registry(vec![
- pkg!(("foo", "1.0.0")),
- pkg!(("foo", "2.0.0")),
- pkg!(("foo", "0.1.0")),
- pkg!(("foo", "0.2.0")),
-
- pkg!("bar" => ["d1", "d2", "d3", "d4"]),
- pkg!("d1" => [dep_req("foo", "1")]),
- pkg!("d2" => [dep_req("foo", "2")]),
- pkg!("d3" => [dep_req("foo", "0.1")]),
- pkg!("d4" => [dep_req("foo", "0.2")]),
- ]);
-
- let res = resolve(&pkg_id("root"), vec![
- dep("bar"),
- ], ®).unwrap();
-
- assert_that(&res, contains(names(&[("root", "1.0.0"),
- ("foo", "1.0.0"),
- ("foo", "2.0.0"),
- ("foo", "0.1.0"),
- ("foo", "0.2.0"),
- ("d1", "1.0.0"),
- ("d2", "1.0.0"),
- ("d3", "1.0.0"),
- ("d4", "1.0.0"),
- ("bar", "1.0.0")])));
-}
-
-#[test]
-fn resolving_with_deep_backtracking() {
- let reg = registry(vec![
- pkg!(("foo", "1.0.1") => [dep_req("bar", "1")]),
- pkg!(("foo", "1.0.0") => [dep_req("bar", "2")]),
-
- pkg!(("bar", "1.0.0") => [dep_req("baz", "=1.0.2"),
- dep_req("other", "1")]),
- pkg!(("bar", "2.0.0") => [dep_req("baz", "=1.0.1")]),
-
- pkg!(("baz", "1.0.2") => [dep_req("other", "2")]),
- pkg!(("baz", "1.0.1")),
-
- pkg!(("dep_req", "1.0.0")),
- pkg!(("dep_req", "2.0.0")),
- ]);
-
- let res = resolve(&pkg_id("root"), vec![
- dep_req("foo", "1"),
- ], ®).unwrap();
-
- assert_that(&res, contains(names(&[("root", "1.0.0"),
- ("foo", "1.0.0"),
- ("bar", "2.0.0"),
- ("baz", "1.0.1")])));
-}
-
-#[test]
-fn resolving_with_constrained_sibling_backtrack_parent() {
- // There is no point in considering all of the backtrack_trap{1,2}
- // candidates since they can't change the result of failing to
- // resolve 'constrained'. Cargo should (ideally) skip past them and resume
- // resolution once the activation of the parent, 'bar', is rolled back.
- // Note that the traps are slightly more constrained to make sure they
- // get picked first.
- let mut reglist = vec![
- pkg!(("foo", "1.0.0") => [dep_req("bar", "1.0"),
- dep_req("constrained", "=1.0.0")]),
-
- pkg!(("bar", "1.0.0") => [dep_req("backtrack_trap1", "1.0.2"),
- dep_req("backtrack_trap2", "1.0.2"),
- dep_req("constrained", "1.0.0")]),
- pkg!(("constrained", "1.0.0")),
- pkg!(("backtrack_trap1", "1.0.0")),
- pkg!(("backtrack_trap2", "1.0.0")),
- ];
- // Bump this to make the test harder - it adds more versions of bar that will
- // fail to resolve, and more versions of the traps to consider.
- const NUM_BARS_AND_TRAPS: usize = 50; // minimum 2
- for i in 1..NUM_BARS_AND_TRAPS {
- let vsn = format!("1.0.{}", i);
- reglist.push(pkg!(("bar", vsn.clone()) => [dep_req("backtrack_trap1", "1.0.2"),
- dep_req("backtrack_trap2", "1.0.2"),
- dep_req("constrained", "1.0.1")]));
- reglist.push(pkg!(("backtrack_trap1", vsn.clone())));
- reglist.push(pkg!(("backtrack_trap2", vsn.clone())));
- reglist.push(pkg!(("constrained", vsn.clone())));
- }
- let reg = registry(reglist);
-
- let res = resolve(&pkg_id("root"), vec![
- dep_req("foo", "1"),
- ], ®).unwrap();
-
- assert_that(&res, contains(names(&[("root", "1.0.0"),
- ("foo", "1.0.0"),
- ("bar", "1.0.0"),
- ("constrained", "1.0.0")])));
-}
-
-#[test]
-fn resolving_with_constrained_sibling_backtrack_activation() {
- // It makes sense to resolve most-constrained deps first, but
- // with that logic the backtrack traps here come between the two
- // attempted resolutions of 'constrained'. When backtracking,
- // cargo should skip past them and resume resolution once the
- // number of activations for 'constrained' changes.
- let mut reglist = vec![
- pkg!(("foo", "1.0.0") => [dep_req("bar", "=1.0.0"),
- dep_req("backtrack_trap1", "1.0"),
- dep_req("backtrack_trap2", "1.0"),
- dep_req("constrained", "<=1.0.60")]),
- pkg!(("bar", "1.0.0") => [dep_req("constrained", ">=1.0.60")]),
- ];
- // Bump these to make the test harder, but you'll also need to
- // change the version constraints on `constrained` above. To correctly
- // exercise Cargo, the relationship between the values is:
- // NUM_CONSTRAINED - vsn < NUM_TRAPS < vsn
- // to make sure the traps are resolved between `constrained`.
- const NUM_TRAPS: usize = 45; // min 1
- const NUM_CONSTRAINED: usize = 100; // min 1
- for i in 0..NUM_TRAPS {
- let vsn = format!("1.0.{}", i);
- reglist.push(pkg!(("backtrack_trap1", vsn.clone())));
- reglist.push(pkg!(("backtrack_trap2", vsn.clone())));
- }
- for i in 0..NUM_CONSTRAINED {
- let vsn = format!("1.0.{}", i);
- reglist.push(pkg!(("constrained", vsn.clone())));
- }
- let reg = registry(reglist);
-
- let res = resolve(&pkg_id("root"), vec![
- dep_req("foo", "1"),
- ], ®).unwrap();
-
- assert_that(&res, contains(names(&[("root", "1.0.0"),
- ("foo", "1.0.0"),
- ("bar", "1.0.0"),
- ("constrained", "1.0.60")])));
-}
-
-#[test]
-fn resolving_with_constrained_sibling_transitive_dep_effects() {
- // When backtracking due to a failed dependency, if Cargo is
- // trying to be clever and skip irrelevant dependencies, care must
- // be taken to not miss the transitive effects of alternatives. E.g.
- // in the right-to-left resolution of the graph below, B may
- // affect whether D is successfully resolved.
- //
- // A
- // / | \
- // B C D
- // | |
- // C D
- let reg = registry(vec![
- pkg!(("A", "1.0.0") => [dep_req("B", "1.0"),
- dep_req("C", "1.0"),
- dep_req("D", "1.0.100")]),
-
- pkg!(("B", "1.0.0") => [dep_req("C", ">=1.0.0")]),
- pkg!(("B", "1.0.1") => [dep_req("C", ">=1.0.1")]),
-
- pkg!(("C", "1.0.0") => [dep_req("D", "1.0.0")]),
- pkg!(("C", "1.0.1") => [dep_req("D", ">=1.0.1,<1.0.100")]),
- pkg!(("C", "1.0.2") => [dep_req("D", ">=1.0.2,<1.0.100")]),
-
- pkg!(("D", "1.0.0")),
- pkg!(("D", "1.0.1")),
- pkg!(("D", "1.0.2")),
- pkg!(("D", "1.0.100")),
- pkg!(("D", "1.0.101")),
- pkg!(("D", "1.0.102")),
- pkg!(("D", "1.0.103")),
- pkg!(("D", "1.0.104")),
- pkg!(("D", "1.0.105")),
- ]);
-
- let res = resolve(&pkg_id("root"), vec![
- dep_req("A", "1"),
- ], ®).unwrap();
-
- assert_that(&res, contains(names(&[("A", "1.0.0"),
- ("B", "1.0.0"),
- ("C", "1.0.0"),
- ("D", "1.0.105")])));
-}
-
-#[test]
-fn resolving_but_no_exists() {
- let reg = registry(vec![
- ]);
-
- let res = resolve(&pkg_id("root"), vec![
- dep_req("foo", "1"),
- ], ®);
- assert!(res.is_err());
-
- assert_eq!(res.err().unwrap().to_string(), "\
-no matching package named `foo` found\n\
-location searched: registry `http://example.com/`\n\
-required by package `root v1.0.0 (registry `http://example.com/`)`\
-");
-}
-
-#[test]
-fn resolving_cycle() {
- let reg = registry(vec![
- pkg!("foo" => ["foo"]),
- ]);
-
- let _ = resolve(&pkg_id("root"), vec![
- dep_req("foo", "1"),
- ], ®);
-}
-
-#[test]
-fn hard_equality() {
- let reg = registry(vec![
- pkg!(("foo", "1.0.1")),
- pkg!(("foo", "1.0.0")),
-
- pkg!(("bar", "1.0.0") => [dep_req("foo", "1.0.0")]),
- ]);
-
- let res = resolve(&pkg_id("root"), vec![
- dep_req("bar", "1"),
- dep_req("foo", "=1.0.0"),
- ], ®).unwrap();
-
- assert_that(&res, contains(names(&[("root", "1.0.0"),
- ("foo", "1.0.0"),
- ("bar", "1.0.0")])));
-}
+++ /dev/null
-extern crate cargo;
-extern crate cargotest;
-extern crate hamcrest;
-
-use cargo::util::paths::dylib_path_envvar;
-use cargotest::support::{project, execs, path2url};
-use hamcrest::{assert_that, existing_file};
-
-#[test]
-fn simple() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/main.rs", r#"
- fn main() { println!("hello"); }
- "#)
- .build();
-
- assert_that(p.cargo("run"),
- execs().with_status(0)
- .with_stderr(&format!("\
-[COMPILING] foo v0.0.1 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] `target[/]debug[/]foo[EXE]`", dir = path2url(p.root())))
- .with_stdout("\
-hello
-"));
- assert_that(&p.bin("foo"), existing_file());
-}
-
-#[test]
-#[ignore]
-fn simple_implicit_main() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/main.rs", r#"
- fn main() { println!("hello world"); }
- "#)
- .build();
-
- assert_that(p.cargo("run").arg("--bins"),
- execs().with_status(0)
- .with_stderr(&format!("\
-[COMPILING] foo v0.0.1 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] `target[/]debug[/]foo[EXE]`", dir = path2url(p.root())))
- .with_stdout("\
-hello
-"));
- assert_that(&p.bin("foo"), existing_file());
-}
-
-#[test]
-fn simple_quiet() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/main.rs", r#"
- fn main() { println!("hello"); }
- "#)
- .build();
-
- assert_that(p.cargo("run").arg("-q"),
- execs().with_status(0).with_stdout("\
-hello
-")
- );
-}
-
-#[test]
-fn simple_quiet_and_verbose() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/main.rs", r#"
- fn main() { println!("hello"); }
- "#)
- .build();
-
- assert_that(p.cargo("run").arg("-q").arg("-v"),
- execs().with_status(101).with_stderr("\
-[ERROR] cannot set both --verbose and --quiet
-"));
-}
-
-#[test]
-fn quiet_and_verbose_config() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file(".cargo/config", r#"
- [term]
- verbose = true
- "#)
- .file("src/main.rs", r#"
- fn main() { println!("hello"); }
- "#)
- .build();
-
- assert_that(p.cargo("run").arg("-q"),
- execs().with_status(0));
-}
-
-#[test]
-fn simple_with_args() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/main.rs", r#"
- fn main() {
- assert_eq!(std::env::args().nth(1).unwrap(), "hello");
- assert_eq!(std::env::args().nth(2).unwrap(), "world");
- }
- "#)
- .build();
-
- assert_that(p.cargo("run").arg("hello").arg("world"),
- execs().with_status(0));
-}
-
-#[test]
-fn exit_code() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/main.rs", r#"
- fn main() { std::process::exit(2); }
- "#)
- .build();
-
- let mut output = String::from("\
-[COMPILING] foo v0.0.1 (file[..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] `target[..]`
-");
- if !cfg!(unix) {
- output.push_str("\
-[ERROR] process didn't exit successfully: `target[..]foo[..]` (exit code: 2)
-");
- }
- assert_that(p.cargo("run"),
- execs().with_status(2).with_stderr(output));
-}
-
-#[test]
-fn exit_code_verbose() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/main.rs", r#"
- fn main() { std::process::exit(2); }
- "#)
- .build();
-
- let mut output = String::from("\
-[COMPILING] foo v0.0.1 (file[..])
-[RUNNING] `rustc [..]`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] `target[..]`
-");
- if !cfg!(unix) {
- output.push_str("\
-[ERROR] process didn't exit successfully: `target[..]foo[..]` (exit code: 2)
-");
- }
-
- assert_that(p.cargo("run").arg("-v"),
- execs().with_status(2).with_stderr(output));
-}
-
-#[test]
-fn no_main_file() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("run"),
- execs().with_status(101)
- .with_stderr("[ERROR] a bin target must be available \
- for `cargo run`\n"));
-}
-
-#[test]
-#[ignore]
-fn no_main_file_implicit() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("run").arg("--bins"),
- execs().with_status(101)
- .with_stderr("[ERROR] a bin target must be available \
- for `cargo run`\n"));
-}
-
-#[test]
-fn too_many_bins() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/lib.rs", "")
- .file("src/bin/a.rs", "")
- .file("src/bin/b.rs", "")
- .build();
-
- assert_that(p.cargo("run"),
- execs().with_status(101)
- .with_stderr("[ERROR] `cargo run` requires that a project only \
- have one executable; use the `--bin` option \
- to specify which one to run\navailable binaries: [..]\n"));
-}
-
-#[test]
-#[ignore]
-fn too_many_bins_implicit() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/lib.rs", "")
- .file("src/bin/a.rs", "")
- .file("src/bin/b.rs", "")
- .build();
-
- assert_that(p.cargo("run").arg("--bins"),
- execs().with_status(101)
- .with_stderr("[ERROR] `cargo run` requires that a project only \
- have one executable; use the `--bin` option \
- to specify which one to run\navailable binaries: [..]\n"));
-}
-
-#[test]
-fn specify_name() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/lib.rs", "")
- .file("src/bin/a.rs", r#"
- #[allow(unused_extern_crates)]
- extern crate foo;
- fn main() { println!("hello a.rs"); }
- "#)
- .file("src/bin/b.rs", r#"
- #[allow(unused_extern_crates)]
- extern crate foo;
- fn main() { println!("hello b.rs"); }
- "#)
- .build();
-
- assert_that(p.cargo("run").arg("--bin").arg("a").arg("-v"),
- execs().with_status(0)
- .with_stderr(&format!("\
-[COMPILING] foo v0.0.1 ({dir})
-[RUNNING] `rustc [..] src[/]lib.rs [..]`
-[RUNNING] `rustc [..] src[/]bin[/]a.rs [..]`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] `target[/]debug[/]a[EXE]`", dir = path2url(p.root())))
- .with_stdout("\
-hello a.rs
-"));
-
- assert_that(p.cargo("run").arg("--bin").arg("b").arg("-v"),
- execs().with_status(0)
- .with_stderr("\
-[COMPILING] foo v0.0.1 ([..])
-[RUNNING] `rustc [..] src[/]bin[/]b.rs [..]`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] `target[/]debug[/]b[EXE]`")
- .with_stdout("\
-hello b.rs
-"));
-}
-
-#[test]
-fn run_example() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/lib.rs", "")
- .file("examples/a.rs", r#"
- fn main() { println!("example"); }
- "#)
- .file("src/bin/a.rs", r#"
- fn main() { println!("bin"); }
- "#)
- .build();
-
- assert_that(p.cargo("run").arg("--example").arg("a"),
- execs().with_status(0)
- .with_stderr(&format!("\
-[COMPILING] foo v0.0.1 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] `target[/]debug[/]examples[/]a[EXE]`", dir = path2url(p.root())))
- .with_stdout("\
-example
-"));
-}
-
-#[test]
-#[ignore]
-fn run_bin_implicit() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/lib.rs", "")
- .file("examples/a.rs", r#"
- fn main() { println!("example"); }
- "#)
- .file("src/bin/a.rs", r#"
- fn main() { println!("bin"); }
- "#)
- .build();
-
- assert_that(p.cargo("run").arg("--bins"),
- execs().with_status(0)
- .with_stderr(&format!("\
-[COMPILING] foo v0.0.1 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] `target[/]debug[/]examples[/]a[EXE]`", dir = path2url(p.root())))
- .with_stdout("\
-bin
-"));
-}
-
-#[test]
-#[ignore]
-fn run_example_implicit() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/lib.rs", "")
- .file("examples/a.rs", r#"
- fn main() { println!("example"); }
- "#)
- .file("src/bin/a.rs", r#"
- fn main() { println!("bin"); }
- "#)
- .build();
-
- assert_that(p.cargo("run").arg("--examples"),
- execs().with_status(0)
- .with_stderr(&format!("\
-[COMPILING] foo v0.0.1 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] `target[/]debug[/]examples[/]a[EXE]`", dir = path2url(p.root())))
- .with_stdout("\
-example
-"));
-}
-
-#[test]
-fn run_with_filename() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/lib.rs", "")
- .file("src/bin/a.rs", r#"
- extern crate foo;
- fn main() { println!("hello a.rs"); }
- "#)
- .file("examples/a.rs", r#"
- fn main() { println!("example"); }
- "#)
- .build();
-
- assert_that(p.cargo("run").arg("--bin").arg("bin.rs"),
- execs().with_status(101).with_stderr("\
-[ERROR] no bin target named `bin.rs`"));
-
- assert_that(p.cargo("run").arg("--bin").arg("a.rs"),
- execs().with_status(101).with_stderr("\
-[ERROR] no bin target named `a.rs`
-
-Did you mean `a`?"));
-
- assert_that(p.cargo("run").arg("--example").arg("example.rs"),
- execs().with_status(101).with_stderr("\
-[ERROR] no example target named `example.rs`"));
-
- assert_that(p.cargo("run").arg("--example").arg("a.rs"),
- execs().with_status(101).with_stderr("\
-[ERROR] no example target named `a.rs`
-
-Did you mean `a`?"));
-}
-
-#[test]
-fn either_name_or_example() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/bin/a.rs", r#"
- fn main() { println!("hello a.rs"); }
- "#)
- .file("examples/b.rs", r#"
- fn main() { println!("hello b.rs"); }
- "#)
- .build();
-
- assert_that(p.cargo("run").arg("--bin").arg("a").arg("--example").arg("b"),
- execs().with_status(101)
- .with_stderr("[ERROR] `cargo run` can run at most one \
- executable, but multiple were \
- specified"));
-}
-
-#[test]
-fn one_bin_multiple_examples() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/lib.rs", "")
- .file("src/bin/main.rs", r#"
- fn main() { println!("hello main.rs"); }
- "#)
- .file("examples/a.rs", r#"
- fn main() { println!("hello a.rs"); }
- "#)
- .file("examples/b.rs", r#"
- fn main() { println!("hello b.rs"); }
- "#)
- .build();
-
- assert_that(p.cargo("run"),
- execs().with_status(0)
- .with_stderr(&format!("\
-[COMPILING] foo v0.0.1 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] `target[/]debug[/]main[EXE]`", dir = path2url(p.root())))
- .with_stdout("\
-hello main.rs
-"));
-}
-
-#[test]
-fn example_with_release_flag() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies.bar]
- version = "*"
- path = "bar"
- "#)
- .file("examples/a.rs", r#"
- extern crate bar;
-
- fn main() {
- if cfg!(debug_assertions) {
- println!("slow1")
- } else {
- println!("fast1")
- }
- bar::baz();
- }
- "#)
- .file("bar/Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.0.1"
- authors = []
-
- [lib]
- name = "bar"
- "#)
- .file("bar/src/bar.rs", r#"
- pub fn baz() {
- if cfg!(debug_assertions) {
- println!("slow2")
- } else {
- println!("fast2")
- }
- }
- "#)
- .build();
-
- assert_that(p.cargo("run").arg("-v").arg("--release").arg("--example").arg("a"),
- execs().with_status(0)
- .with_stderr(&format!("\
-[COMPILING] bar v0.0.1 ({url}/bar)
-[RUNNING] `rustc --crate-name bar bar[/]src[/]bar.rs --crate-type lib \
- --emit=dep-info,link \
- -C opt-level=3 \
- -C metadata=[..] \
- --out-dir {dir}[/]target[/]release[/]deps \
- -L dependency={dir}[/]target[/]release[/]deps`
-[COMPILING] foo v0.0.1 ({url})
-[RUNNING] `rustc --crate-name a examples[/]a.rs --crate-type bin \
- --emit=dep-info,link \
- -C opt-level=3 \
- -C metadata=[..] \
- --out-dir {dir}[/]target[/]release[/]examples \
- -L dependency={dir}[/]target[/]release[/]deps \
- --extern bar={dir}[/]target[/]release[/]deps[/]libbar-[..].rlib`
-[FINISHED] release [optimized] target(s) in [..]
-[RUNNING] `target[/]release[/]examples[/]a[EXE]`
-",
- dir = p.root().display(),
- url = path2url(p.root()),
- ))
- .with_stdout("\
-fast1
-fast2"));
-
- assert_that(p.cargo("run").arg("-v").arg("--example").arg("a"),
- execs().with_status(0)
- .with_stderr(&format!("\
-[COMPILING] bar v0.0.1 ({url}/bar)
-[RUNNING] `rustc --crate-name bar bar[/]src[/]bar.rs --crate-type lib \
- --emit=dep-info,link \
- -C debuginfo=2 \
- -C metadata=[..] \
- --out-dir {dir}[/]target[/]debug[/]deps \
- -L dependency={dir}[/]target[/]debug[/]deps`
-[COMPILING] foo v0.0.1 ({url})
-[RUNNING] `rustc --crate-name a examples[/]a.rs --crate-type bin \
- --emit=dep-info,link \
- -C debuginfo=2 \
- -C metadata=[..] \
- --out-dir {dir}[/]target[/]debug[/]examples \
- -L dependency={dir}[/]target[/]debug[/]deps \
- --extern bar={dir}[/]target[/]debug[/]deps[/]libbar-[..].rlib`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] `target[/]debug[/]examples[/]a[EXE]`
-",
- dir = p.root().display(),
- url = path2url(p.root()),
- ))
- .with_stdout("\
-slow1
-slow2"));
-}
-
-#[test]
-fn run_dylib_dep() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies.bar]
- path = "bar"
- "#)
- .file("src/main.rs", r#"
- extern crate bar;
- fn main() { bar::bar(); }
- "#)
- .file("bar/Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
-
- [lib]
- name = "bar"
- crate-type = ["dylib"]
- "#)
- .file("bar/src/lib.rs", "pub fn bar() {}")
- .build();
-
- assert_that(p.cargo("run").arg("hello").arg("world"),
- execs().with_status(0));
-}
-
-#[test]
-fn release_works() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/main.rs", r#"
- fn main() { if cfg!(debug_assertions) { panic!() } }
- "#)
- .build();
-
- assert_that(p.cargo("run").arg("--release"),
- execs().with_status(0).with_stderr(&format!("\
-[COMPILING] foo v0.0.1 ({dir})
-[FINISHED] release [optimized] target(s) in [..]
-[RUNNING] `target[/]release[/]foo[EXE]`
-",
- dir = path2url(p.root()),
- )));
- assert_that(&p.release_bin("foo"), existing_file());
-}
-
-#[test]
-fn run_bin_different_name() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [[bin]]
- name = "bar"
- "#)
- .file("src/bar.rs", r#"
- fn main() { }
- "#)
- .build();
-
- assert_that(p.cargo("run"), execs().with_status(0));
-}
-
-#[test]
-fn dashes_are_forwarded() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [[bin]]
- name = "bar"
- "#)
- .file("src/main.rs", r#"
- fn main() {
- let s: Vec<String> = std::env::args().collect();
- assert_eq!(s[1], "a");
- assert_eq!(s[2], "--");
- assert_eq!(s[3], "b");
- }
- "#)
- .build();
-
- assert_that(p.cargo("run").arg("--").arg("a").arg("--").arg("b"),
- execs().with_status(0));
-}
-
-#[test]
-fn run_from_executable_folder() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/main.rs", r#"
- fn main() { println!("hello"); }
- "#)
- .build();
-
- let cwd = p.root().join("target").join("debug");
- p.cargo("build").exec_with_output().unwrap();
-
- assert_that(p.cargo("run").cwd(cwd),
- execs().with_status(0)
- .with_stderr("\
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]\n\
-[RUNNING] `.[/]foo[EXE]`")
- .with_stdout("\
-hello
-"));
-}
-
-#[test]
-fn run_with_library_paths() {
- let p = project("foo");
-
- // Only link search directories within the target output directory are
- // propagated through to dylib_path_envvar() (see #3366).
- let mut dir1 = p.target_debug_dir();
- dir1.push("foo\\backslash");
-
- let mut dir2 = p.target_debug_dir();
- dir2.push("dir=containing=equal=signs");
-
- let p = p
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- build = "build.rs"
- "#)
- .file("build.rs", &format!(r##"
- fn main() {{
- println!(r#"cargo:rustc-link-search=native={}"#);
- println!(r#"cargo:rustc-link-search={}"#);
- }}
- "##, dir1.display(), dir2.display()))
- .file("src/main.rs", &format!(r##"
- fn main() {{
- let search_path = std::env::var_os("{}").unwrap();
- let paths = std::env::split_paths(&search_path).collect::<Vec<_>>();
- assert!(paths.contains(&r#"{}"#.into()));
- assert!(paths.contains(&r#"{}"#.into()));
- }}
- "##, dylib_path_envvar(), dir1.display(), dir2.display()))
- .build();
-
- assert_that(p.cargo("run"), execs().with_status(0));
-}
-
-#[test]
-fn library_paths_sorted_alphabetically() {
- let p = project("foo");
-
- let mut dir1 = p.target_debug_dir();
- dir1.push("zzzzzzz");
-
- let mut dir2 = p.target_debug_dir();
- dir2.push("BBBBBBB");
-
- let mut dir3 = p.target_debug_dir();
- dir3.push("aaaaaaa");
-
- let p = p
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- build = "build.rs"
- "#)
- .file("build.rs", &format!(r##"
- fn main() {{
- println!(r#"cargo:rustc-link-search=native={}"#);
- println!(r#"cargo:rustc-link-search=native={}"#);
- println!(r#"cargo:rustc-link-search=native={}"#);
- }}
- "##, dir1.display(), dir2.display(), dir3.display()))
- .file("src/main.rs", &format!(r##"
- fn main() {{
- let search_path = std::env::var_os("{}").unwrap();
- let paths = std::env::split_paths(&search_path).collect::<Vec<_>>();
- // ASCII case-sensitive sort
- assert_eq!("BBBBBBB", paths[0].file_name().unwrap().to_string_lossy());
- assert_eq!("aaaaaaa", paths[1].file_name().unwrap().to_string_lossy());
- assert_eq!("zzzzzzz", paths[2].file_name().unwrap().to_string_lossy());
- }}
- "##, dylib_path_envvar()))
- .build();
-
- assert_that(p.cargo("run"), execs().with_status(0));
-}
-
-#[test]
-fn fail_no_extra_verbose() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/main.rs", r#"
- fn main() {
- std::process::exit(1);
- }
- "#)
- .build();
-
- assert_that(p.cargo("run").arg("-q"),
- execs().with_status(1)
- .with_stdout("")
- .with_stderr(""));
-}
-
-#[test]
-fn run_multiple_packages() {
- let p = project("foo")
- .file("foo/Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [workspace]
-
- [dependencies]
- d1 = { path = "d1" }
- d2 = { path = "d2" }
- d3 = { path = "../d3" } # outside of the workspace
-
- [[bin]]
- name = "foo"
- "#)
- .file("foo/src/foo.rs", "fn main() { println!(\"foo\"); }")
- .file("foo/d1/Cargo.toml", r#"
- [package]
- name = "d1"
- version = "0.0.1"
- authors = []
-
- [[bin]]
- name = "d1"
- "#)
- .file("foo/d1/src/lib.rs", "")
- .file("foo/d1/src/main.rs", "fn main() { println!(\"d1\"); }")
- .file("foo/d2/Cargo.toml", r#"
- [package]
- name = "d2"
- version = "0.0.1"
- authors = []
-
- [[bin]]
- name = "d2"
- "#)
- .file("foo/d2/src/main.rs", "fn main() { println!(\"d2\"); }")
- .file("d3/Cargo.toml", r#"
- [package]
- name = "d3"
- version = "0.0.1"
- authors = []
- "#)
- .file("d3/src/main.rs", "fn main() { println!(\"d2\"); }")
- .build();
-
- let cargo = || {
- let mut process_builder = p.cargo("run");
- process_builder.cwd(p.root().join("foo"));
- process_builder
- };
-
- assert_that(cargo().arg("-p").arg("d1"),
- execs().with_status(0).with_stdout("d1"));
-
- assert_that(cargo().arg("-p").arg("d2").arg("--bin").arg("d2"),
- execs().with_status(0).with_stdout("d2"));
-
- assert_that(cargo(),
- execs().with_status(0).with_stdout("foo"));
-
- assert_that(cargo().arg("-p").arg("d1").arg("-p").arg("d2"),
- execs()
- .with_status(1)
- .with_stderr_contains("[ERROR] Invalid arguments."));
-
- assert_that(cargo().arg("-p").arg("d3"),
- execs()
- .with_status(101)
- .with_stderr_contains("[ERROR] package `d3` is not a member of the workspace"));
-}
+++ /dev/null
-extern crate cargotest;
-extern crate hamcrest;
-
-use cargotest::support::{execs, project};
-use hamcrest::assert_that;
-
-const CARGO_RUSTC_ERROR: &'static str =
-"[ERROR] extra arguments to `rustc` can only be passed to one target, consider filtering
-the package by passing e.g. `--lib` or `--bin NAME` to specify a single target";
-
-#[test]
-fn build_lib_for_foo() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/main.rs", r#"
- fn main() {}
- "#)
- .file("src/lib.rs", r#" "#)
- .build();
-
- assert_that(p.cargo("rustc").arg("--lib").arg("-v"),
- execs()
- .with_status(0)
- .with_stderr(format!("\
-[COMPILING] foo v0.0.1 ({url})
-[RUNNING] `rustc --crate-name foo src[/]lib.rs --crate-type lib \
- --emit=dep-info,link -C debuginfo=2 \
- -C metadata=[..] \
- --out-dir [..] \
- -L dependency={dir}[/]target[/]debug[/]deps`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-", dir = p.root().display(), url = p.url())));
-}
-
-#[test]
-fn lib() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/main.rs", r#"
- fn main() {}
- "#)
- .file("src/lib.rs", r#" "#)
- .build();
-
- assert_that(p.cargo("rustc").arg("--lib").arg("-v")
- .arg("--").arg("-C").arg("debug-assertions=off"),
- execs()
- .with_status(0)
- .with_stderr(format!("\
-[COMPILING] foo v0.0.1 ({url})
-[RUNNING] `rustc --crate-name foo src[/]lib.rs --crate-type lib \
- --emit=dep-info,link -C debuginfo=2 \
- -C debug-assertions=off \
- -C metadata=[..] \
- --out-dir [..] \
- -L dependency={dir}[/]target[/]debug[/]deps`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-", dir = p.root().display(), url = p.url())))
-}
-
-#[test]
-fn build_main_and_allow_unstable_options() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/main.rs", r#"
- fn main() {}
- "#)
- .file("src/lib.rs", r#" "#)
- .build();
-
- assert_that(p.cargo("rustc").arg("-v").arg("--bin").arg("foo")
- .arg("--").arg("-C").arg("debug-assertions"),
- execs()
- .with_status(0)
- .with_stderr(&format!("\
-[COMPILING] {name} v{version} ({url})
-[RUNNING] `rustc --crate-name {name} src[/]lib.rs --crate-type lib \
- --emit=dep-info,link -C debuginfo=2 \
- -C metadata=[..] \
- --out-dir [..] \
- -L dependency={dir}[/]target[/]debug[/]deps`
-[RUNNING] `rustc --crate-name {name} src[/]main.rs --crate-type bin \
- --emit=dep-info,link -C debuginfo=2 \
- -C debug-assertions \
- -C metadata=[..] \
- --out-dir [..] \
- -L dependency={dir}[/]target[/]debug[/]deps \
- --extern {name}={dir}[/]target[/]debug[/]deps[/]lib{name}-[..].rlib`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-",
- dir = p.root().display(), url = p.url(),
- name = "foo", version = "0.0.1")));
-}
-
-#[test]
-fn fails_when_trying_to_build_main_and_lib_with_args() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/main.rs", r#"
- fn main() {}
- "#)
- .file("src/lib.rs", r#" "#)
- .build();
-
- assert_that(p.cargo("rustc").arg("-v")
- .arg("--").arg("-C").arg("debug-assertions"),
- execs()
- .with_status(101)
- .with_stderr(CARGO_RUSTC_ERROR));
-}
-
-#[test]
-fn build_with_args_to_one_of_multiple_binaries() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/bin/foo.rs", r#"
- fn main() {}
- "#)
- .file("src/bin/bar.rs", r#"
- fn main() {}
- "#)
- .file("src/bin/baz.rs", r#"
- fn main() {}
- "#)
- .file("src/lib.rs", r#" "#)
- .build();
-
- assert_that(p.cargo("rustc").arg("-v").arg("--bin").arg("bar")
- .arg("--").arg("-C").arg("debug-assertions"),
- execs()
- .with_status(0)
- .with_stderr(format!("\
-[COMPILING] foo v0.0.1 ({url})
-[RUNNING] `rustc --crate-name foo src[/]lib.rs --crate-type lib --emit=dep-info,link \
- -C debuginfo=2 -C metadata=[..] \
- --out-dir [..]`
-[RUNNING] `rustc --crate-name bar src[/]bin[/]bar.rs --crate-type bin --emit=dep-info,link \
- -C debuginfo=2 -C debug-assertions [..]`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-", url = p.url())));
-}
-
-#[test]
-fn fails_with_args_to_all_binaries() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/bin/foo.rs", r#"
- fn main() {}
- "#)
- .file("src/bin/bar.rs", r#"
- fn main() {}
- "#)
- .file("src/bin/baz.rs", r#"
- fn main() {}
- "#)
- .file("src/lib.rs", r#" "#)
- .build();
-
- assert_that(p.cargo("rustc").arg("-v")
- .arg("--").arg("-C").arg("debug-assertions"),
- execs()
- .with_status(101)
- .with_stderr(CARGO_RUSTC_ERROR));
-}
-
-#[test]
-fn build_with_args_to_one_of_multiple_tests() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("tests/foo.rs", r#" "#)
- .file("tests/bar.rs", r#" "#)
- .file("tests/baz.rs", r#" "#)
- .file("src/lib.rs", r#" "#)
- .build();
-
- assert_that(p.cargo("rustc").arg("-v").arg("--test").arg("bar")
- .arg("--").arg("-C").arg("debug-assertions"),
- execs()
- .with_status(0)
- .with_stderr(format!("\
-[COMPILING] foo v0.0.1 ({url})
-[RUNNING] `rustc --crate-name foo src[/]lib.rs --crate-type lib --emit=dep-info,link \
- -C debuginfo=2 -C metadata=[..] \
- --out-dir [..]`
-[RUNNING] `rustc --crate-name bar tests[/]bar.rs --emit=dep-info,link -C debuginfo=2 \
- -C debug-assertions [..]--test[..]`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-", url = p.url())));
-}
-
-#[test]
-fn build_foo_with_bar_dependency() {
- let foo = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies.bar]
- path = "../bar"
- "#)
- .file("src/main.rs", r#"
- extern crate bar;
- fn main() {
- bar::baz()
- }
- "#)
- .build();
- let _bar = project("bar")
- .file("Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.1.0"
- authors = []
- "#)
- .file("src/lib.rs", r#"
- pub fn baz() {}
- "#)
- .build();
-
- assert_that(foo.cargo("rustc").arg("-v").arg("--").arg("-C").arg("debug-assertions"),
- execs()
- .with_status(0)
- .with_stderr(format!("\
-[COMPILING] bar v0.1.0 ([..])
-[RUNNING] `[..] -C debuginfo=2 [..]`
-[COMPILING] foo v0.0.1 ({url})
-[RUNNING] `[..] -C debuginfo=2 -C debug-assertions [..]`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-", url = foo.url())));
-}
-
-#[test]
-fn build_only_bar_dependency() {
- let foo = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies.bar]
- path = "../bar"
- "#)
- .file("src/main.rs", r#"
- extern crate bar;
- fn main() {
- bar::baz()
- }
- "#)
- .build();
- let _bar = project("bar")
- .file("Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.1.0"
- authors = []
- "#)
- .file("src/lib.rs", r#"
- pub fn baz() {}
- "#)
- .build();
-
- assert_that(foo.cargo("rustc").arg("-v").arg("-p").arg("bar")
- .arg("--").arg("-C").arg("debug-assertions"),
- execs()
- .with_status(0)
- .with_stderr("\
-[COMPILING] bar v0.1.0 ([..])
-[RUNNING] `rustc --crate-name bar [..] --crate-type lib [..] -C debug-assertions [..]`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-}
-
-#[test]
-fn fail_with_multiple_packages() {
- let foo = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies.bar]
- path = "../bar"
-
- [dependencies.baz]
- path = "../baz"
- "#)
- .file("src/main.rs", r#"
- fn main() {}
- "#)
- .build();
-
- let _bar = project("bar")
- .file("Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.1.0"
- authors = []
- "#)
- .file("src/main.rs", r#"
- fn main() {
- if cfg!(flag = "1") { println!("Yeah from bar!"); }
- }
- "#)
- .build();
-
- let _baz = project("baz")
- .file("Cargo.toml", r#"
- [package]
- name = "baz"
- version = "0.1.0"
- authors = []
- "#)
- .file("src/main.rs", r#"
- fn main() {
- if cfg!(flag = "1") { println!("Yeah from baz!"); }
- }
- "#)
- .build();
-
- assert_that(foo.cargo("rustc").arg("-v").arg("-p").arg("bar")
- .arg("-p").arg("baz"),
- execs().with_status(1).with_stderr("\
-[ERROR] Invalid arguments.
-
-Usage:
- cargo rustc [options] [--] [<opts>...]"));
-}
-
-#[test]
-fn rustc_with_other_profile() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dev-dependencies]
- a = { path = "a" }
- "#)
- .file("src/main.rs", r#"
- #[cfg(test)] extern crate a;
-
- #[test]
- fn foo() {}
- "#)
- .file("a/Cargo.toml", r#"
- [package]
- name = "a"
- version = "0.1.0"
- authors = []
- "#)
- .file("a/src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("rustc").arg("--profile").arg("test"),
- execs().with_status(0));
-}
+++ /dev/null
-extern crate cargotest;
-extern crate hamcrest;
-
-use cargotest::support::{execs, project};
-use hamcrest::{assert_that};
-
-#[test]
-fn rustdoc_simple() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/lib.rs", r#" "#)
- .build();
-
- assert_that(p.cargo("rustdoc").arg("-v"),
- execs()
- .with_status(0)
- .with_stderr(format!("\
-[DOCUMENTING] foo v0.0.1 ({url})
-[RUNNING] `rustdoc --crate-name foo src[/]lib.rs \
- -o {dir}[/]target[/]doc \
- -L dependency={dir}[/]target[/]debug[/]deps`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-", dir = p.root().display(), url = p.url())));
-}
-
-#[test]
-fn rustdoc_args() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/lib.rs", r#" "#)
- .build();
-
- assert_that(p.cargo("rustdoc").arg("-v").arg("--").arg("--cfg=foo"),
- execs()
- .with_status(0)
- .with_stderr(format!("\
-[DOCUMENTING] foo v0.0.1 ({url})
-[RUNNING] `rustdoc --crate-name foo src[/]lib.rs \
- -o {dir}[/]target[/]doc \
- --cfg=foo \
- -L dependency={dir}[/]target[/]debug[/]deps`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-", dir = p.root().display(), url = p.url())));
-}
-
-
-
-#[test]
-fn rustdoc_foo_with_bar_dependency() {
- let foo = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies.bar]
- path = "../bar"
- "#)
- .file("src/lib.rs", r#"
- extern crate bar;
- pub fn foo() {}
- "#)
- .build();
- let _bar = project("bar")
- .file("Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/lib.rs", r#"
- pub fn baz() {}
- "#)
- .build();
-
- assert_that(foo.cargo("rustdoc").arg("-v").arg("--").arg("--cfg=foo"),
- execs()
- .with_status(0)
- .with_stderr(format!("\
-[COMPILING] bar v0.0.1 ([..])
-[RUNNING] `rustc [..]bar[/]src[/]lib.rs [..]`
-[DOCUMENTING] foo v0.0.1 ({url})
-[RUNNING] `rustdoc --crate-name foo src[/]lib.rs \
- -o {dir}[/]target[/]doc \
- --cfg=foo \
- -L dependency={dir}[/]target[/]debug[/]deps \
- --extern [..]`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-", dir = foo.root().display(), url = foo.url())));
-}
-
-#[test]
-fn rustdoc_only_bar_dependency() {
- let foo = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies.bar]
- path = "../bar"
- "#)
- .file("src/main.rs", r#"
- extern crate bar;
- fn main() {
- bar::baz()
- }
- "#)
- .build();
- let _bar = project("bar")
- .file("Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/lib.rs", r#"
- pub fn baz() {}
- "#)
- .build();
-
- assert_that(foo.cargo("rustdoc").arg("-v").arg("-p").arg("bar")
- .arg("--").arg("--cfg=foo"),
- execs()
- .with_status(0)
- .with_stderr(format!("\
-[DOCUMENTING] bar v0.0.1 ([..])
-[RUNNING] `rustdoc --crate-name bar [..]bar[/]src[/]lib.rs \
- -o {dir}[/]target[/]doc \
- --cfg=foo \
- -L dependency={dir}[/]target[/]debug[/]deps`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-", dir = foo.root().display())));
-}
-
-
-#[test]
-fn rustdoc_same_name_documents_lib() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/main.rs", r#"
- fn main() {}
- "#)
- .file("src/lib.rs", r#" "#)
- .build();
-
- assert_that(p.cargo("rustdoc").arg("-v")
- .arg("--").arg("--cfg=foo"),
- execs()
- .with_status(0)
- .with_stderr(format!("\
-[DOCUMENTING] foo v0.0.1 ([..])
-[RUNNING] `rustdoc --crate-name foo src[/]lib.rs \
- -o {dir}[/]target[/]doc \
- --cfg=foo \
- -L dependency={dir}[/]target[/]debug[/]deps`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-", dir = p.root().display())));
-}
+++ /dev/null
-extern crate cargotest;
-extern crate hamcrest;
-
-use cargotest::support::{project, execs};
-use hamcrest::assert_that;
-
-#[test]
-fn parses_env() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("doc").env("RUSTDOCFLAGS", "--cfg=foo").arg("-v"),
- execs().with_status(0)
- .with_stderr_contains("\
-[RUNNING] `rustdoc [..] --cfg=foo[..]`
-"));
-}
-
-#[test]
-fn parses_config() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/lib.rs", "")
- .file(".cargo/config", r#"
- [build]
- rustdocflags = ["--cfg", "foo"]
- "#)
- .build();
-
- assert_that(p.cargo("doc").arg("-v"),
- execs().with_status(0)
- .with_stderr_contains("\
-[RUNNING] `rustdoc [..] --cfg foo[..]`
-"));
-}
-
-#[test]
-fn bad_flags() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("doc").env("RUSTDOCFLAGS", "--bogus"),
- execs().with_status(101));
-}
-
-#[test]
-fn rerun() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("doc").env("RUSTDOCFLAGS", "--cfg=foo"),
- execs().with_status(0));
- assert_that(p.cargo("doc").env("RUSTDOCFLAGS", "--cfg=foo"),
- execs().with_status(0).with_stderr("\
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
- assert_that(p.cargo("doc").env("RUSTDOCFLAGS", "--cfg=bar"),
- execs().with_status(0).with_stderr("\
-[DOCUMENTING] foo v0.0.1 ([..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-}
-
-#[test]
-fn rustdocflags_passed_to_rustdoc_through_cargo_test() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- "#)
- .file("src/lib.rs", r#"
- //! ```
- //! assert!(cfg!(do_not_choke));
- //! ```
- "#)
- .build();
-
- assert_that(p.cargo("test").arg("--doc").env("RUSTDOCFLAGS", "--cfg do_not_choke"),
- execs().with_status(0));
-}
-
-#[test]
-fn rustdocflags_passed_to_rustdoc_through_cargo_test_only_once() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- "#)
- .file("src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("test").arg("--doc").env("RUSTDOCFLAGS", "--markdown-no-toc"),
- execs().with_status(0));
-}
+++ /dev/null
-extern crate cargotest;
-extern crate hamcrest;
-
-use std::io::Write;
-use std::fs::{self, File};
-
-use cargotest::rustc_host;
-use cargotest::support::{project, project_in_home, execs, paths};
-use hamcrest::assert_that;
-
-#[test]
-fn env_rustflags_normal_source() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- "#)
- .file("src/lib.rs", "")
- .file("src/bin/a.rs", "fn main() {}")
- .file("examples/b.rs", "fn main() {}")
- .file("tests/c.rs", "#[test] fn f() { }")
- .file("benches/d.rs", r#"
- #![feature(test)]
- extern crate test;
- #[bench] fn run1(_ben: &mut test::Bencher) { }"#)
- .build();
-
- // Use RUSTFLAGS to pass an argument that will generate an error
- assert_that(p.cargo("build").env("RUSTFLAGS", "-Z bogus")
- .arg("--lib"),
- execs().with_status(101));
- assert_that(p.cargo("build").env("RUSTFLAGS", "-Z bogus")
- .arg("--bin=a"),
- execs().with_status(101));
- assert_that(p.cargo("build").env("RUSTFLAGS", "-Z bogus")
- .arg("--example=b"),
- execs().with_status(101));
- assert_that(p.cargo("test").env("RUSTFLAGS", "-Z bogus"),
- execs().with_status(101));
- assert_that(p.cargo("bench").env("RUSTFLAGS", "-Z bogus"),
- execs().with_status(101));
-}
-
-#[test]
-fn env_rustflags_build_script() {
- // RUSTFLAGS should be passed to rustc for build scripts
- // when --target is not specified.
- // In this test if --cfg foo is passed the build will fail.
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- build = "build.rs"
- "#)
- .file("src/lib.rs", "")
- .file("build.rs", r#"
- fn main() { }
- #[cfg(not(foo))]
- fn main() { }
- "#)
- .build();
-
- assert_that(p.cargo("build").env("RUSTFLAGS", "--cfg foo"),
- execs().with_status(0));
-}
-
-#[test]
-fn env_rustflags_build_script_dep() {
- // RUSTFLAGS should be passed to rustc for build scripts
- // when --target is not specified.
- // In this test if --cfg foo is not passed the build will fail.
- let foo = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- build = "build.rs"
-
- [build-dependencies.bar]
- path = "../bar"
- "#)
- .file("src/lib.rs", "")
- .file("build.rs", r#"
- fn main() { }
- "#)
- .build();
- let _bar = project("bar")
- .file("Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- "#)
- .file("src/lib.rs", r#"
- fn bar() { }
- #[cfg(not(foo))]
- fn bar() { }
- "#)
- .build();
-
- assert_that(foo.cargo("build").env("RUSTFLAGS", "--cfg foo"),
- execs().with_status(0));
-}
-
-#[test]
-fn env_rustflags_plugin() {
- // RUSTFLAGS should be passed to rustc for plugins
- // when --target is not specified.
- // In this test if --cfg foo is not passed the build will fail.
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
-
- [lib]
- name = "foo"
- plugin = true
- "#)
- .file("src/lib.rs", r#"
- fn main() { }
- #[cfg(not(foo))]
- fn main() { }
- "#)
- .build();
-
- assert_that(p.cargo("build").env("RUSTFLAGS", "--cfg foo"),
- execs().with_status(0));
-}
-
-#[test]
-fn env_rustflags_plugin_dep() {
- // RUSTFLAGS should be passed to rustc for plugins
- // when --target is not specified.
- // In this test if --cfg foo is not passed the build will fail.
- let foo = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
-
- [lib]
- name = "foo"
- plugin = true
-
- [dependencies.bar]
- path = "../bar"
- "#)
- .file("src/lib.rs", r#"
- fn foo() { }
- "#)
- .build();
- let _bar = project("bar")
- .file("Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
-
- [lib]
- name = "bar"
- "#)
- .file("src/lib.rs", r#"
- fn bar() { }
- #[cfg(not(foo))]
- fn bar() { }
- "#)
- .build();
-
- assert_that(foo.cargo("build").env("RUSTFLAGS", "--cfg foo"),
- execs().with_status(0));
-}
-
-#[test]
-fn env_rustflags_normal_source_with_target() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- "#)
- .file("src/lib.rs", "")
- .file("src/bin/a.rs", "fn main() {}")
- .file("examples/b.rs", "fn main() {}")
- .file("tests/c.rs", "#[test] fn f() { }")
- .file("benches/d.rs", r#"
- #![feature(test)]
- extern crate test;
- #[bench] fn run1(_ben: &mut test::Bencher) { }"#)
- .build();
-
- let host = &rustc_host();
-
- // Use RUSTFLAGS to pass an argument that will generate an error
- assert_that(p.cargo("build").env("RUSTFLAGS", "-Z bogus")
- .arg("--lib").arg("--target").arg(host),
- execs().with_status(101));
- assert_that(p.cargo("build").env("RUSTFLAGS", "-Z bogus")
- .arg("--bin=a").arg("--target").arg(host),
- execs().with_status(101));
- assert_that(p.cargo("build").env("RUSTFLAGS", "-Z bogus")
- .arg("--example=b").arg("--target").arg(host),
- execs().with_status(101));
- assert_that(p.cargo("test").env("RUSTFLAGS", "-Z bogus")
- .arg("--target").arg(host),
- execs().with_status(101));
- assert_that(p.cargo("bench").env("RUSTFLAGS", "-Z bogus")
- .arg("--target").arg(host),
- execs().with_status(101));
-}
-
-#[test]
-fn env_rustflags_build_script_with_target() {
- // RUSTFLAGS should not be passed to rustc for build scripts
- // when --target is specified.
- // In this test if --cfg foo is passed the build will fail.
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- build = "build.rs"
- "#)
- .file("src/lib.rs", "")
- .file("build.rs", r#"
- fn main() { }
- #[cfg(foo)]
- fn main() { }
- "#)
- .build();
-
- let host = rustc_host();
- assert_that(p.cargo("build").env("RUSTFLAGS", "--cfg foo")
- .arg("--target").arg(host),
- execs().with_status(0));
-}
-
-#[test]
-fn env_rustflags_build_script_dep_with_target() {
- // RUSTFLAGS should not be passed to rustc for build scripts
- // when --target is specified.
- // In this test if --cfg foo is passed the build will fail.
- let foo = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- build = "build.rs"
-
- [build-dependencies.bar]
- path = "../bar"
- "#)
- .file("src/lib.rs", "")
- .file("build.rs", r#"
- fn main() { }
- "#)
- .build();
- let _bar = project("bar")
- .file("Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- "#)
- .file("src/lib.rs", r#"
- fn bar() { }
- #[cfg(foo)]
- fn bar() { }
- "#)
- .build();
-
- let host = rustc_host();
- assert_that(foo.cargo("build").env("RUSTFLAGS", "--cfg foo")
- .arg("--target").arg(host),
- execs().with_status(0));
-}
-
-#[test]
-fn env_rustflags_plugin_with_target() {
- // RUSTFLAGS should not be passed to rustc for plugins
- // when --target is specified.
- // In this test if --cfg foo is passed the build will fail.
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
-
- [lib]
- name = "foo"
- plugin = true
- "#)
- .file("src/lib.rs", r#"
- fn main() { }
- #[cfg(foo)]
- fn main() { }
- "#)
- .build();
-
- let host = rustc_host();
- assert_that(p.cargo("build").env("RUSTFLAGS", "--cfg foo")
- .arg("--target").arg(host),
- execs().with_status(0));
-}
-
-#[test]
-fn env_rustflags_plugin_dep_with_target() {
- // RUSTFLAGS should not be passed to rustc for plugins
- // when --target is specified.
- // In this test if --cfg foo is passed the build will fail.
- let foo = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
-
- [lib]
- name = "foo"
- plugin = true
-
- [dependencies.bar]
- path = "../bar"
- "#)
- .file("src/lib.rs", r#"
- fn foo() { }
- "#)
- .build();
- let _bar = project("bar")
- .file("Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
-
- [lib]
- name = "bar"
- "#)
- .file("src/lib.rs", r#"
- fn bar() { }
- #[cfg(foo)]
- fn bar() { }
- "#)
- .build();
-
- let host = rustc_host();
- assert_that(foo.cargo("build").env("RUSTFLAGS", "--cfg foo")
- .arg("--target").arg(host),
- execs().with_status(0));
-}
-
-#[test]
-fn env_rustflags_recompile() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- "#)
- .file("src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0));
- // Setting RUSTFLAGS forces a recompile
- assert_that(p.cargo("build").env("RUSTFLAGS", "-Z bogus"),
- execs().with_status(101));
-}
-
-#[test]
-fn env_rustflags_recompile2() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- "#)
- .file("src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build").env("RUSTFLAGS", "--cfg foo"),
- execs().with_status(0));
- // Setting RUSTFLAGS forces a recompile
- assert_that(p.cargo("build").env("RUSTFLAGS", "-Z bogus"),
- execs().with_status(101));
-}
-
-#[test]
-fn env_rustflags_no_recompile() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- "#)
- .file("src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build").env("RUSTFLAGS", "--cfg foo"),
- execs().with_status(0));
- assert_that(p.cargo("build").env("RUSTFLAGS", "--cfg foo"),
- execs().with_stdout("").with_status(0));
-}
-
-#[test]
-fn build_rustflags_normal_source() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- "#)
- .file("src/lib.rs", "")
- .file("src/bin/a.rs", "fn main() {}")
- .file("examples/b.rs", "fn main() {}")
- .file("tests/c.rs", "#[test] fn f() { }")
- .file("benches/d.rs", r#"
- #![feature(test)]
- extern crate test;
- #[bench] fn run1(_ben: &mut test::Bencher) { }"#)
- .file(".cargo/config", r#"
- [build]
- rustflags = ["-Z", "bogus"]
- "#)
- .build();
-
- assert_that(p.cargo("build")
- .arg("--lib"),
- execs().with_status(101));
- assert_that(p.cargo("build")
- .arg("--bin=a"),
- execs().with_status(101));
- assert_that(p.cargo("build")
- .arg("--example=b"),
- execs().with_status(101));
- assert_that(p.cargo("test"),
- execs().with_status(101));
- assert_that(p.cargo("bench"),
- execs().with_status(101));
-}
-
-#[test]
-fn build_rustflags_build_script() {
- // RUSTFLAGS should be passed to rustc for build scripts
- // when --target is not specified.
- // In this test if --cfg foo is passed the build will fail.
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- build = "build.rs"
- "#)
- .file("src/lib.rs", "")
- .file("build.rs", r#"
- fn main() { }
- #[cfg(not(foo))]
- fn main() { }
- "#)
- .file(".cargo/config", r#"
- [build]
- rustflags = ["--cfg", "foo"]
- "#)
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0));
-}
-
-#[test]
-fn build_rustflags_build_script_dep() {
- // RUSTFLAGS should be passed to rustc for build scripts
- // when --target is not specified.
- // In this test if --cfg foo is not passed the build will fail.
- let foo = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- build = "build.rs"
-
- [build-dependencies.bar]
- path = "../bar"
- "#)
- .file("src/lib.rs", "")
- .file("build.rs", r#"
- fn main() { }
- "#)
- .file(".cargo/config", r#"
- [build]
- rustflags = ["--cfg", "foo"]
- "#)
- .build();
- let _bar = project("bar")
- .file("Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- "#)
- .file("src/lib.rs", r#"
- fn bar() { }
- #[cfg(not(foo))]
- fn bar() { }
- "#)
- .build();
-
- assert_that(foo.cargo("build"),
- execs().with_status(0));
-}
-
-#[test]
-fn build_rustflags_plugin() {
- // RUSTFLAGS should be passed to rustc for plugins
- // when --target is not specified.
- // In this test if --cfg foo is not passed the build will fail.
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
-
- [lib]
- name = "foo"
- plugin = true
- "#)
- .file("src/lib.rs", r#"
- fn main() { }
- #[cfg(not(foo))]
- fn main() { }
- "#)
- .file(".cargo/config", r#"
- [build]
- rustflags = ["--cfg", "foo"]
- "#)
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0));
-}
-
-#[test]
-fn build_rustflags_plugin_dep() {
- // RUSTFLAGS should be passed to rustc for plugins
- // when --target is not specified.
- // In this test if --cfg foo is not passed the build will fail.
- let foo = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
-
- [lib]
- name = "foo"
- plugin = true
-
- [dependencies.bar]
- path = "../bar"
- "#)
- .file("src/lib.rs", r#"
- fn foo() { }
- "#)
- .file(".cargo/config", r#"
- [build]
- rustflags = ["--cfg", "foo"]
- "#)
- .build();
- let _bar = project("bar")
- .file("Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
-
- [lib]
- name = "bar"
- "#)
- .file("src/lib.rs", r#"
- fn bar() { }
- #[cfg(not(foo))]
- fn bar() { }
- "#)
- .build();
-
- assert_that(foo.cargo("build"),
- execs().with_status(0));
-}
-
-#[test]
-fn build_rustflags_normal_source_with_target() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- "#)
- .file("src/lib.rs", "")
- .file("src/bin/a.rs", "fn main() {}")
- .file("examples/b.rs", "fn main() {}")
- .file("tests/c.rs", "#[test] fn f() { }")
- .file("benches/d.rs", r#"
- #![feature(test)]
- extern crate test;
- #[bench] fn run1(_ben: &mut test::Bencher) { }"#)
- .file(".cargo/config", r#"
- [build]
- rustflags = ["-Z", "bogus"]
- "#)
- .build();
-
- let ref host = rustc_host();
-
- // Use RUSTFLAGS to pass an argument that will generate an error
- assert_that(p.cargo("build")
- .arg("--lib").arg("--target").arg(host),
- execs().with_status(101));
- assert_that(p.cargo("build")
- .arg("--bin=a").arg("--target").arg(host),
- execs().with_status(101));
- assert_that(p.cargo("build")
- .arg("--example=b").arg("--target").arg(host),
- execs().with_status(101));
- assert_that(p.cargo("test")
- .arg("--target").arg(host),
- execs().with_status(101));
- assert_that(p.cargo("bench")
- .arg("--target").arg(host),
- execs().with_status(101));
-}
-
-#[test]
-fn build_rustflags_build_script_with_target() {
- // RUSTFLAGS should not be passed to rustc for build scripts
- // when --target is specified.
- // In this test if --cfg foo is passed the build will fail.
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- build = "build.rs"
- "#)
- .file("src/lib.rs", "")
- .file("build.rs", r#"
- fn main() { }
- #[cfg(foo)]
- fn main() { }
- "#)
- .file(".cargo/config", r#"
- [build]
- rustflags = ["--cfg", "foo"]
- "#)
- .build();
-
- let host = rustc_host();
- assert_that(p.cargo("build")
- .arg("--target").arg(host),
- execs().with_status(0));
-}
-
-#[test]
-fn build_rustflags_build_script_dep_with_target() {
- // RUSTFLAGS should not be passed to rustc for build scripts
- // when --target is specified.
- // In this test if --cfg foo is passed the build will fail.
- let foo = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- build = "build.rs"
-
- [build-dependencies.bar]
- path = "../bar"
- "#)
- .file("src/lib.rs", "")
- .file("build.rs", r#"
- fn main() { }
- "#)
- .file(".cargo/config", r#"
- [build]
- rustflags = ["--cfg", "foo"]
- "#)
- .build();
- let _bar = project("bar")
- .file("Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- "#)
- .file("src/lib.rs", r#"
- fn bar() { }
- #[cfg(foo)]
- fn bar() { }
- "#)
- .build();
-
- let host = rustc_host();
- assert_that(foo.cargo("build")
- .arg("--target").arg(host),
- execs().with_status(0));
-}
-
-#[test]
-fn build_rustflags_plugin_with_target() {
- // RUSTFLAGS should not be passed to rustc for plugins
- // when --target is specified.
- // In this test if --cfg foo is passed the build will fail.
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
-
- [lib]
- name = "foo"
- plugin = true
- "#)
- .file("src/lib.rs", r#"
- fn main() { }
- #[cfg(foo)]
- fn main() { }
- "#)
- .file(".cargo/config", r#"
- [build]
- rustflags = ["--cfg", "foo"]
- "#)
- .build();
-
- let host = rustc_host();
- assert_that(p.cargo("build")
- .arg("--target").arg(host),
- execs().with_status(0));
-}
-
-#[test]
-fn build_rustflags_plugin_dep_with_target() {
- // RUSTFLAGS should not be passed to rustc for plugins
- // when --target is specified.
- // In this test if --cfg foo is passed the build will fail.
- let foo = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
-
- [lib]
- name = "foo"
- plugin = true
-
- [dependencies.bar]
- path = "../bar"
- "#)
- .file("src/lib.rs", r#"
- fn foo() { }
- "#)
- .file(".cargo/config", r#"
- [build]
- rustflags = ["--cfg", "foo"]
- "#)
- .build();
- let _bar = project("bar")
- .file("Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
-
- [lib]
- name = "bar"
- "#)
- .file("src/lib.rs", r#"
- fn bar() { }
- #[cfg(foo)]
- fn bar() { }
- "#)
- .build();
-
- let host = rustc_host();
- assert_that(foo.cargo("build")
- .arg("--target").arg(host),
- execs().with_status(0));
-}
-
-#[test]
-fn build_rustflags_recompile() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- "#)
- .file("src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0));
-
- // Setting RUSTFLAGS forces a recompile
- let config = r#"
- [build]
- rustflags = ["-Z", "bogus"]
- "#;
- let config_file = paths::root().join("foo/.cargo/config");
- fs::create_dir_all(config_file.parent().unwrap()).unwrap();
- let mut config_file = File::create(config_file).unwrap();
- config_file.write_all(config.as_bytes()).unwrap();
-
- assert_that(p.cargo("build"),
- execs().with_status(101));
-}
-
-#[test]
-fn build_rustflags_recompile2() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- "#)
- .file("src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build").env("RUSTFLAGS", "--cfg foo"),
- execs().with_status(0));
-
- // Setting RUSTFLAGS forces a recompile
- let config = r#"
- [build]
- rustflags = ["-Z", "bogus"]
- "#;
- let config_file = paths::root().join("foo/.cargo/config");
- fs::create_dir_all(config_file.parent().unwrap()).unwrap();
- let mut config_file = File::create(config_file).unwrap();
- config_file.write_all(config.as_bytes()).unwrap();
-
- assert_that(p.cargo("build"),
- execs().with_status(101));
-}
-
-#[test]
-fn build_rustflags_no_recompile() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- "#)
- .file("src/lib.rs", "")
- .file(".cargo/config", r#"
- [build]
- rustflags = ["--cfg", "foo"]
- "#)
- .build();
-
- assert_that(p.cargo("build").env("RUSTFLAGS", "--cfg foo"),
- execs().with_status(0));
- assert_that(p.cargo("build").env("RUSTFLAGS", "--cfg foo"),
- execs().with_stdout("").with_status(0));
-}
-
-#[test]
-fn build_rustflags_with_home_config() {
- // We need a config file inside the home directory
- let home = paths::home();
- let home_config = home.join(".cargo");
- fs::create_dir(&home_config).unwrap();
- File::create(&home_config.join("config")).unwrap().write_all(br#"
- [build]
- rustflags = ["-Cllvm-args=-x86-asm-syntax=intel"]
- "#).unwrap();
-
- // And we need the project to be inside the home directory
- // so the walking process finds the home project twice.
- let p = project_in_home("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- "#)
- .file("src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(0));
-}
-
-#[test]
-fn target_rustflags_normal_source() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- "#)
- .file("src/lib.rs", "")
- .file("src/bin/a.rs", "fn main() {}")
- .file("examples/b.rs", "fn main() {}")
- .file("tests/c.rs", "#[test] fn f() { }")
- .file("benches/d.rs", r#"
- #![feature(test)]
- extern crate test;
- #[bench] fn run1(_ben: &mut test::Bencher) { }"#)
- .file(".cargo/config", &format!("
- [target.{}]
- rustflags = [\"-Z\", \"bogus\"]
- ", rustc_host()))
- .build();
-
- assert_that(p.cargo("build")
- .arg("--lib"),
- execs().with_status(101));
- assert_that(p.cargo("build")
- .arg("--bin=a"),
- execs().with_status(101));
- assert_that(p.cargo("build")
- .arg("--example=b"),
- execs().with_status(101));
- assert_that(p.cargo("test"),
- execs().with_status(101));
- assert_that(p.cargo("bench"),
- execs().with_status(101));
-}
-
-// target.{}.rustflags takes precedence over build.rustflags
-#[test]
-fn target_rustflags_precedence() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- "#)
- .file("src/lib.rs", "")
- .file(".cargo/config", &format!("
- [build]
- rustflags = [\"--cfg\", \"foo\"]
-
- [target.{}]
- rustflags = [\"-Z\", \"bogus\"]
- ", rustc_host()))
- .build();
-
- assert_that(p.cargo("build")
- .arg("--lib"),
- execs().with_status(101));
- assert_that(p.cargo("build")
- .arg("--bin=a"),
- execs().with_status(101));
- assert_that(p.cargo("build")
- .arg("--example=b"),
- execs().with_status(101));
- assert_that(p.cargo("test"),
- execs().with_status(101));
- assert_that(p.cargo("bench"),
- execs().with_status(101));
-}
-
-#[test]
-fn cfg_rustflags_normal_source() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- "#)
- .file("src/lib.rs", "pub fn t() {}")
- .file("src/bin/a.rs", "fn main() {}")
- .file("examples/b.rs", "fn main() {}")
- .file("tests/c.rs", "#[test] fn f() { }")
- .file(".cargo/config", &format!(r#"
- [target.'cfg({})']
- rustflags = ["--cfg", "bar"]
- "#, if rustc_host().contains("-windows-") {"windows"} else {"not(windows)"}))
- .build();
-
- assert_that(p.cargo("build").arg("--lib").arg("-v"),
- execs().with_status(0).with_stderr("\
-[COMPILING] foo v0.0.1 ([..])
-[RUNNING] `rustc [..] --cfg bar[..]`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-
- assert_that(p.cargo("build").arg("--bin=a").arg("-v"),
- execs().with_status(0).with_stderr("\
-[COMPILING] foo v0.0.1 ([..])
-[RUNNING] `rustc [..] --cfg bar[..]`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-
- assert_that(p.cargo("build").arg("--example=b").arg("-v"),
- execs().with_status(0).with_stderr("\
-[COMPILING] foo v0.0.1 ([..])
-[RUNNING] `rustc [..] --cfg bar[..]`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-
- assert_that(p.cargo("test").arg("--no-run").arg("-v"),
- execs().with_status(0).with_stderr("\
-[COMPILING] foo v0.0.1 ([..])
-[RUNNING] `rustc [..] --cfg bar[..]`
-[RUNNING] `rustc [..] --cfg bar[..]`
-[RUNNING] `rustc [..] --cfg bar[..]`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-
- assert_that(p.cargo("bench").arg("--no-run").arg("-v"),
- execs().with_status(0).with_stderr("\
-[COMPILING] foo v0.0.1 ([..])
-[RUNNING] `rustc [..] --cfg bar[..]`
-[RUNNING] `rustc [..] --cfg bar[..]`
-[RUNNING] `rustc [..] --cfg bar[..]`
-[FINISHED] release [optimized] target(s) in [..]
-"));
-
-}
-
-// target.'cfg(...)'.rustflags takes precedence over build.rustflags
-#[test]
-fn cfg_rustflags_precedence() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- "#)
- .file("src/lib.rs", "pub fn t() {}")
- .file("src/bin/a.rs", "fn main() {}")
- .file("examples/b.rs", "fn main() {}")
- .file("tests/c.rs", "#[test] fn f() { }")
- .file(".cargo/config", &format!(r#"
- [build]
- rustflags = ["--cfg", "foo"]
-
- [target.'cfg({})']
- rustflags = ["--cfg", "bar"]
- "#, if rustc_host().contains("-windows-") { "windows" } else { "not(windows)" }))
- .build();
-
- assert_that(p.cargo("build").arg("--lib").arg("-v"),
- execs().with_status(0).with_stderr("\
-[COMPILING] foo v0.0.1 ([..])
-[RUNNING] `rustc [..] --cfg bar[..]`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-
- assert_that(p.cargo("build").arg("--bin=a").arg("-v"),
- execs().with_status(0).with_stderr("\
-[COMPILING] foo v0.0.1 ([..])
-[RUNNING] `rustc [..] --cfg bar[..]`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-
- assert_that(p.cargo("build").arg("--example=b").arg("-v"),
- execs().with_status(0).with_stderr("\
-[COMPILING] foo v0.0.1 ([..])
-[RUNNING] `rustc [..] --cfg bar[..]`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-
- assert_that(p.cargo("test").arg("--no-run").arg("-v"),
- execs().with_status(0).with_stderr("\
-[COMPILING] foo v0.0.1 ([..])
-[RUNNING] `rustc [..] --cfg bar[..]`
-[RUNNING] `rustc [..] --cfg bar[..]`
-[RUNNING] `rustc [..] --cfg bar[..]`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-
- assert_that(p.cargo("bench").arg("--no-run").arg("-v"),
- execs().with_status(0).with_stderr("\
-[COMPILING] foo v0.0.1 ([..])
-[RUNNING] `rustc [..] --cfg bar[..]`
-[RUNNING] `rustc [..] --cfg bar[..]`
-[RUNNING] `rustc [..] --cfg bar[..]`
-[FINISHED] release [optimized] target(s) in [..]
-"));
-
-}
-
-#[test]
-fn target_rustflags_string_and_array_form1() {
- let p1 = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- "#)
- .file("src/lib.rs", "")
- .file(".cargo/config", r#"
- [build]
- rustflags = ["--cfg", "foo"]
- "#)
- .build();
-
- assert_that(p1.cargo("build").arg("-v"),
- execs().with_status(0).with_stderr("\
-[COMPILING] foo v0.0.1 ([..])
-[RUNNING] `rustc [..] --cfg foo[..]`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-
- let p2 = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- "#)
- .file("src/lib.rs", "")
- .file(".cargo/config", r#"
- [build]
- rustflags = "--cfg foo"
- "#)
- .build();
-
- assert_that(p2.cargo("build").arg("-v"),
- execs().with_status(0).with_stderr("\
-[COMPILING] foo v0.0.1 ([..])
-[RUNNING] `rustc [..] --cfg foo[..]`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-
-}
-
-#[test]
-fn target_rustflags_string_and_array_form2() {
- let p1 = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- "#)
- .file(".cargo/config", &format!(r#"
- [target.{}]
- rustflags = ["--cfg", "foo"]
- "#, rustc_host()))
- .file("src/lib.rs", "")
- .build();
-
- assert_that(p1.cargo("build").arg("-v"),
- execs().with_status(0).with_stderr("\
-[COMPILING] foo v0.0.1 ([..])
-[RUNNING] `rustc [..] --cfg foo[..]`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-
- let p2 = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- "#)
- .file(".cargo/config", &format!(r#"
- [target.{}]
- rustflags = "--cfg foo"
- "#, rustc_host()))
- .file("src/lib.rs", "")
- .build();
-
- assert_that(p2.cargo("build").arg("-v"),
- execs().with_status(0).with_stderr("\
-[COMPILING] foo v0.0.1 ([..])
-[RUNNING] `rustc [..] --cfg foo[..]`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-}
-
-#[test]
-fn two_matching_in_config() {
- let p1 = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- "#)
- .file(".cargo/config", r#"
- [target.'cfg(unix)']
- rustflags = ["--cfg", 'foo="a"']
- [target.'cfg(windows)']
- rustflags = ["--cfg", 'foo="a"']
- [target.'cfg(target_pointer_width = "32")']
- rustflags = ["--cfg", 'foo="b"']
- [target.'cfg(target_pointer_width = "64")']
- rustflags = ["--cfg", 'foo="b"']
- "#)
- .file("src/main.rs", r#"
- fn main() {
- if cfg!(foo = "a") {
- println!("a");
- } else if cfg!(foo = "b") {
- println!("b");
- } else {
- panic!()
- }
- }
- "#)
- .build();
-
- assert_that(p1.cargo("run"), execs().with_status(0));
- assert_that(p1.cargo("build"),
- execs().with_status(0).with_stderr("\
-[FINISHED] [..]
-"));
-}
+++ /dev/null
-extern crate cargo;
-extern crate cargotest;
-extern crate hamcrest;
-extern crate url;
-
-use std::fs::{self, File};
-use std::io::prelude::*;
-use std::path::PathBuf;
-
-use cargo::util::ProcessBuilder;
-use cargotest::support::execs;
-use cargotest::support::git::repo;
-use cargotest::support::paths;
-use hamcrest::assert_that;
-use url::Url;
-
-fn registry_path() -> PathBuf { paths::root().join("registry") }
-fn registry() -> Url { Url::from_file_path(&*registry_path()).ok().unwrap() }
-fn api_path() -> PathBuf { paths::root().join("api") }
-fn api() -> Url { Url::from_file_path(&*api_path()).ok().unwrap() }
-
-fn setup() {
- let config = paths::root().join(".cargo/config");
- fs::create_dir_all(config.parent().unwrap()).unwrap();
- fs::create_dir_all(&api_path().join("api/v1")).unwrap();
-
- let _ = repo(®istry_path())
- .file("config.json", &format!(r#"{{
- "dl": "{0}",
- "api": "{0}"
- }}"#, api()))
- .build();
-}
-
-fn cargo_process(s: &str) -> ProcessBuilder {
- let mut b = cargotest::cargo_process();
- b.arg(s);
- b
-}
-
-#[test]
-fn simple() {
- setup();
-
- let contents = r#"{
- "crates": [{
- "created_at": "2014-11-16T20:17:35Z",
- "description": "Design by contract style assertions for Rust",
- "documentation": null,
- "downloads": 2,
- "homepage": null,
- "id": "hoare",
- "keywords": [],
- "license": null,
- "links": {
- "owners": "/api/v1/crates/hoare/owners",
- "reverse_dependencies": "/api/v1/crates/hoare/reverse_dependencies",
- "version_downloads": "/api/v1/crates/hoare/downloads",
- "versions": "/api/v1/crates/hoare/versions"
- },
- "max_version": "0.1.1",
- "name": "hoare",
- "repository": "https://github.com/nick29581/libhoare",
- "updated_at": "2014-11-20T21:49:21Z",
- "versions": null
- }],
- "meta": {
- "total": 1
- }
- }"#;
- let base = api_path().join("api/v1/crates");
-
- // Older versions of curl don't peel off query parameters when looking for
- // filenames, so just make both files.
- //
- // On windows, though, `?` is an invalid character, but we always build curl
- // from source there anyway!
- File::create(&base).unwrap().write_all(contents.as_bytes()).unwrap();
- if !cfg!(windows) {
- File::create(&base.with_file_name("crates?q=postgres&per_page=10")).unwrap()
- .write_all(contents.as_bytes()).unwrap();
- }
-
- assert_that(cargo_process("search").arg("postgres")
- .arg("--index").arg(registry().to_string()),
- execs().with_status(0)
- .with_stdout_contains("\
-hoare = \"0.1.1\" # Design by contract style assertions for Rust"));
-}
-
-// TODO: Deprecated
-// remove once it has been decided '--host' can be safely removed
-#[test]
-fn simple_with_host() {
- setup();
-
- let contents = r#"{
- "crates": [{
- "created_at": "2014-11-16T20:17:35Z",
- "description": "Design by contract style assertions for Rust",
- "documentation": null,
- "downloads": 2,
- "homepage": null,
- "id": "hoare",
- "keywords": [],
- "license": null,
- "links": {
- "owners": "/api/v1/crates/hoare/owners",
- "reverse_dependencies": "/api/v1/crates/hoare/reverse_dependencies",
- "version_downloads": "/api/v1/crates/hoare/downloads",
- "versions": "/api/v1/crates/hoare/versions"
- },
- "max_version": "0.1.1",
- "name": "hoare",
- "repository": "https://github.com/nick29581/libhoare",
- "updated_at": "2014-11-20T21:49:21Z",
- "versions": null
- }],
- "meta": {
- "total": 1
- }
- }"#;
- let base = api_path().join("api/v1/crates");
-
- // Older versions of curl don't peel off query parameters when looking for
- // filenames, so just make both files.
- //
- // On windows, though, `?` is an invalid character, but we always build curl
- // from source there anyway!
- File::create(&base).unwrap().write_all(contents.as_bytes()).unwrap();
- if !cfg!(windows) {
- File::create(&base.with_file_name("crates?q=postgres&per_page=10")).unwrap()
- .write_all(contents.as_bytes()).unwrap();
- }
-
- assert_that(cargo_process("search").arg("postgres")
- .arg("--host").arg(registry().to_string()),
- execs().with_status(0)
- .with_stderr(&format!("\
-[WARNING] The flag '--host' is no longer valid.
-
-Previous versions of Cargo accepted this flag, but it is being
-deprecated. The flag is being renamed to 'index', as the flag
-wants the location of the index in which to search. Please
-use '--index' instead.
-
-This will soon become a hard error, so it's either recommended
-to update to a fixed version or contact the upstream maintainer
-about this warning.
-[UPDATING] registry `{reg}`
-",
- reg = registry()))
- .with_stdout_contains("\
-hoare = \"0.1.1\" # Design by contract style assertions for Rust"));
-}
-
-// TODO: Deprecated
-// remove once it has been decided '--host' can be safely removed
-#[test]
-fn simple_with_index_and_host() {
- setup();
-
- let contents = r#"{
- "crates": [{
- "created_at": "2014-11-16T20:17:35Z",
- "description": "Design by contract style assertions for Rust",
- "documentation": null,
- "downloads": 2,
- "homepage": null,
- "id": "hoare",
- "keywords": [],
- "license": null,
- "links": {
- "owners": "/api/v1/crates/hoare/owners",
- "reverse_dependencies": "/api/v1/crates/hoare/reverse_dependencies",
- "version_downloads": "/api/v1/crates/hoare/downloads",
- "versions": "/api/v1/crates/hoare/versions"
- },
- "max_version": "0.1.1",
- "name": "hoare",
- "repository": "https://github.com/nick29581/libhoare",
- "updated_at": "2014-11-20T21:49:21Z",
- "versions": null
- }],
- "meta": {
- "total": 1
- }
- }"#;
- let base = api_path().join("api/v1/crates");
-
- // Older versions of curl don't peel off query parameters when looking for
- // filenames, so just make both files.
- //
- // On windows, though, `?` is an invalid character, but we always build curl
- // from source there anyway!
- File::create(&base).unwrap().write_all(contents.as_bytes()).unwrap();
- if !cfg!(windows) {
- File::create(&base.with_file_name("crates?q=postgres&per_page=10")).unwrap()
- .write_all(contents.as_bytes()).unwrap();
- }
-
- assert_that(cargo_process("search").arg("postgres")
- .arg("--index").arg(registry().to_string())
- .arg("--host").arg(registry().to_string()),
- execs().with_status(0)
- .with_stderr(&format!("\
-[WARNING] The flag '--host' is no longer valid.
-
-Previous versions of Cargo accepted this flag, but it is being
-deprecated. The flag is being renamed to 'index', as the flag
-wants the location of the index in which to search. Please
-use '--index' instead.
-
-This will soon become a hard error, so it's either recommended
-to update to a fixed version or contact the upstream maintainer
-about this warning.
-[UPDATING] registry `{reg}`
-",
- reg = registry()))
- .with_stdout_contains("\
-hoare = \"0.1.1\" # Design by contract style assertions for Rust"));
-}
-
-#[test]
-fn multiple_query_params() {
- setup();
-
- let contents = r#"{
- "crates": [{
- "created_at": "2014-11-16T20:17:35Z",
- "description": "Design by contract style assertions for Rust",
- "documentation": null,
- "downloads": 2,
- "homepage": null,
- "id": "hoare",
- "keywords": [],
- "license": null,
- "links": {
- "owners": "/api/v1/crates/hoare/owners",
- "reverse_dependencies": "/api/v1/crates/hoare/reverse_dependencies",
- "version_downloads": "/api/v1/crates/hoare/downloads",
- "versions": "/api/v1/crates/hoare/versions"
- },
- "max_version": "0.1.1",
- "name": "hoare",
- "repository": "https://github.com/nick29581/libhoare",
- "updated_at": "2014-11-20T21:49:21Z",
- "versions": null
- }],
- "meta": {
- "total": 1
- }
- }"#;
- let base = api_path().join("api/v1/crates");
-
- // Older versions of curl don't peel off query parameters when looking for
- // filenames, so just make both files.
- //
- // On windows, though, `?` is an invalid character, but we always build curl
- // from source there anyway!
- File::create(&base).unwrap().write_all(contents.as_bytes()).unwrap();
- if !cfg!(windows) {
- File::create(&base.with_file_name("crates?q=postgres+sql&per_page=10")).unwrap()
- .write_all(contents.as_bytes()).unwrap();
- }
-
- assert_that(cargo_process("search").arg("postgres").arg("sql")
- .arg("--index").arg(registry().to_string()),
- execs().with_status(0)
- .with_stdout_contains("\
-hoare = \"0.1.1\" # Design by contract style assertions for Rust"));
-}
-
-#[test]
-fn help() {
- assert_that(cargo_process("search").arg("-h"),
- execs().with_status(0));
- assert_that(cargo_process("help").arg("search"),
- execs().with_status(0));
- // Ensure that help output goes to stdout, not stderr.
- assert_that(cargo_process("search").arg("--help"),
- execs().with_stderr(""));
- assert_that(cargo_process("search").arg("--help"),
- execs().with_stdout_contains("[..] --frozen [..]"));
-}
+++ /dev/null
-extern crate cargotest;
-extern crate git2;
-extern crate hamcrest;
-extern crate url;
-
-use std::env;
-use std::ffi::OsStr;
-use std::path::PathBuf;
-use std::process::Command;
-
-use cargotest::support::{execs, project};
-use cargotest::support::registry::Package;
-use cargotest::support::paths;
-use cargotest::support::git;
-use hamcrest::assert_that;
-
-use url::Url;
-
-fn find_index() -> PathBuf {
- let dir = paths::home().join(".cargo/registry/index");
- dir.read_dir().unwrap().next().unwrap().unwrap().path()
-}
-
-fn run_test(path_env: Option<&OsStr>) {
- const N: usize = 50;
-
- let foo = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- bar = "*"
- "#)
- .file("src/lib.rs", "")
- .build();
- Package::new("bar", "0.1.0").publish();
-
- assert_that(foo.cargo("build"),
- execs().with_status(0));
-
- let index = find_index();
- let path = paths::home().join("tmp");
- let url = Url::from_file_path(&path).unwrap().to_string();
- let repo = git2::Repository::init(&path).unwrap();
- let index = git2::Repository::open(&index).unwrap();
- let mut cfg = repo.config().unwrap();
- cfg.set_str("user.email", "foo@bar.com").unwrap();
- cfg.set_str("user.name", "Foo Bar").unwrap();
- let mut cfg = index.config().unwrap();
- cfg.set_str("user.email", "foo@bar.com").unwrap();
- cfg.set_str("user.name", "Foo Bar").unwrap();
-
- for _ in 0..N {
- git::commit(&repo);
- index.remote_anonymous(&url).unwrap()
- .fetch(&["refs/heads/master:refs/remotes/foo/master"],
- None,
- None).unwrap();
- }
- drop((repo, index));
- Package::new("bar", "0.1.1").publish();
-
- let before = find_index().join(".git/objects/pack")
- .read_dir().unwrap()
- .count();
- assert!(before > N);
-
- let mut cmd = foo.cargo("update");
- cmd.env("__CARGO_PACKFILE_LIMIT", "10");
- if let Some(path) = path_env {
- cmd.env("PATH", path);
- }
- cmd.env("RUST_LOG", "trace");
- assert_that(cmd, execs().with_status(0));
- let after = find_index().join(".git/objects/pack")
- .read_dir().unwrap()
- .count();
- assert!(after < before,
- "packfiles before: {}\n\
- packfiles after: {}", before, after);
-}
-
-#[test]
-fn use_git_gc() {
- if Command::new("git").arg("--version").output().is_err() {
- return
- }
- run_test(None);
-}
-
-#[test]
-// it looks like this test passes on some windows machines but not others,
-// notably not on AppVeyor's machines. Sounds like another but for another day.
-#[cfg_attr(windows, ignore)]
-fn avoid_using_git() {
- let path = env::var_os("PATH").unwrap_or_default();
- let mut paths = env::split_paths(&path).collect::<Vec<_>>();
- let idx = paths.iter().position(|p| {
- p.join("git").exists() || p.join("git.exe").exists()
- });
- match idx {
- Some(i) => { paths.remove(i); }
- None => return,
- }
- run_test(Some(&env::join_paths(&paths).unwrap()));
-}
+++ /dev/null
-extern crate cargo;
-extern crate cargotest;
-extern crate hamcrest;
-
-use std::fs::File;
-use std::io::prelude::*;
-use std::str;
-
-use cargotest::{sleep_ms, is_nightly, rustc_host};
-use cargotest::support::{project, execs, basic_bin_manifest, basic_lib_manifest, cargo_exe};
-use cargotest::support::paths::CargoPathExt;
-use cargotest::support::registry::Package;
-use hamcrest::{assert_that, existing_file, is_not};
-use cargo::util::process;
-
-#[test]
-fn cargo_test_simple() {
- let p = project("foo")
- .file("Cargo.toml", &basic_bin_manifest("foo"))
- .file("src/main.rs", r#"
- fn hello() -> &'static str {
- "hello"
- }
-
- pub fn main() {
- println!("{}", hello())
- }
-
- #[test]
- fn test_hello() {
- assert_eq!(hello(), "hello")
- }"#)
- .build();
-
- assert_that(p.cargo("build"), execs().with_status(0));
- assert_that(&p.bin("foo"), existing_file());
-
- assert_that(process(&p.bin("foo")),
- execs().with_status(0).with_stdout("hello\n"));
-
- assert_that(p.cargo("test"),
- execs().with_status(0).with_stderr(format!("\
-[COMPILING] foo v0.5.0 ({})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] target[/]debug[/]deps[/]foo-[..][EXE]", p.url()))
- .with_stdout_contains("test test_hello ... ok"));
-}
-
-#[test]
-fn cargo_test_release() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- authors = []
- version = "0.1.0"
-
- [dependencies]
- bar = { path = "bar" }
- "#)
- .file("src/lib.rs", r#"
- extern crate bar;
- pub fn foo() { bar::bar(); }
-
- #[test]
- fn test() { foo(); }
- "#)
- .file("tests/test.rs", r#"
- extern crate foo;
-
- #[test]
- fn test() { foo::foo(); }
- "#)
- .file("bar/Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
- "#)
- .file("bar/src/lib.rs", "pub fn bar() {}")
- .build();
-
- assert_that(p.cargo("test").arg("-v").arg("--release"),
- execs().with_status(0).with_stderr(format!("\
-[COMPILING] bar v0.0.1 ({dir}/bar)
-[RUNNING] [..] -C opt-level=3 [..]
-[COMPILING] foo v0.1.0 ({dir})
-[RUNNING] [..] -C opt-level=3 [..]
-[RUNNING] [..] -C opt-level=3 [..]
-[RUNNING] [..] -C opt-level=3 [..]
-[FINISHED] release [optimized] target(s) in [..]
-[RUNNING] `[..]target[/]release[/]deps[/]foo-[..][EXE]`
-[RUNNING] `[..]target[/]release[/]deps[/]test-[..][EXE]`
-[DOCTEST] foo
-[RUNNING] `rustdoc --test [..]lib.rs[..]`", dir = p.url()))
- .with_stdout_contains_n("test test ... ok", 2)
- .with_stdout_contains("running 0 tests"));
-}
-
-#[test]
-fn cargo_test_overflow_checks() {
- if !is_nightly() {
- return;
- }
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.5.0"
- authors = []
-
- [[bin]]
- name = "foo"
-
- [profile.release]
- overflow-checks = true
- "#)
- .file("src/foo.rs", r#"
- use std::panic;
- pub fn main() {
- let r = panic::catch_unwind(|| {
- [1, i32::max_value()].iter().sum::<i32>();
- });
- assert!(r.is_err());
- }"#)
- .build();
-
- assert_that(p.cargo("build").arg("--release"),
- execs().with_status(0));
- assert_that(&p.release_bin("foo"), existing_file());
-
- assert_that(process(&p.release_bin("foo")),
- execs().with_status(0).with_stdout(""));
-}
-
-#[test]
-fn cargo_test_verbose() {
- let p = project("foo")
- .file("Cargo.toml", &basic_bin_manifest("foo"))
- .file("src/main.rs", r#"
- fn main() {}
- #[test] fn test_hello() {}
- "#)
- .build();
-
- assert_that(p.cargo("test").arg("-v").arg("hello"),
- execs().with_status(0).with_stderr(format!("\
-[COMPILING] foo v0.5.0 ({url})
-[RUNNING] `rustc [..] src[/]main.rs [..]`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] `[..]target[/]debug[/]deps[/]foo-[..][EXE] hello`", url = p.url()))
- .with_stdout_contains("test test_hello ... ok"));
-}
-
-#[test]
-fn many_similar_names() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/lib.rs", "
- pub fn foo() {}
- #[test] fn lib_test() {}
- ")
- .file("src/main.rs", "
- extern crate foo;
- fn main() {}
- #[test] fn bin_test() { foo::foo() }
- ")
- .file("tests/foo.rs", r#"
- extern crate foo;
- #[test] fn test_test() { foo::foo() }
- "#)
- .build();
-
- let output = p.cargo("test").arg("-v").exec_with_output().unwrap();
- let output = str::from_utf8(&output.stdout).unwrap();
- assert!(output.contains("test bin_test"), "bin_test missing\n{}", output);
- assert!(output.contains("test lib_test"), "lib_test missing\n{}", output);
- assert!(output.contains("test test_test"), "test_test missing\n{}", output);
-}
-
-#[test]
-fn cargo_test_failing_test_in_bin() {
- let p = project("foo")
- .file("Cargo.toml", &basic_bin_manifest("foo"))
- .file("src/main.rs", r#"
- fn hello() -> &'static str {
- "hello"
- }
-
- pub fn main() {
- println!("{}", hello())
- }
-
- #[test]
- fn test_hello() {
- assert_eq!(hello(), "nope")
- }"#)
- .build();
-
- assert_that(p.cargo("build"), execs().with_status(0));
- assert_that(&p.bin("foo"), existing_file());
-
- assert_that(process(&p.bin("foo")),
- execs().with_status(0).with_stdout("hello\n"));
-
- assert_that(p.cargo("test"),
- execs().with_stderr(format!("\
-[COMPILING] foo v0.5.0 ({url})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] target[/]debug[/]deps[/]foo-[..][EXE]
-[ERROR] test failed, to rerun pass '--bin foo'", url = p.url()))
- .with_stdout_contains("
-running 1 test
-test test_hello ... FAILED
-
-failures:
-
----- test_hello stdout ----
-<tab>thread 'test_hello' panicked at 'assertion failed:[..]")
- .with_stdout_contains("[..]`(left == right)`[..]")
- .with_stdout_contains("[..]left: `\"hello\"`,[..]")
- .with_stdout_contains("[..]right: `\"nope\"`[..]")
- .with_stdout_contains("[..]src[/]main.rs:12[..]")
- .with_stdout_contains("\
-failures:
- test_hello
-")
- .with_status(101));
-}
-
-#[test]
-fn cargo_test_failing_test_in_test() {
- let p = project("foo")
- .file("Cargo.toml", &basic_bin_manifest("foo"))
- .file("src/main.rs", r#"
- pub fn main() {
- println!("hello");
- }"#)
- .file("tests/footest.rs", r#"
- #[test]
- fn test_hello() {
- assert!(false)
- }"#)
- .build();
-
- assert_that(p.cargo("build"), execs().with_status(0));
- assert_that(&p.bin("foo"), existing_file());
-
- assert_that(process(&p.bin("foo")),
- execs().with_status(0).with_stdout("hello\n"));
-
- assert_that(p.cargo("test"),
- execs().with_stderr(format!("\
-[COMPILING] foo v0.5.0 ({url})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] target[/]debug[/]deps[/]foo-[..][EXE]
-[RUNNING] target[/]debug[/]deps[/]footest-[..][EXE]
-[ERROR] test failed, to rerun pass '--test footest'", url = p.url()))
- .with_stdout_contains("running 0 tests")
- .with_stdout_contains("\
-running 1 test
-test test_hello ... FAILED
-
-failures:
-
----- test_hello stdout ----
-<tab>thread 'test_hello' panicked at 'assertion failed: false', \
- tests[/]footest.rs:4[..]
-")
- .with_stdout_contains("\
-failures:
- test_hello
-")
- .with_status(101));
-}
-
-#[test]
-fn cargo_test_failing_test_in_lib() {
- let p = project("foo")
- .file("Cargo.toml", &basic_lib_manifest("foo"))
- .file("src/lib.rs", r#"
- #[test]
- fn test_hello() {
- assert!(false)
- }"#)
- .build();
-
- assert_that(p.cargo("test"),
- execs().with_stderr(format!("\
-[COMPILING] foo v0.5.0 ({url})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] target[/]debug[/]deps[/]foo-[..][EXE]
-[ERROR] test failed, to rerun pass '--lib'", url = p.url()))
- .with_stdout_contains("\
-test test_hello ... FAILED
-
-failures:
-
----- test_hello stdout ----
-<tab>thread 'test_hello' panicked at 'assertion failed: false', \
- src[/]lib.rs:4[..]
-")
- .with_stdout_contains("\
-failures:
- test_hello
-")
- .with_status(101));
-}
-
-
-#[test]
-fn test_with_lib_dep() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [[bin]]
- name = "baz"
- path = "src/main.rs"
- "#)
- .file("src/lib.rs", r#"
- ///
- /// ```rust
- /// extern crate foo;
- /// fn main() {
- /// println!("{:?}", foo::foo());
- /// }
- /// ```
- ///
- pub fn foo(){}
- #[test] fn lib_test() {}
- "#)
- .file("src/main.rs", "
- #[allow(unused_extern_crates)]
- extern crate foo;
-
- fn main() {}
-
- #[test]
- fn bin_test() {}
- ")
- .build();
-
- assert_that(p.cargo("test"),
- execs().with_status(0).with_stderr(format!("\
-[COMPILING] foo v0.0.1 ({})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] target[/]debug[/]deps[/]foo-[..][EXE]
-[RUNNING] target[/]debug[/]deps[/]baz-[..][EXE]
-[DOCTEST] foo", p.url()))
- .with_stdout_contains("test lib_test ... ok")
- .with_stdout_contains("test bin_test ... ok")
- .with_stdout_contains_n("test [..] ... ok", 3));
-}
-
-#[test]
-fn test_with_deep_lib_dep() {
- let p = project("bar")
- .file("Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
-
- [dependencies.foo]
- path = "../foo"
- "#)
- .file("src/lib.rs", "
- #[cfg(test)]
- extern crate foo;
- /// ```
- /// bar::bar();
- /// ```
- pub fn bar() {}
-
- #[test]
- fn bar_test() {
- foo::foo();
- }
- ")
- .build();
- let _p2 = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/lib.rs", "
- pub fn foo() {}
-
- #[test]
- fn foo_test() {}
- ")
- .build();
-
- assert_that(p.cargo("test"),
- execs().with_status(0)
- .with_stderr(&format!("\
-[COMPILING] foo v0.0.1 ([..])
-[COMPILING] bar v0.0.1 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] target[..]
-[DOCTEST] bar", dir = p.url()))
- .with_stdout_contains("test bar_test ... ok")
- .with_stdout_contains_n("test [..] ... ok", 2));
-}
-
-#[test]
-fn external_test_explicit() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [[test]]
- name = "test"
- path = "src/test.rs"
- "#)
- .file("src/lib.rs", r#"
- pub fn get_hello() -> &'static str { "Hello" }
-
- #[test]
- fn internal_test() {}
- "#)
- .file("src/test.rs", r#"
- extern crate foo;
-
- #[test]
- fn external_test() { assert_eq!(foo::get_hello(), "Hello") }
- "#)
- .build();
-
- assert_that(p.cargo("test"),
- execs().with_status(0).with_stderr(format!("\
-[COMPILING] foo v0.0.1 ({})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] target[/]debug[/]deps[/]foo-[..][EXE]
-[RUNNING] target[/]debug[/]deps[/]test-[..][EXE]
-[DOCTEST] foo", p.url()))
- .with_stdout_contains("test internal_test ... ok")
- .with_stdout_contains("test external_test ... ok")
- .with_stdout_contains("running 0 tests"));
-}
-
-#[test]
-fn external_test_named_test() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [[test]]
- name = "test"
- "#)
- .file("src/lib.rs", "")
- .file("tests/test.rs", r#"
- #[test]
- fn foo() { }
- "#)
- .build();
-
- assert_that(p.cargo("test"),
- execs().with_status(0))
-}
-
-#[test]
-fn external_test_implicit() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/lib.rs", r#"
- pub fn get_hello() -> &'static str { "Hello" }
-
- #[test]
- fn internal_test() {}
- "#)
- .file("tests/external.rs", r#"
- extern crate foo;
-
- #[test]
- fn external_test() { assert_eq!(foo::get_hello(), "Hello") }
- "#)
- .build();
-
- assert_that(p.cargo("test"),
- execs().with_status(0).with_stderr(format!("\
-[COMPILING] foo v0.0.1 ({})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] target[/]debug[/]deps[/]foo-[..][EXE]
-[RUNNING] target[/]debug[/]deps[/]external-[..][EXE]
-[DOCTEST] foo", p.url()))
- .with_stdout_contains("test internal_test ... ok")
- .with_stdout_contains("test external_test ... ok")
- .with_stdout_contains("running 0 tests"));
-}
-
-#[test]
-fn dont_run_examples() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/lib.rs", r#"
- "#)
- .file("examples/dont-run-me-i-will-fail.rs", r#"
- fn main() { panic!("Examples should not be run by 'cargo test'"); }
- "#)
- .build();
- assert_that(p.cargo("test"),
- execs().with_status(0));
-}
-
-#[test]
-fn pass_through_command_line() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/lib.rs", "
- #[test] fn foo() {}
- #[test] fn bar() {}
- ")
- .build();
-
- assert_that(p.cargo("test").arg("bar"),
- execs().with_status(0)
- .with_stderr(&format!("\
-[COMPILING] foo v0.0.1 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] target[/]debug[/]deps[/]foo-[..][EXE]
-[DOCTEST] foo", dir = p.url()))
- .with_stdout_contains("test bar ... ok")
- .with_stdout_contains("running 0 tests"));
-
- assert_that(p.cargo("test").arg("foo"),
- execs().with_status(0)
- .with_stderr("\
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] target[/]debug[/]deps[/]foo-[..][EXE]
-[DOCTEST] foo")
- .with_stdout_contains("test foo ... ok")
- .with_stdout_contains("running 0 tests"));
-}
-
-// Regression test for running cargo-test twice with
-// tests in an rlib
-#[test]
-fn cargo_test_twice() {
- let p = project("test_twice")
- .file("Cargo.toml", &basic_lib_manifest("test_twice"))
- .file("src/test_twice.rs", r#"
- #![crate_type = "rlib"]
-
- #[test]
- fn dummy_test() { }
- "#)
- .build();
-
- p.cargo("build");
-
- for _ in 0..2 {
- assert_that(p.cargo("test"),
- execs().with_status(0));
- }
-}
-
-#[test]
-fn lib_bin_same_name() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [lib]
- name = "foo"
- [[bin]]
- name = "foo"
- "#)
- .file("src/lib.rs", "
- #[test] fn lib_test() {}
- ")
- .file("src/main.rs", "
- #[allow(unused_extern_crates)]
- extern crate foo;
-
- #[test]
- fn bin_test() {}
- ")
- .build();
-
- assert_that(p.cargo("test"),
- execs().with_status(0).with_stderr(format!("\
-[COMPILING] foo v0.0.1 ({})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] target[/]debug[/]deps[/]foo-[..][EXE]
-[RUNNING] target[/]debug[/]deps[/]foo-[..][EXE]
-[DOCTEST] foo", p.url()))
- .with_stdout_contains_n("test [..] ... ok", 2)
- .with_stdout_contains("running 0 tests"));
-}
-
-#[test]
-fn lib_with_standard_name() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "syntax"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/lib.rs", "
- /// ```
- /// syntax::foo();
- /// ```
- pub fn foo() {}
-
- #[test]
- fn foo_test() {}
- ")
- .file("tests/test.rs", "
- extern crate syntax;
-
- #[test]
- fn test() { syntax::foo() }
- ")
- .build();
-
- assert_that(p.cargo("test"),
- execs().with_status(0)
- .with_stderr(&format!("\
-[COMPILING] syntax v0.0.1 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] target[/]debug[/]deps[/]syntax-[..][EXE]
-[RUNNING] target[/]debug[/]deps[/]test-[..][EXE]
-[DOCTEST] syntax", dir = p.url()))
- .with_stdout_contains("test foo_test ... ok")
- .with_stdout_contains("test test ... ok")
- .with_stdout_contains_n("test [..] ... ok", 3));
-}
-
-#[test]
-fn lib_with_standard_name2() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "syntax"
- version = "0.0.1"
- authors = []
-
- [lib]
- name = "syntax"
- test = false
- doctest = false
- "#)
- .file("src/lib.rs", "
- pub fn foo() {}
- ")
- .file("src/main.rs", "
- extern crate syntax;
-
- fn main() {}
-
- #[test]
- fn test() { syntax::foo() }
- ")
- .build();
-
- assert_that(p.cargo("test"),
- execs().with_status(0)
- .with_stderr(&format!("\
-[COMPILING] syntax v0.0.1 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] target[/]debug[/]deps[/]syntax-[..][EXE]", dir = p.url()))
- .with_stdout_contains("test test ... ok"));
-}
-
-#[test]
-fn lib_without_name() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "syntax"
- version = "0.0.1"
- authors = []
-
- [lib]
- test = false
- doctest = false
- "#)
- .file("src/lib.rs", "
- pub fn foo() {}
- ")
- .file("src/main.rs", "
- extern crate syntax;
-
- fn main() {}
-
- #[test]
- fn test() { syntax::foo() }
- ")
- .build();
-
- assert_that(p.cargo("test"),
- execs().with_status(0)
- .with_stderr(&format!("\
-[COMPILING] syntax v0.0.1 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] target[/]debug[/]deps[/]syntax-[..][EXE]", dir = p.url()))
- .with_stdout_contains("test test ... ok"));
-}
-
-#[test]
-fn bin_without_name() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "syntax"
- version = "0.0.1"
- authors = []
-
- [lib]
- test = false
- doctest = false
-
- [[bin]]
- path = "src/main.rs"
- "#)
- .file("src/lib.rs", "
- pub fn foo() {}
- ")
- .file("src/main.rs", "
- extern crate syntax;
-
- fn main() {}
-
- #[test]
- fn test() { syntax::foo() }
- ")
- .build();
-
- assert_that(p.cargo("test"),
- execs().with_status(101)
- .with_stderr("\
-[ERROR] failed to parse manifest at `[..]`
-
-Caused by:
- binary target bin.name is required"));
-}
-
-#[test]
-fn bench_without_name() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "syntax"
- version = "0.0.1"
- authors = []
-
- [lib]
- test = false
- doctest = false
-
- [[bench]]
- path = "src/bench.rs"
- "#)
- .file("src/lib.rs", "
- pub fn foo() {}
- ")
- .file("src/main.rs", "
- extern crate syntax;
-
- fn main() {}
-
- #[test]
- fn test() { syntax::foo() }
- ")
- .file("src/bench.rs", "
- #![feature(test)]
- extern crate syntax;
- extern crate test;
-
- #[bench]
- fn external_bench(_b: &mut test::Bencher) {}
- ")
- .build();
-
- assert_that(p.cargo("test"),
- execs().with_status(101)
- .with_stderr("\
-[ERROR] failed to parse manifest at `[..]`
-
-Caused by:
- benchmark target bench.name is required"));
-}
-
-#[test]
-fn test_without_name() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "syntax"
- version = "0.0.1"
- authors = []
-
- [lib]
- test = false
- doctest = false
-
- [[test]]
- path = "src/test.rs"
- "#)
- .file("src/lib.rs", r#"
- pub fn foo() {}
- pub fn get_hello() -> &'static str { "Hello" }
- "#)
- .file("src/main.rs", "
- extern crate syntax;
-
- fn main() {}
-
- #[test]
- fn test() { syntax::foo() }
- ")
- .file("src/test.rs", r#"
- extern crate syntax;
-
- #[test]
- fn external_test() { assert_eq!(syntax::get_hello(), "Hello") }
- "#)
- .build();
-
- assert_that(p.cargo("test"),
- execs().with_status(101)
- .with_stderr("\
-[ERROR] failed to parse manifest at `[..]`
-
-Caused by:
- test target test.name is required"));
-}
-
-#[test]
-fn example_without_name() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "syntax"
- version = "0.0.1"
- authors = []
-
- [lib]
- test = false
- doctest = false
-
- [[example]]
- path = "examples/example.rs"
- "#)
- .file("src/lib.rs", "
- pub fn foo() {}
- ")
- .file("src/main.rs", "
- extern crate syntax;
-
- fn main() {}
-
- #[test]
- fn test() { syntax::foo() }
- ")
- .file("examples/example.rs", r#"
- extern crate syntax;
-
- fn main() {
- println!("example1");
- }
- "#)
- .build();
-
- assert_that(p.cargo("test"),
- execs().with_status(101)
- .with_stderr("\
-[ERROR] failed to parse manifest at `[..]`
-
-Caused by:
- example target example.name is required"));
-}
-
-#[test]
-fn bin_there_for_integration() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/main.rs", "
- fn main() { std::process::exit(101); }
- #[test] fn main_test() {}
- ")
- .file("tests/foo.rs", r#"
- use std::process::Command;
- #[test]
- fn test_test() {
- let status = Command::new("target/debug/foo").status().unwrap();
- assert_eq!(status.code(), Some(101));
- }
- "#)
- .build();
-
- let output = p.cargo("test").arg("-v").exec_with_output().unwrap();
- let output = str::from_utf8(&output.stdout).unwrap();
- assert!(output.contains("main_test ... ok"), "no main_test\n{}", output);
- assert!(output.contains("test_test ... ok"), "no test_test\n{}", output);
-}
-
-#[test]
-fn test_dylib() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [lib]
- name = "foo"
- crate_type = ["dylib"]
-
- [dependencies.bar]
- path = "bar"
- "#)
- .file("src/lib.rs", r#"
- extern crate bar as the_bar;
-
- pub fn bar() { the_bar::baz(); }
-
- #[test]
- fn foo() { bar(); }
- "#)
- .file("tests/test.rs", r#"
- extern crate foo as the_foo;
-
- #[test]
- fn foo() { the_foo::bar(); }
- "#)
- .file("bar/Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
-
- [lib]
- name = "bar"
- crate_type = ["dylib"]
- "#)
- .file("bar/src/lib.rs", "
- pub fn baz() {}
- ")
- .build();
-
- assert_that(p.cargo("test"),
- execs().with_status(0)
- .with_stderr(&format!("\
-[COMPILING] bar v0.0.1 ({dir}/bar)
-[COMPILING] foo v0.0.1 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] target[/]debug[/]deps[/]foo-[..][EXE]
-[RUNNING] target[/]debug[/]deps[/]test-[..][EXE]", dir = p.url()))
- .with_stdout_contains_n("test foo ... ok", 2));
-
- p.root().move_into_the_past();
- assert_that(p.cargo("test"),
- execs().with_status(0)
- .with_stderr("\
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] target[/]debug[/]deps[/]foo-[..][EXE]
-[RUNNING] target[/]debug[/]deps[/]test-[..][EXE]")
- .with_stdout_contains_n("test foo ... ok", 2));
-}
-
-#[test]
-fn test_twice_with_build_cmd() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- build = "build.rs"
- "#)
- .file("build.rs", "fn main() {}")
- .file("src/lib.rs", "
- #[test]
- fn foo() {}
- ")
- .build();
-
- assert_that(p.cargo("test"),
- execs().with_status(0)
- .with_stderr(&format!("\
-[COMPILING] foo v0.0.1 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] target[/]debug[/]deps[/]foo-[..][EXE]
-[DOCTEST] foo", dir = p.url()))
- .with_stdout_contains("test foo ... ok")
- .with_stdout_contains("running 0 tests"));
-
- assert_that(p.cargo("test"),
- execs().with_status(0)
- .with_stderr("\
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] target[/]debug[/]deps[/]foo-[..][EXE]
-[DOCTEST] foo")
- .with_stdout_contains("test foo ... ok")
- .with_stdout_contains("running 0 tests"));
-}
-
-#[test]
-fn test_then_build() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/lib.rs", "
- #[test]
- fn foo() {}
- ")
- .build();
-
- assert_that(p.cargo("test"),
- execs().with_status(0)
- .with_stderr(&format!("\
-[COMPILING] foo v0.0.1 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] target[/]debug[/]deps[/]foo-[..][EXE]
-[DOCTEST] foo", dir = p.url()))
- .with_stdout_contains("test foo ... ok")
- .with_stdout_contains("running 0 tests"));
-
- assert_that(p.cargo("build"),
- execs().with_status(0)
- .with_stdout(""));
-}
-
-#[test]
-fn test_no_run() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/lib.rs", "
- #[test]
- fn foo() { panic!() }
- ")
- .build();
-
- assert_that(p.cargo("test").arg("--no-run"),
- execs().with_status(0)
- .with_stderr(&format!("\
-[COMPILING] foo v0.0.1 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-",
- dir = p.url())));
-}
-
-#[test]
-fn test_run_specific_bin_target() {
- let prj = project("foo")
- .file("Cargo.toml" , r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [[bin]]
- name="bin1"
- path="src/bin1.rs"
-
- [[bin]]
- name="bin2"
- path="src/bin2.rs"
- "#)
- .file("src/bin1.rs", "#[test] fn test1() { }")
- .file("src/bin2.rs", "#[test] fn test2() { }")
- .build();
-
- assert_that(prj.cargo("test").arg("--bin").arg("bin2"),
- execs().with_status(0)
- .with_stderr(format!("\
-[COMPILING] foo v0.0.1 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] target[/]debug[/]deps[/]bin2-[..][EXE]", dir = prj.url()))
- .with_stdout_contains("test test2 ... ok"));
-}
-
-#[test]
-fn test_run_implicit_bin_target() {
- let prj = project("foo")
- .file("Cargo.toml" , r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [[bin]]
- name="mybin"
- path="src/mybin.rs"
- "#)
- .file("src/mybin.rs", "#[test] fn test_in_bin() { }
- fn main() { panic!(\"Don't execute me!\"); }")
- .file("tests/mytest.rs", "#[test] fn test_in_test() { }")
- .file("benches/mybench.rs", "#[test] fn test_in_bench() { }")
- .file("examples/myexm.rs", "#[test] fn test_in_exm() { }
- fn main() { panic!(\"Don't execute me!\"); }")
- .build();
-
- assert_that(prj.cargo("test").arg("--bins"),
- execs().with_status(0)
- .with_stderr(format!("\
-[COMPILING] foo v0.0.1 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] target[/]debug[/]deps[/]mybin-[..][EXE]", dir = prj.url()))
- .with_stdout_contains("test test_in_bin ... ok"));
-}
-
-#[test]
-fn test_run_specific_test_target() {
- let prj = project("foo")
- .file("Cargo.toml" , r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/bin/a.rs", "fn main() { }")
- .file("src/bin/b.rs", "#[test] fn test_b() { } fn main() { }")
- .file("tests/a.rs", "#[test] fn test_a() { }")
- .file("tests/b.rs", "#[test] fn test_b() { }")
- .build();
-
- assert_that(prj.cargo("test").arg("--test").arg("b"),
- execs().with_status(0)
- .with_stderr(format!("\
-[COMPILING] foo v0.0.1 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] target[/]debug[/]deps[/]b-[..][EXE]", dir = prj.url()))
- .with_stdout_contains("test test_b ... ok"));
-}
-
-#[test]
-fn test_run_implicit_test_target() {
- let prj = project("foo")
- .file("Cargo.toml" , r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [[bin]]
- name="mybin"
- path="src/mybin.rs"
- "#)
- .file("src/mybin.rs", "#[test] fn test_in_bin() { }
- fn main() { panic!(\"Don't execute me!\"); }")
- .file("tests/mytest.rs", "#[test] fn test_in_test() { }")
- .file("benches/mybench.rs", "#[test] fn test_in_bench() { }")
- .file("examples/myexm.rs", "#[test] fn test_in_exm() { }
- fn main() { panic!(\"Don't execute me!\"); }")
- .build();
-
- assert_that(prj.cargo("test").arg("--tests"),
- execs().with_status(0)
- .with_stderr(format!("\
-[COMPILING] foo v0.0.1 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] target[/]debug[/]deps[/]mybin-[..][EXE]
-[RUNNING] target[/]debug[/]deps[/]mytest-[..][EXE]
-[RUNNING] target[/]debug[/]examples[/]myexm-[..][EXE]", dir = prj.url()))
- .with_stdout_contains("test test_in_test ... ok"));
-}
-
-#[test]
-fn test_run_implicit_bench_target() {
- let prj = project("foo")
- .file("Cargo.toml" , r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [[bin]]
- name="mybin"
- path="src/mybin.rs"
- "#)
- .file("src/mybin.rs", "#[test] fn test_in_bin() { }
- fn main() { panic!(\"Don't execute me!\"); }")
- .file("tests/mytest.rs", "#[test] fn test_in_test() { }")
- .file("benches/mybench.rs", "#[test] fn test_in_bench() { }")
- .file("examples/myexm.rs", "#[test] fn test_in_exm() { }
- fn main() { panic!(\"Don't execute me!\"); }")
- .build();
-
- assert_that(prj.cargo("test").arg("--benches"),
- execs().with_status(0)
- .with_stderr(format!("\
-[COMPILING] foo v0.0.1 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] target[/]debug[/]deps[/]mybin-[..][EXE]
-[RUNNING] target[/]debug[/]deps[/]mybench-[..][EXE]", dir = prj.url()))
- .with_stdout_contains("test test_in_bench ... ok"));
-}
-
-#[test]
-fn test_run_implicit_example_target() {
- let prj = project("foo")
- .file("Cargo.toml" , r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [[bin]]
- name="mybin"
- path="src/mybin.rs"
- "#)
- .file("src/mybin.rs", "#[test] fn test_in_bin() { }
- fn main() { panic!(\"Don't execute me!\"); }")
- .file("tests/mytest.rs", "#[test] fn test_in_test() { }")
- .file("benches/mybench.rs", "#[test] fn test_in_bench() { }")
- .file("examples/myexm.rs", "#[test] fn test_in_exm() { }
- fn main() { panic!(\"Don't execute me!\"); }")
- .build();
-
- assert_that(prj.cargo("test").arg("--examples"),
- execs().with_status(0)
- .with_stderr(format!("\
-[COMPILING] foo v0.0.1 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] target[/]debug[/]examples[/]myexm-[..][EXE]", dir = prj.url())));
-}
-
-#[test]
-fn test_no_harness() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [[bin]]
- name = "foo"
- test = false
-
- [[test]]
- name = "bar"
- path = "foo.rs"
- harness = false
- "#)
- .file("src/main.rs", "fn main() {}")
- .file("foo.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("test").arg("--").arg("--nocapture"),
- execs().with_status(0)
- .with_stderr(&format!("\
-[COMPILING] foo v0.0.1 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] target[/]debug[/]deps[/]bar-[..][EXE]
-",
- dir = p.url())));
-}
-
-#[test]
-fn selective_testing() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies.d1]
- path = "d1"
- [dependencies.d2]
- path = "d2"
-
- [lib]
- name = "foo"
- doctest = false
- "#)
- .file("src/lib.rs", "")
- .file("d1/Cargo.toml", r#"
- [package]
- name = "d1"
- version = "0.0.1"
- authors = []
-
- [lib]
- name = "d1"
- doctest = false
- "#)
- .file("d1/src/lib.rs", "")
- .file("d1/src/main.rs", "#[allow(unused_extern_crates)] extern crate d1; fn main() {}")
- .file("d2/Cargo.toml", r#"
- [package]
- name = "d2"
- version = "0.0.1"
- authors = []
-
- [lib]
- name = "d2"
- doctest = false
- "#)
- .file("d2/src/lib.rs", "")
- .file("d2/src/main.rs", "#[allow(unused_extern_crates)] extern crate d2; fn main() {}");
- let p = p.build();
-
- println!("d1");
- assert_that(p.cargo("test").arg("-p").arg("d1"),
- execs().with_status(0)
- .with_stderr(&format!("\
-[COMPILING] d1 v0.0.1 ({dir}/d1)
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] target[/]debug[/]deps[/]d1-[..][EXE]
-[RUNNING] target[/]debug[/]deps[/]d1-[..][EXE]", dir = p.url()))
- .with_stdout_contains_n("running 0 tests", 2));
-
- println!("d2");
- assert_that(p.cargo("test").arg("-p").arg("d2"),
- execs().with_status(0)
- .with_stderr(&format!("\
-[COMPILING] d2 v0.0.1 ({dir}/d2)
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] target[/]debug[/]deps[/]d2-[..][EXE]
-[RUNNING] target[/]debug[/]deps[/]d2-[..][EXE]", dir = p.url()))
- .with_stdout_contains_n("running 0 tests", 2));
-
- println!("whole");
- assert_that(p.cargo("test"),
- execs().with_status(0)
- .with_stderr(&format!("\
-[COMPILING] foo v0.0.1 ({dir})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] target[/]debug[/]deps[/]foo-[..][EXE]", dir = p.url()))
- .with_stdout_contains("running 0 tests"));
-}
-
-#[test]
-fn almost_cyclic_but_not_quite() {
- let p = project("a")
- .file("Cargo.toml", r#"
- [package]
- name = "a"
- version = "0.0.1"
- authors = []
-
- [dev-dependencies.b]
- path = "b"
- [dev-dependencies.c]
- path = "c"
- "#)
- .file("src/lib.rs", r#"
- #[cfg(test)] extern crate b;
- #[cfg(test)] extern crate c;
- "#)
- .file("b/Cargo.toml", r#"
- [package]
- name = "b"
- version = "0.0.1"
- authors = []
-
- [dependencies.a]
- path = ".."
- "#)
- .file("b/src/lib.rs", r#"
- #[allow(unused_extern_crates)]
- extern crate a;
- "#)
- .file("c/Cargo.toml", r#"
- [package]
- name = "c"
- version = "0.0.1"
- authors = []
- "#)
- .file("c/src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build"), execs().with_status(0));
- assert_that(p.cargo("test"),
- execs().with_status(0));
-}
-
-#[test]
-fn build_then_selective_test() {
- let p = project("a")
- .file("Cargo.toml", r#"
- [package]
- name = "a"
- version = "0.0.1"
- authors = []
-
- [dependencies.b]
- path = "b"
- "#)
- .file("src/lib.rs", "#[allow(unused_extern_crates)] extern crate b;")
- .file("src/main.rs", r#"
- #[allow(unused_extern_crates)]
- extern crate b;
- #[allow(unused_extern_crates)]
- extern crate a;
- fn main() {}
- "#)
- .file("b/Cargo.toml", r#"
- [package]
- name = "b"
- version = "0.0.1"
- authors = []
- "#)
- .file("b/src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("build"), execs().with_status(0));
- p.root().move_into_the_past();
- assert_that(p.cargo("test").arg("-p").arg("b"),
- execs().with_status(0));
-}
-
-#[test]
-fn example_dev_dep() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dev-dependencies.bar]
- path = "bar"
- "#)
- .file("src/lib.rs", r#"
- "#)
- .file("examples/e1.rs", r#"
- extern crate bar;
- fn main() { }
- "#)
- .file("bar/Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
- "#)
- .file("bar/src/lib.rs", r#"
- // make sure this file takes awhile to compile
- macro_rules! f0( () => (1) );
- macro_rules! f1( () => ({(f0!()) + (f0!())}) );
- macro_rules! f2( () => ({(f1!()) + (f1!())}) );
- macro_rules! f3( () => ({(f2!()) + (f2!())}) );
- macro_rules! f4( () => ({(f3!()) + (f3!())}) );
- macro_rules! f5( () => ({(f4!()) + (f4!())}) );
- macro_rules! f6( () => ({(f5!()) + (f5!())}) );
- macro_rules! f7( () => ({(f6!()) + (f6!())}) );
- macro_rules! f8( () => ({(f7!()) + (f7!())}) );
- pub fn bar() {
- f8!();
- }
- "#)
- .build();
- assert_that(p.cargo("test"),
- execs().with_status(0));
- assert_that(p.cargo("run")
- .arg("--example").arg("e1").arg("--release").arg("-v"),
- execs().with_status(0));
-}
-
-#[test]
-fn selective_testing_with_docs() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies.d1]
- path = "d1"
- "#)
- .file("src/lib.rs", r#"
- /// ```
- /// not valid rust
- /// ```
- pub fn foo() {}
- "#)
- .file("d1/Cargo.toml", r#"
- [package]
- name = "d1"
- version = "0.0.1"
- authors = []
-
- [lib]
- name = "d1"
- path = "d1.rs"
- "#)
- .file("d1/d1.rs", "");
- let p = p.build();
-
- assert_that(p.cargo("test").arg("-p").arg("d1"),
- execs().with_status(0)
- .with_stderr(&format!("\
-[COMPILING] d1 v0.0.1 ({dir}/d1)
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] target[/]debug[/]deps[/]d1[..][EXE]
-[DOCTEST] d1", dir = p.url()))
- .with_stdout_contains_n("running 0 tests", 2));
-}
-
-#[test]
-fn example_bin_same_name() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/bin/foo.rs", r#"fn main() { println!("bin"); }"#)
- .file("examples/foo.rs", r#"fn main() { println!("example"); }"#)
- .build();
-
- assert_that(p.cargo("test").arg("--no-run").arg("-v"),
- execs().with_status(0)
- .with_stderr(&format!("\
-[COMPILING] foo v0.0.1 ({dir})
-[RUNNING] `rustc [..]`
-[RUNNING] `rustc [..]`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-", dir = p.url())));
-
- assert_that(&p.bin("foo"), is_not(existing_file()));
- assert_that(&p.bin("examples/foo"), existing_file());
-
- assert_that(p.process(&p.bin("examples/foo")),
- execs().with_status(0).with_stdout("example\n"));
-
- assert_that(p.cargo("run"),
- execs().with_status(0)
- .with_stderr("\
-[COMPILING] foo v0.0.1 ([..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] [..]")
- .with_stdout("\
-bin
-"));
- assert_that(&p.bin("foo"), existing_file());
-}
-
-#[test]
-fn test_with_example_twice() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/bin/foo.rs", r#"fn main() { println!("bin"); }"#)
- .file("examples/foo.rs", r#"fn main() { println!("example"); }"#)
- .build();
-
- println!("first");
- assert_that(p.cargo("test").arg("-v"),
- execs().with_status(0));
- assert_that(&p.bin("examples/foo"), existing_file());
- println!("second");
- assert_that(p.cargo("test").arg("-v"),
- execs().with_status(0));
- assert_that(&p.bin("examples/foo"), existing_file());
-}
-
-#[test]
-fn example_with_dev_dep() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [lib]
- name = "foo"
- test = false
- doctest = false
-
- [dev-dependencies.a]
- path = "a"
- "#)
- .file("src/lib.rs", "")
- .file("examples/ex.rs", "#[allow(unused_extern_crates)] extern crate a; fn main() {}")
- .file("a/Cargo.toml", r#"
- [package]
- name = "a"
- version = "0.0.1"
- authors = []
- "#)
- .file("a/src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("test").arg("-v"),
- execs().with_status(0)
- .with_stderr("\
-[..]
-[..]
-[..]
-[..]
-[RUNNING] `rustc --crate-name ex [..] --extern a=[..]`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-}
-
-#[test]
-fn bin_is_preserved() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/lib.rs", "")
- .file("src/main.rs", "fn main() {}")
- .build();
-
- assert_that(p.cargo("build").arg("-v"),
- execs().with_status(0));
- assert_that(&p.bin("foo"), existing_file());
-
- println!("testing");
- assert_that(p.cargo("test").arg("-v"),
- execs().with_status(0));
- assert_that(&p.bin("foo"), existing_file());
-}
-
-#[test]
-fn bad_example() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/lib.rs", "");
- let p = p.build();
-
- assert_that(p.cargo("run").arg("--example").arg("foo"),
- execs().with_status(101).with_stderr("\
-[ERROR] no example target named `foo`
-"));
- assert_that(p.cargo("run").arg("--bin").arg("foo"),
- execs().with_status(101).with_stderr("\
-[ERROR] no bin target named `foo`
-"));
-}
-
-#[test]
-fn doctest_feature() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- [features]
- bar = []
- "#)
- .file("src/lib.rs", r#"
- /// ```rust
- /// assert_eq!(foo::foo(), 1);
- /// ```
- #[cfg(feature = "bar")]
- pub fn foo() -> i32 { 1 }
- "#)
- .build();
-
- assert_that(p.cargo("test").arg("--features").arg("bar"),
- execs().with_status(0)
- .with_stderr("\
-[COMPILING] foo [..]
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] target[/]debug[/]deps[/]foo[..][EXE]
-[DOCTEST] foo")
- .with_stdout_contains("running 0 tests")
- .with_stdout_contains("test [..] ... ok"));
-}
-
-#[test]
-fn dashes_to_underscores() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo-bar"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/lib.rs", r#"
- /// ```
- /// assert_eq!(foo_bar::foo(), 1);
- /// ```
- pub fn foo() -> i32 { 1 }
- "#)
- .build();
-
- assert_that(p.cargo("test").arg("-v"),
- execs().with_status(0));
-}
-
-#[test]
-fn doctest_dev_dep() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dev-dependencies]
- b = { path = "b" }
- "#)
- .file("src/lib.rs", r#"
- /// ```
- /// extern crate b;
- /// ```
- pub fn foo() {}
- "#)
- .file("b/Cargo.toml", r#"
- [package]
- name = "b"
- version = "0.0.1"
- authors = []
- "#)
- .file("b/src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("test").arg("-v"),
- execs().with_status(0));
-}
-
-#[test]
-fn filter_no_doc_tests() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/lib.rs", r#"
- /// ```
- /// extern crate b;
- /// ```
- pub fn foo() {}
- "#)
- .file("tests/foo.rs", "")
- .build();
-
- assert_that(p.cargo("test").arg("--test=foo"),
- execs().with_status(0).with_stderr("\
-[COMPILING] foo v0.0.1 ([..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] target[/]debug[/]deps[/]foo[..][EXE]")
- .with_stdout_contains("running 0 tests"));
-}
-
-#[test]
-fn dylib_doctest() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [lib]
- name = "foo"
- crate-type = ["rlib", "dylib"]
- test = false
- "#)
- .file("src/lib.rs", r#"
- /// ```
- /// foo::foo();
- /// ```
- pub fn foo() {}
- "#)
- .build();
-
- assert_that(p.cargo("test"),
- execs().with_status(0).with_stderr("\
-[COMPILING] foo v0.0.1 ([..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[DOCTEST] foo")
- .with_stdout_contains("test [..] ... ok"));
-}
-
-#[test]
-fn dylib_doctest2() {
- // can't doctest dylibs as they're statically linked together
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [lib]
- name = "foo"
- crate-type = ["dylib"]
- test = false
- "#)
- .file("src/lib.rs", r#"
- /// ```
- /// foo::foo();
- /// ```
- pub fn foo() {}
- "#)
- .build();
-
- assert_that(p.cargo("test"),
- execs().with_status(0).with_stdout(""));
-}
-
-#[test]
-fn cyclic_dev_dep_doc_test() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dev-dependencies]
- bar = { path = "bar" }
- "#)
- .file("src/lib.rs", r#"
- //! ```
- //! extern crate bar;
- //! ```
- "#)
- .file("bar/Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- foo = { path = ".." }
- "#)
- .file("bar/src/lib.rs", r#"
- #[allow(unused_extern_crates)]
- extern crate foo;
- "#)
- .build();
- assert_that(p.cargo("test"),
- execs().with_status(0).with_stderr("\
-[COMPILING] foo v0.0.1 ([..])
-[COMPILING] bar v0.0.1 ([..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] target[/]debug[/]deps[/]foo[..][EXE]
-[DOCTEST] foo")
- .with_stdout_contains("running 0 tests")
- .with_stdout_contains("test [..] ... ok"));
-}
-
-#[test]
-fn dev_dep_with_build_script() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dev-dependencies]
- bar = { path = "bar" }
- "#)
- .file("src/lib.rs", "")
- .file("examples/foo.rs", "fn main() {}")
- .file("bar/Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
- build = "build.rs"
- "#)
- .file("bar/src/lib.rs", "")
- .file("bar/build.rs", "fn main() {}")
- .build();
- assert_that(p.cargo("test"),
- execs().with_status(0));
-}
-
-#[test]
-fn no_fail_fast() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/lib.rs", r#"
- pub fn add_one(x: i32) -> i32{
- x + 1
- }
-
- /// ```rust
- /// use foo::sub_one;
- /// assert_eq!(sub_one(101), 100);
- /// ```
- pub fn sub_one(x: i32) -> i32{
- x - 1
- }
- "#)
- .file("tests/test_add_one.rs", r#"
- extern crate foo;
- use foo::*;
-
- #[test]
- fn add_one_test() {
- assert_eq!(add_one(1), 2);
- }
-
- #[test]
- fn fail_add_one_test() {
- assert_eq!(add_one(1), 1);
- }
- "#)
- .file("tests/test_sub_one.rs", r#"
- extern crate foo;
- use foo::*;
-
- #[test]
- fn sub_one_test() {
- assert_eq!(sub_one(1), 0);
- }
- "#)
- .build();
- assert_that(p.cargo("test").arg("--no-fail-fast"),
- execs().with_status(101)
- .with_stderr_contains("\
-[COMPILING] foo v0.0.1 ([..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] target[/]debug[/]deps[/]foo-[..][EXE]
-[RUNNING] target[/]debug[/]deps[/]test_add_one-[..][EXE]")
- .with_stdout_contains("running 0 tests")
- .with_stderr_contains("\
-[RUNNING] target[/]debug[/]deps[/]test_sub_one-[..][EXE]
-[DOCTEST] foo")
- .with_stdout_contains("test result: FAILED. [..]")
- .with_stdout_contains("test sub_one_test ... ok")
- .with_stdout_contains_n("test [..] ... ok", 3));
-}
-
-#[test]
-fn test_multiple_packages() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies.d1]
- path = "d1"
- [dependencies.d2]
- path = "d2"
-
- [lib]
- name = "foo"
- doctest = false
- "#)
- .file("src/lib.rs", "")
- .file("d1/Cargo.toml", r#"
- [package]
- name = "d1"
- version = "0.0.1"
- authors = []
-
- [lib]
- name = "d1"
- doctest = false
- "#)
- .file("d1/src/lib.rs", "")
- .file("d2/Cargo.toml", r#"
- [package]
- name = "d2"
- version = "0.0.1"
- authors = []
-
- [lib]
- name = "d2"
- doctest = false
- "#)
- .file("d2/src/lib.rs", "");
- let p = p.build();
-
- assert_that(p.cargo("test").arg("-p").arg("d1").arg("-p").arg("d2"),
- execs().with_status(0)
- .with_stderr_contains("\
-[RUNNING] target[/]debug[/]deps[/]d1-[..][EXE]")
- .with_stderr_contains("\
-[RUNNING] target[/]debug[/]deps[/]d2-[..][EXE]")
- .with_stdout_contains_n("running 0 tests", 2));
-}
-
-#[test]
-fn bin_does_not_rebuild_tests() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/lib.rs", "")
- .file("src/main.rs", "fn main() {}")
- .file("tests/foo.rs", "");
- let p = p.build();
-
- assert_that(p.cargo("test").arg("-v"),
- execs().with_status(0));
-
- sleep_ms(1000);
- File::create(&p.root().join("src/main.rs")).unwrap()
- .write_all(b"fn main() { 3; }").unwrap();
-
- assert_that(p.cargo("test").arg("-v").arg("--no-run"),
- execs().with_status(0)
- .with_stderr("\
-[COMPILING] foo v0.0.1 ([..])
-[RUNNING] `rustc [..] src[/]main.rs [..]`
-[RUNNING] `rustc [..] src[/]main.rs [..]`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-}
-
-#[test]
-fn selective_test_wonky_profile() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [profile.release]
- opt-level = 2
-
- [dependencies]
- a = { path = "a" }
- "#)
- .file("src/lib.rs", "")
- .file("a/Cargo.toml", r#"
- [package]
- name = "a"
- version = "0.0.1"
- authors = []
- "#)
- .file("a/src/lib.rs", "");
- let p = p.build();
-
- assert_that(p.cargo("test").arg("-v").arg("--no-run").arg("--release")
- .arg("-p").arg("foo").arg("-p").arg("a"),
- execs().with_status(0));
-}
-
-#[test]
-fn selective_test_optional_dep() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- a = { path = "a", optional = true }
- "#)
- .file("src/lib.rs", "")
- .file("a/Cargo.toml", r#"
- [package]
- name = "a"
- version = "0.0.1"
- authors = []
- "#)
- .file("a/src/lib.rs", "");
- let p = p.build();
-
- assert_that(p.cargo("test").arg("-v").arg("--no-run")
- .arg("--features").arg("a").arg("-p").arg("a"),
- execs().with_status(0).with_stderr("\
-[COMPILING] a v0.0.1 ([..])
-[RUNNING] `rustc [..] a[/]src[/]lib.rs [..]`
-[RUNNING] `rustc [..] a[/]src[/]lib.rs [..]`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-}
-
-#[test]
-fn only_test_docs() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
- "#)
- .file("src/lib.rs", r#"
- #[test]
- fn foo() {
- let a: u32 = "hello";
- }
-
- /// ```
- /// foo::bar();
- /// println!("ok");
- /// ```
- pub fn bar() {
- }
- "#)
- .file("tests/foo.rs", "this is not rust");
- let p = p.build();
-
- assert_that(p.cargo("test").arg("--doc"),
- execs().with_status(0)
- .with_stderr("\
-[COMPILING] foo v0.0.1 ([..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[DOCTEST] foo")
- .with_stdout_contains("test [..] ... ok"));
-}
-
-#[test]
-fn test_panic_abort_with_dep() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- bar = { path = "bar" }
-
- [profile.dev]
- panic = 'abort'
- "#)
- .file("src/lib.rs", r#"
- extern crate bar;
-
- #[test]
- fn foo() {}
- "#)
- .file("bar/Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
- "#)
- .file("bar/src/lib.rs", "")
- .build();
- assert_that(p.cargo("test").arg("-v"),
- execs().with_status(0));
-}
-
-#[test]
-fn cfg_test_even_with_no_harness() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [lib]
- harness = false
- doctest = false
- "#)
- .file("src/lib.rs", r#"
- #[cfg(test)]
- fn main() {
- println!("hello!");
- }
- "#)
- .build();
- assert_that(p.cargo("test").arg("-v"),
- execs().with_status(0)
- .with_stdout("hello!\n")
- .with_stderr("\
-[COMPILING] foo v0.0.1 ([..])
-[RUNNING] `rustc [..]`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] `[..]`
-"));
-}
-
-#[test]
-fn panic_abort_multiple() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- a = { path = "a" }
-
- [profile.release]
- panic = 'abort'
- "#)
- .file("src/lib.rs", "#[allow(unused_extern_crates)] extern crate a;")
- .file("a/Cargo.toml", r#"
- [package]
- name = "a"
- version = "0.0.1"
- authors = []
- "#)
- .file("a/src/lib.rs", "")
- .build();
- assert_that(p.cargo("test")
- .arg("--release").arg("-v")
- .arg("-p").arg("foo")
- .arg("-p").arg("a"),
- execs().with_status(0));
-}
-
-#[test]
-fn pass_correct_cfgs_flags_to_rustdoc() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- authors = []
-
- [features]
- default = ["feature_a/default"]
- nightly = ["feature_a/nightly"]
-
- [dependencies.feature_a]
- path = "libs/feature_a"
- default-features = false
- "#)
- .file("src/lib.rs", r#"
- #[cfg(test)]
- mod tests {
- #[test]
- fn it_works() {
- assert!(true);
- }
- }
- "#)
- .file("libs/feature_a/Cargo.toml", r#"
- [package]
- name = "feature_a"
- version = "0.1.0"
- authors = []
-
- [features]
- default = ["mock_serde_codegen"]
- nightly = ["mock_serde_derive"]
-
- [dependencies]
- mock_serde_derive = { path = "../mock_serde_derive", optional = true }
-
- [build-dependencies]
- mock_serde_codegen = { path = "../mock_serde_codegen", optional = true }
- "#)
- .file("libs/feature_a/src/lib.rs", r#"
- #[cfg(feature = "mock_serde_derive")]
- const MSG: &'static str = "This is safe";
-
- #[cfg(feature = "mock_serde_codegen")]
- const MSG: &'static str = "This is risky";
-
- pub fn get() -> &'static str {
- MSG
- }
- "#)
- .file("libs/mock_serde_derive/Cargo.toml", r#"
- [package]
- name = "mock_serde_derive"
- version = "0.1.0"
- authors = []
- "#)
- .file("libs/mock_serde_derive/src/lib.rs", "")
- .file("libs/mock_serde_codegen/Cargo.toml", r#"
- [package]
- name = "mock_serde_codegen"
- version = "0.1.0"
- authors = []
- "#)
- .file("libs/mock_serde_codegen/src/lib.rs", "");
- let p = p.build();
-
- assert_that(p.cargo("test")
- .arg("--package").arg("feature_a")
- .arg("--verbose"),
- execs().with_status(0)
- .with_stderr_contains("\
-[DOCTEST] feature_a
-[RUNNING] `rustdoc --test [..]mock_serde_codegen[..]`"));
-
- assert_that(p.cargo("test")
- .arg("--verbose"),
- execs().with_status(0)
- .with_stderr_contains("\
-[DOCTEST] foo
-[RUNNING] `rustdoc --test [..]feature_a[..]`"));
-}
-
-#[test]
-fn test_release_ignore_panic() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- a = { path = "a" }
-
- [profile.test]
- panic = 'abort'
- [profile.release]
- panic = 'abort'
- "#)
- .file("src/lib.rs", "#[allow(unused_extern_crates)] extern crate a;")
- .file("a/Cargo.toml", r#"
- [package]
- name = "a"
- version = "0.0.1"
- authors = []
- "#)
- .file("a/src/lib.rs", "");
- let p = p.build();
- println!("test");
- assert_that(p.cargo("test").arg("-v"), execs().with_status(0));
- println!("bench");
- assert_that(p.cargo("bench").arg("-v"), execs().with_status(0));
-}
-
-#[test]
-fn test_many_with_features() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- a = { path = "a" }
-
- [features]
- foo = []
-
- [workspace]
- "#)
- .file("src/lib.rs", "")
- .file("a/Cargo.toml", r#"
- [package]
- name = "a"
- version = "0.0.1"
- authors = []
- "#)
- .file("a/src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("test").arg("-v")
- .arg("-p").arg("a")
- .arg("-p").arg("foo")
- .arg("--features").arg("foo"),
- execs().with_status(0));
-}
-
-#[test]
-fn test_all_workspace() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.1.0"
-
- [dependencies]
- bar = { path = "bar" }
-
- [workspace]
- "#)
- .file("src/main.rs", r#"
- #[test]
- fn foo_test() {}
- "#)
- .file("bar/Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.1.0"
- "#)
- .file("bar/src/lib.rs", r#"
- #[test]
- fn bar_test() {}
- "#)
- .build();
-
- assert_that(p.cargo("test")
- .arg("--all"),
- execs().with_status(0)
- .with_stdout_contains("test foo_test ... ok")
- .with_stdout_contains("test bar_test ... ok"));
-}
-
-#[test]
-fn test_all_exclude() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.1.0"
-
- [workspace]
- members = ["bar", "baz"]
- "#)
- .file("src/main.rs", r#"
- fn main() {}
- "#)
- .file("bar/Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.1.0"
- "#)
- .file("bar/src/lib.rs", r#"
- #[test]
- pub fn bar() {}
- "#)
- .file("baz/Cargo.toml", r#"
- [project]
- name = "baz"
- version = "0.1.0"
- "#)
- .file("baz/src/lib.rs", r#"
- #[test]
- pub fn baz() {
- assert!(false);
- }
- "#)
- .build();
-
- assert_that(p.cargo("test")
- .arg("--all")
- .arg("--exclude")
- .arg("baz"),
- execs().with_status(0)
- .with_stdout_contains("running 1 test
-test bar ... ok"));
-}
-
-#[test]
-fn test_all_virtual_manifest() {
- let p = project("workspace")
- .file("Cargo.toml", r#"
- [workspace]
- members = ["a", "b"]
- "#)
- .file("a/Cargo.toml", r#"
- [project]
- name = "a"
- version = "0.1.0"
- "#)
- .file("a/src/lib.rs", r#"
- #[test]
- fn a() {}
- "#)
- .file("b/Cargo.toml", r#"
- [project]
- name = "b"
- version = "0.1.0"
- "#)
- .file("b/src/lib.rs", r#"
- #[test]
- fn b() {}
- "#)
- .build();
-
- assert_that(p.cargo("test")
- .arg("--all"),
- execs().with_status(0)
- .with_stdout_contains("test a ... ok")
- .with_stdout_contains("test b ... ok"));
-}
-
-#[test]
-fn test_virtual_manifest_all_implied() {
- let p = project("workspace")
- .file("Cargo.toml", r#"
- [workspace]
- members = ["a", "b"]
- "#)
- .file("a/Cargo.toml", r#"
- [project]
- name = "a"
- version = "0.1.0"
- "#)
- .file("a/src/lib.rs", r#"
- #[test]
- fn a() {}
- "#)
- .file("b/Cargo.toml", r#"
- [project]
- name = "b"
- version = "0.1.0"
- "#)
- .file("b/src/lib.rs", r#"
- #[test]
- fn b() {}
- "#)
- .build();
-
- assert_that(p.cargo("test"),
- execs().with_status(0)
- .with_stdout_contains("test a ... ok")
- .with_stdout_contains("test b ... ok"));
-}
-
-#[test]
-fn test_all_member_dependency_same_name() {
- let p = project("workspace")
- .file("Cargo.toml", r#"
- [workspace]
- members = ["a"]
- "#)
- .file("a/Cargo.toml", r#"
- [project]
- name = "a"
- version = "0.1.0"
-
- [dependencies]
- a = "0.1.0"
- "#)
- .file("a/src/lib.rs", r#"
- #[test]
- fn a() {}
- "#)
- .build();
-
- Package::new("a", "0.1.0").publish();
-
- assert_that(p.cargo("test")
- .arg("--all"),
- execs().with_status(0)
- .with_stdout_contains("test a ... ok"));
-}
-
-#[test]
-fn doctest_only_with_dev_dep() {
- let p = project("workspace")
- .file("Cargo.toml", r#"
- [project]
- name = "a"
- version = "0.1.0"
-
- [dev-dependencies]
- b = { path = "b" }
- "#)
- .file("src/lib.rs", r#"
- /// ```
- /// extern crate b;
- ///
- /// b::b();
- /// ```
- pub fn a() {}
- "#)
- .file("b/Cargo.toml", r#"
- [project]
- name = "b"
- version = "0.1.0"
- "#)
- .file("b/src/lib.rs", r#"
- pub fn b() {}
- "#)
- .build();
-
- assert_that(p.cargo("test").arg("--doc").arg("-v"),
- execs().with_status(0));
-}
-
-#[test]
-fn test_many_targets() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.1.0"
- "#)
- .file("src/bin/a.rs", r#"
- fn main() {}
- #[test] fn bin_a() {}
- "#)
- .file("src/bin/b.rs", r#"
- fn main() {}
- #[test] fn bin_b() {}
- "#)
- .file("src/bin/c.rs", r#"
- fn main() {}
- #[test] fn bin_c() { panic!(); }
- "#)
- .file("examples/a.rs", r#"
- fn main() {}
- #[test] fn example_a() {}
- "#)
- .file("examples/b.rs", r#"
- fn main() {}
- #[test] fn example_b() {}
- "#)
- .file("examples/c.rs", r#"
- #[test] fn example_c() { panic!(); }
- "#)
- .file("tests/a.rs", r#"
- #[test] fn test_a() {}
- "#)
- .file("tests/b.rs", r#"
- #[test] fn test_b() {}
- "#)
- .file("tests/c.rs", r#"
- does not compile
- "#)
- .build();
-
- assert_that(p.cargo("test").arg("--verbose")
- .arg("--bin").arg("a").arg("--bin").arg("b")
- .arg("--example").arg("a").arg("--example").arg("b")
- .arg("--test").arg("a").arg("--test").arg("b"),
- execs()
- .with_status(0)
- .with_stdout_contains("test bin_a ... ok")
- .with_stdout_contains("test bin_b ... ok")
- .with_stdout_contains("test test_a ... ok")
- .with_stdout_contains("test test_b ... ok")
- .with_stderr_contains("[RUNNING] `rustc --crate-name a examples[/]a.rs [..]`")
- .with_stderr_contains("[RUNNING] `rustc --crate-name b examples[/]b.rs [..]`"))
-}
-
-#[test]
-fn doctest_and_registry() {
- let p = project("workspace")
- .file("Cargo.toml", r#"
- [project]
- name = "a"
- version = "0.1.0"
-
- [dependencies]
- b = { path = "b" }
- c = { path = "c" }
-
- [workspace]
- "#)
- .file("src/lib.rs", "")
- .file("b/Cargo.toml", r#"
- [project]
- name = "b"
- version = "0.1.0"
- "#)
- .file("b/src/lib.rs", "
- /// ```
- /// b::foo();
- /// ```
- pub fn foo() {}
- ")
- .file("c/Cargo.toml", r#"
- [project]
- name = "c"
- version = "0.1.0"
-
- [dependencies]
- b = "0.1"
- "#)
- .file("c/src/lib.rs", "")
- .build();
-
- Package::new("b", "0.1.0").publish();
-
- assert_that(p.cargo("test").arg("--all").arg("-v"),
- execs().with_status(0));
-}
-
-#[test]
-fn cargo_test_env() {
- let src = format!(r#"
- #![crate_type = "rlib"]
-
- #[test]
- fn env_test() {{
- use std::env;
- println!("{{}}", env::var("{}").unwrap());
- }}
- "#, cargo::CARGO_ENV);
-
- let p = project("env_test")
- .file("Cargo.toml", &basic_lib_manifest("env_test"))
- .file("src/lib.rs", &src)
- .build();
-
- let mut pr = p.cargo("test");
- let cargo = cargo_exe().canonicalize().unwrap();
- assert_that(pr.args(&["--lib", "--", "--nocapture"]),
- execs().with_status(0)
- .with_stdout_contains(format!("\
-{}
-test env_test ... ok
-", cargo.to_str().unwrap())));
-}
-
-#[test]
-fn test_order() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.1.0"
- "#)
- .file("src/lib.rs", r#"
- #[test] fn test_lib() {}
- "#)
- .file("tests/a.rs", r#"
- #[test] fn test_a() {}
- "#)
- .file("tests/z.rs", r#"
- #[test] fn test_z() {}
- "#)
- .build();
-
- assert_that(p.cargo("test").arg("--all"),
- execs().with_status(0)
- .with_stdout_contains("
-running 1 test
-test test_lib ... ok
-
-test result: ok. [..]
-
-
-running 1 test
-test test_a ... ok
-
-test result: ok. [..]
-
-
-running 1 test
-test test_z ... ok
-
-test result: ok. [..]
-"));
-
-}
-
-#[test]
-fn cyclic_dev() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.1.0"
-
- [dev-dependencies]
- foo = { path = "." }
- "#)
- .file("src/lib.rs", r#"
- #[test] fn test_lib() {}
- "#)
- .file("tests/foo.rs", r#"
- extern crate foo;
- "#)
- .build();
-
- assert_that(p.cargo("test").arg("--all"),
- execs().with_status(0));
-}
-
-#[test]
-fn publish_a_crate_without_tests() {
- Package::new("testless", "0.1.0")
- .file("Cargo.toml", r#"
- [project]
- name = "testless"
- version = "0.1.0"
- exclude = ["tests/*"]
-
- [[test]]
- name = "a_test"
- "#)
- .file("src/lib.rs", "")
-
- // In real life, the package will have a test,
- // which would be excluded from .crate file by the
- // `exclude` field. Our test harness does not honor
- // exclude though, so let's just not add the file!
- // .file("tests/a_test.rs", "")
-
- .publish();
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.1.0"
-
- [dependencies]
- testless = "0.1.0"
- "#)
- .file("src/lib.rs", "")
- .build();
-
- assert_that(p.cargo("test"), execs().with_status(0));
- assert_that(p.cargo("test").arg("--package").arg("testless"),
- execs().with_status(0));
-}
-
-#[test]
-fn find_dependency_of_proc_macro_dependency_with_target() {
- let workspace = project("workspace")
- .file("Cargo.toml", r#"
- [workspace]
- members = ["root", "proc_macro_dep"]
- "#)
- .file("root/Cargo.toml", r#"
- [project]
- name = "root"
- version = "0.1.0"
- authors = []
-
- [dependencies]
- proc_macro_dep = { path = "../proc_macro_dep" }
- "#)
- .file("root/src/lib.rs", r#"
- #[macro_use]
- extern crate proc_macro_dep;
-
- #[derive(Noop)]
- pub struct X;
- "#)
- .file("proc_macro_dep/Cargo.toml", r#"
- [project]
- name = "proc_macro_dep"
- version = "0.1.0"
- authors = []
-
- [lib]
- proc-macro = true
-
- [dependencies]
- bar = "^0.1"
- "#)
- .file("proc_macro_dep/src/lib.rs", r#"
- extern crate bar;
- extern crate proc_macro;
- use proc_macro::TokenStream;
-
- #[proc_macro_derive(Noop)]
- pub fn noop(_input: TokenStream) -> TokenStream {
- "".parse().unwrap()
- }
- "#)
- .build();
- Package::new("foo", "0.1.0").publish();
- Package::new("bar", "0.1.0")
- .dep("foo", "0.1")
- .file("src/lib.rs", "extern crate foo;")
- .publish();
- assert_that(workspace.cargo("test").arg("--all").arg("--target").arg(rustc_host()),
- execs().with_status(0));
-}
-
-#[test]
-fn test_hint_not_masked_by_doctest() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- "#)
- .file("src/lib.rs", r#"
- /// ```
- /// assert_eq!(1, 1);
- /// ```
- pub fn this_works() {}
- "#)
- .file("tests/integ.rs", r#"
- #[test]
- fn this_fails() {
- panic!();
- }
- "#)
- .build();
- assert_that(p.cargo("test")
- .arg("--no-fail-fast"),
- execs()
- .with_status(101)
- .with_stdout_contains("test this_fails ... FAILED")
- .with_stdout_contains("[..]this_works (line [..]ok")
- .with_stderr_contains("[ERROR] test failed, to rerun pass \
- '--test integ'"));
-}
--- /dev/null
+use cargotest::ChannelChanger;
+use cargotest::support::registry::{self, Package, alt_api_path};
+use cargotest::support::{paths, project, execs};
+use hamcrest::assert_that;
+use std::fs::File;
+use std::io::Write;
+
+#[test]
+fn is_feature_gated() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.bar]
+ version = "0.0.1"
+ registry = "alternative"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ Package::new("bar", "0.0.1").alternative(true).publish();
+
+ assert_that(p.cargo("build").masquerade_as_nightly_cargo(),
+ execs().with_status(101)
+ .with_stderr_contains(" feature `alternative-registries` is required"));
+}
+
+#[test]
+fn depend_on_alt_registry() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ cargo-features = ["alternative-registries"]
+
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.bar]
+ version = "0.0.1"
+ registry = "alternative"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ Package::new("bar", "0.0.1").alternative(true).publish();
+
+ assert_that(p.cargo("build").masquerade_as_nightly_cargo(),
+ execs().with_status(0).with_stderr(&format!("\
+[UPDATING] registry `{reg}`
+[DOWNLOADING] bar v0.0.1 (registry `file://[..]`)
+[COMPILING] bar v0.0.1 (registry `file://[..]`)
+[COMPILING] foo v0.0.1 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] secs
+",
+ dir = p.url(),
+ reg = registry::alt_registry())));
+
+ assert_that(p.cargo("clean").masquerade_as_nightly_cargo(), execs().with_status(0));
+
+ // Don't download a second time
+ assert_that(p.cargo("build").masquerade_as_nightly_cargo(),
+ execs().with_status(0).with_stderr(&format!("\
+[COMPILING] bar v0.0.1 (registry `file://[..]`)
+[COMPILING] foo v0.0.1 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] secs
+",
+ dir = p.url())));
+}
+
+#[test]
+fn depend_on_alt_registry_depends_on_same_registry_no_index() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ cargo-features = ["alternative-registries"]
+
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.bar]
+ version = "0.0.1"
+ registry = "alternative"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ Package::new("baz", "0.0.1").alternative(true).publish();
+ Package::new("bar", "0.0.1").dep("baz", "0.0.1").alternative(true).publish();
+
+ assert_that(p.cargo("build").masquerade_as_nightly_cargo(),
+ execs().with_status(0).with_stderr(&format!("\
+[UPDATING] registry `{reg}`
+[DOWNLOADING] [..] v0.0.1 (registry `file://[..]`)
+[DOWNLOADING] [..] v0.0.1 (registry `file://[..]`)
+[COMPILING] baz v0.0.1 (registry `file://[..]`)
+[COMPILING] bar v0.0.1 (registry `file://[..]`)
+[COMPILING] foo v0.0.1 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] secs
+",
+ dir = p.url(),
+ reg = registry::alt_registry())));
+}
+
+#[test]
+fn depend_on_alt_registry_depends_on_same_registry() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ cargo-features = ["alternative-registries"]
+
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.bar]
+ version = "0.0.1"
+ registry = "alternative"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ Package::new("baz", "0.0.1").alternative(true).publish();
+ Package::new("bar", "0.0.1").registry_dep("baz", "0.0.1", registry::alt_registry().as_str()).alternative(true).publish();
+
+ assert_that(p.cargo("build").masquerade_as_nightly_cargo(),
+ execs().with_status(0).with_stderr(&format!("\
+[UPDATING] registry `{reg}`
+[DOWNLOADING] [..] v0.0.1 (registry `file://[..]`)
+[DOWNLOADING] [..] v0.0.1 (registry `file://[..]`)
+[COMPILING] baz v0.0.1 (registry `file://[..]`)
+[COMPILING] bar v0.0.1 (registry `file://[..]`)
+[COMPILING] foo v0.0.1 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] secs
+",
+ dir = p.url(),
+ reg = registry::alt_registry())));
+}
+
+#[test]
+fn depend_on_alt_registry_depends_on_crates_io() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ cargo-features = ["alternative-registries"]
+
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.bar]
+ version = "0.0.1"
+ registry = "alternative"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ Package::new("baz", "0.0.1").publish();
+ Package::new("bar", "0.0.1").registry_dep("baz", "0.0.1", registry::registry().as_str()).alternative(true).publish();
+
+ assert_that(p.cargo("build").masquerade_as_nightly_cargo(),
+ execs().with_status(0).with_stderr(&format!("\
+[UPDATING] registry `{alt_reg}`
+[UPDATING] registry `{reg}`
+[DOWNLOADING] [..] v0.0.1 (registry `file://[..]`)
+[DOWNLOADING] [..] v0.0.1 (registry `file://[..]`)
+[COMPILING] baz v0.0.1 (registry `file://[..]`)
+[COMPILING] bar v0.0.1 (registry `file://[..]`)
+[COMPILING] foo v0.0.1 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] secs
+",
+ dir = p.url(),
+ alt_reg = registry::alt_registry(),
+ reg = registry::registry())));
+}
+
+#[test]
+fn registry_and_path_dep_works() {
+ registry::init();
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ cargo-features = ["alternative-registries"]
+
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.bar]
+ path = "bar"
+ registry = "alternative"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .file("bar/Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("bar/src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build").masquerade_as_nightly_cargo(),
+ execs().with_status(0)
+ .with_stderr(&format!("\
+[COMPILING] bar v0.0.1 ({dir}/bar)
+[COMPILING] foo v0.0.1 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] secs
+",
+ dir = p.url())));
+}
+
+#[test]
+fn registry_incompatible_with_git() {
+ registry::init();
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ cargo-features = ["alternative-registries"]
+
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.bar]
+ git = ""
+ registry = "alternative"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("build").masquerade_as_nightly_cargo(),
+ execs().with_status(101)
+ .with_stderr_contains(" dependency (bar) specification is ambiguous. Only one of `git` or `registry` is allowed."));
+}
+
+#[test]
+fn cannot_publish_to_crates_io_with_registry_dependency() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ cargo-features = ["alternative-registries"]
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ [dependencies.bar]
+ version = "0.0.1"
+ registry = "alternative"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ Package::new("bar", "0.0.1").alternative(true).publish();
+
+ assert_that(p.cargo("publish").masquerade_as_nightly_cargo()
+ .arg("--index").arg(registry::registry().to_string()),
+ execs().with_status(101));
+}
+
+#[test]
+fn publish_with_registry_dependency() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ cargo-features = ["alternative-registries"]
+
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.bar]
+ version = "0.0.1"
+ registry = "alternative"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ Package::new("bar", "0.0.1").alternative(true).publish();
+
+ // Login so that we have the token available
+ assert_that(p.cargo("login").masquerade_as_nightly_cargo()
+ .arg("--registry").arg("alternative").arg("TOKEN").arg("-Zunstable-options"),
+ execs().with_status(0));
+
+ assert_that(p.cargo("publish").masquerade_as_nightly_cargo()
+ .arg("--registry").arg("alternative").arg("-Zunstable-options"),
+ execs().with_status(0));
+}
+
+#[test]
+fn alt_registry_and_crates_io_deps() {
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ cargo-features = ["alternative-registries"]
+
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ crates_io_dep = "0.0.1"
+
+ [dependencies.alt_reg_dep]
+ version = "0.1.0"
+ registry = "alternative"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ Package::new("crates_io_dep", "0.0.1").publish();
+ Package::new("alt_reg_dep", "0.1.0").alternative(true).publish();
+
+ assert_that(p.cargo("build").masquerade_as_nightly_cargo(),
+ execs().with_status(0)
+ .with_stderr_contains(format!("\
+[UPDATING] registry `{}`", registry::alt_registry()))
+ .with_stderr_contains(&format!("\
+[UPDATING] registry `{}`", registry::registry()))
+ .with_stderr_contains("\
+[DOWNLOADING] crates_io_dep v0.0.1 (registry `file://[..]`)")
+ .with_stderr_contains("\
+[DOWNLOADING] alt_reg_dep v0.1.0 (registry `file://[..]`)")
+ .with_stderr_contains("\
+[COMPILING] alt_reg_dep v0.1.0 (registry `file://[..]`)")
+ .with_stderr_contains("\
+[COMPILING] crates_io_dep v0.0.1")
+ .with_stderr_contains(&format!("\
+[COMPILING] foo v0.0.1 ({})", p.url()))
+ .with_stderr_contains("\
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] secs"))
+
+}
+
+#[test]
+fn block_publish_due_to_no_token() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ // Setup the registry by publishing a package
+ Package::new("bar", "0.0.1").alternative(true).publish();
+
+ // Now perform the actual publish
+ assert_that(p.cargo("publish").masquerade_as_nightly_cargo()
+ .arg("--registry").arg("alternative").arg("-Zunstable-options"),
+ execs().with_status(101)
+ .with_stderr_contains("error: no upload token found, please run `cargo login`"));
+}
+
+#[test]
+fn publish_to_alt_registry() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ cargo-features = ["alternative-registries"]
+
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ // Setup the registry by publishing a package
+ Package::new("bar", "0.0.1").alternative(true).publish();
+
+ // Login so that we have the token available
+ assert_that(p.cargo("login").masquerade_as_nightly_cargo()
+ .arg("--registry").arg("alternative").arg("TOKEN").arg("-Zunstable-options"),
+ execs().with_status(0));
+
+ // Now perform the actual publish
+ assert_that(p.cargo("publish").masquerade_as_nightly_cargo()
+ .arg("--registry").arg("alternative").arg("-Zunstable-options"),
+ execs().with_status(0));
+
+ // Ensure that the crate is uploaded
+ assert!(alt_api_path().join("api/v1/crates/new").exists());
+}
+
+#[test]
+fn publish_with_crates_io_dep() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ cargo-features = ["alternative-registries"]
+
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = ["me"]
+ license = "MIT"
+ description = "foo"
+
+ [dependencies.bar]
+ version = "0.0.1"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ Package::new("bar", "0.0.1").publish();
+
+ // Login so that we have the token available
+ assert_that(p.cargo("login").masquerade_as_nightly_cargo()
+ .arg("--registry").arg("alternative").arg("TOKEN").arg("-Zunstable-options"),
+ execs().with_status(0));
+
+ assert_that(p.cargo("publish").masquerade_as_nightly_cargo()
+ .arg("--registry").arg("alternative").arg("-Zunstable-options"),
+ execs().with_status(0));
+}
+
+#[test]
+fn credentials_in_url_forbidden() {
+ registry::init();
+
+ let config = paths::home().join(".cargo/config");
+
+ File::create(config)
+ .unwrap()
+ .write_all(br#"
+ [registries.alternative]
+ index = "ssh://git:secret@foobar.com"
+ "#)
+ .unwrap();
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ cargo-features = ["alternative-registries"]
+
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("publish").masquerade_as_nightly_cargo()
+ .arg("--registry").arg("alternative").arg("-Zunstable-options"),
+ execs().with_status(101)
+ .with_stderr_contains("error: Registry URLs may not contain credentials"));
+}
--- /dev/null
+use cargotest::support::{project, execs};
+use cargotest::support::registry::Package;
+use hamcrest::assert_that;
+
+#[test]
+fn bad1() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.0"
+ authors = []
+ "#)
+ .file("src/lib.rs", "")
+ .file(".cargo/config", r#"
+ [target]
+ nonexistent-target = "foo"
+ "#)
+ .build();
+ assert_that(p.cargo("build").arg("-v")
+ .arg("--target=nonexistent-target"),
+ execs().with_status(101).with_stderr("\
+[ERROR] expected table for configuration key `target.nonexistent-target`, \
+but found string in [..]config
+"));
+}
+
+#[test]
+fn bad2() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.0"
+ authors = []
+ "#)
+ .file("src/lib.rs", "")
+ .file(".cargo/config", r#"
+ [http]
+ proxy = 3.0
+ "#)
+ .build();
+ assert_that(p.cargo("publish").arg("-v"),
+ execs().with_status(101).with_stderr("\
+[ERROR] Couldn't load Cargo configuration
+
+Caused by:
+ failed to load TOML configuration from `[..]config`
+
+Caused by:
+ failed to parse key `http`
+
+Caused by:
+ failed to parse key `proxy`
+
+Caused by:
+ found TOML configuration value of unknown type `float`
+"));
+}
+
+#[test]
+fn bad3() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.0"
+ authors = []
+ "#)
+ .file("src/lib.rs", "")
+ .file(".cargo/config", r#"
+ [http]
+ proxy = true
+ "#)
+ .build();
+ Package::new("foo", "1.0.0").publish();
+
+ assert_that(p.cargo("publish").arg("-v"),
+ execs().with_status(101).with_stderr("\
+error: failed to update registry [..]
+
+Caused by:
+ invalid configuration for key `http.proxy`
+expected a string, but found a boolean for `http.proxy` in [..]config
+"));
+}
+
+#[test]
+fn bad4() {
+ let p = project("foo")
+ .file(".cargo/config", r#"
+ [cargo-new]
+ name = false
+ "#)
+ .build();
+ assert_that(p.cargo("new").arg("-v").arg("foo"),
+ execs().with_status(101).with_stderr("\
+[ERROR] Failed to create project `foo` at `[..]`
+
+Caused by:
+ invalid configuration for key `cargo-new.name`
+expected a string, but found a boolean for `cargo-new.name` in [..]config
+"));
+}
+
+#[test]
+fn bad5() {
+ let p = project("foo")
+ .file(".cargo/config", r#"
+ foo = ""
+ "#)
+ .file("foo/.cargo/config", r#"
+ foo = 2
+ "#)
+ .build();
+ assert_that(p.cargo("new")
+ .arg("-v").arg("foo").cwd(&p.root().join("foo")),
+ execs().with_status(101).with_stderr("\
+[ERROR] Failed to create project `foo` at `[..]`
+
+Caused by:
+ Couldn't load Cargo configuration
+
+Caused by:
+ failed to merge configuration at `[..]`
+
+Caused by:
+ failed to merge key `foo` between files:
+ file 1: [..]foo[..]foo[..]config
+ file 2: [..]foo[..]config
+
+Caused by:
+ expected integer, but found string
+"));
+}
+
+#[test]
+fn bad_cargo_config_jobs() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.0"
+ authors = []
+ "#)
+ .file("src/lib.rs", "")
+ .file(".cargo/config", r#"
+ [build]
+ jobs = -1
+ "#)
+ .build();
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(101).with_stderr("\
+[ERROR] build.jobs must be positive, but found -1 in [..]
+"));
+}
+
+#[test]
+fn default_cargo_config_jobs() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.0"
+ authors = []
+ "#)
+ .file("src/lib.rs", "")
+ .file(".cargo/config", r#"
+ [build]
+ jobs = 1
+ "#)
+ .build();
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(0));
+}
+
+#[test]
+fn good_cargo_config_jobs() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.0"
+ authors = []
+ "#)
+ .file("src/lib.rs", "")
+ .file(".cargo/config", r#"
+ [build]
+ jobs = 4
+ "#)
+ .build();
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(0));
+}
+
+#[test]
+fn invalid_global_config() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.0"
+ authors = []
+
+ [dependencies]
+ foo = "0.1.0"
+ "#)
+ .file(".cargo/config", "4")
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(101).with_stderr("\
+[ERROR] Couldn't load Cargo configuration
+
+Caused by:
+ could not parse TOML configuration in `[..]`
+
+Caused by:
+ could not parse input as TOML
+
+Caused by:
+ expected an equals, found eof at line 1
+"));
+}
+
+#[test]
+fn bad_cargo_lock() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.0"
+ authors = []
+ "#)
+ .file("Cargo.lock", "[[package]]\nfoo = 92")
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(101).with_stderr("\
+[ERROR] failed to parse lock file at: [..]Cargo.lock
+
+Caused by:
+ missing field `name` for key `package`
+"));
+}
+
+#[test]
+fn duplicate_packages_in_cargo_lock() {
+ Package::new("foo", "0.1.0").publish();
+
+ let p = project("bar")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ foo = "0.1.0"
+ "#)
+ .file("src/lib.rs", "")
+ .file("Cargo.lock", r#"
+ [[package]]
+ name = "bar"
+ version = "0.0.1"
+ dependencies = [
+ "foo 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ ]
+
+ [[package]]
+ name = "foo"
+ version = "0.1.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+
+ [[package]]
+ name = "foo"
+ version = "0.1.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+ "#)
+ .build();
+
+ assert_that(p.cargo("build").arg("--verbose"),
+ execs().with_status(101).with_stderr("\
+[ERROR] failed to parse lock file at: [..]
+
+Caused by:
+ package `foo` is specified twice in the lockfile
+"));
+}
+
+#[test]
+fn bad_source_in_cargo_lock() {
+ Package::new("foo", "0.1.0").publish();
+
+ let p = project("bar")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ foo = "0.1.0"
+ "#)
+ .file("src/lib.rs", "")
+ .file("Cargo.lock", r#"
+ [[package]]
+ name = "bar"
+ version = "0.0.1"
+ dependencies = [
+ "foo 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ ]
+
+ [[package]]
+ name = "foo"
+ version = "0.1.0"
+ source = "You shall not parse"
+ "#)
+ .build();
+
+ assert_that(p.cargo("build").arg("--verbose"),
+ execs().with_status(101).with_stderr("\
+[ERROR] failed to parse lock file at: [..]
+
+Caused by:
+ invalid source `You shall not parse` for key `package.source`
+"));
+}
+
+#[test]
+fn bad_dependency_in_lockfile() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .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)",
+ ]
+ "#)
+ .build();
+
+ assert_that(p.cargo("build").arg("--verbose"),
+ execs().with_status(101).with_stderr("\
+[ERROR] failed to parse lock file at: [..]
+
+Caused by:
+ package `bar 0.1.0 ([..])` is specified as a dependency, but is missing from the package list
+"));
+
+}
+
+#[test]
+fn bad_git_dependency() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.0"
+ authors = []
+
+ [dependencies]
+ foo = { git = "file:.." }
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(101).with_stderr("\
+[UPDATING] git repository `file:///`
+[ERROR] failed to load source for a dependency on `foo`
+
+Caused by:
+ Unable to update file:///
+
+Caused by:
+ failed to clone into: [..]
+
+Caused by:
+ [..]'file:///' is not a valid local file URI[..]
+"));
+}
+
+#[test]
+fn bad_crate_type() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.0"
+ authors = []
+
+ [lib]
+ crate-type = ["bad_type", "rlib"]
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(101).with_stderr_contains("\
+error: failed to run `rustc` to learn about target-specific information
+"));
+}
+
+#[test]
+fn malformed_override() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.0"
+ authors = []
+
+ [target.x86_64-apple-darwin.freetype]
+ native = {
+ foo: "bar"
+ }
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101).with_stderr("\
+[ERROR] failed to parse manifest at `[..]`
+
+Caused by:
+ could not parse input as TOML
+
+Caused by:
+ expected a table key, found a newline at line 8
+"));
+}
+
+#[test]
+fn duplicate_binary_names() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "qqq"
+ version = "0.1.0"
+ authors = ["A <a@a.a>"]
+
+ [[bin]]
+ name = "e"
+ path = "a.rs"
+
+ [[bin]]
+ name = "e"
+ path = "b.rs"
+ "#)
+ .file("a.rs", r#"fn main() -> () {}"#)
+ .file("b.rs", r#"fn main() -> () {}"#)
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101).with_stderr("\
+[ERROR] failed to parse manifest at `[..]`
+
+Caused by:
+ found duplicate binary name e, but all binary targets must have a unique name
+"));
+}
+
+#[test]
+fn duplicate_example_names() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "qqq"
+ version = "0.1.0"
+ authors = ["A <a@a.a>"]
+
+ [[example]]
+ name = "ex"
+ path = "examples/ex.rs"
+
+ [[example]]
+ name = "ex"
+ path = "examples/ex2.rs"
+ "#)
+ .file("examples/ex.rs", r#"fn main () -> () {}"#)
+ .file("examples/ex2.rs", r#"fn main () -> () {}"#)
+ .build();
+
+ assert_that(p.cargo("build").arg("--example").arg("ex"),
+ execs().with_status(101).with_stderr("\
+[ERROR] failed to parse manifest at `[..]`
+
+Caused by:
+ found duplicate example name ex, but all example targets must have a unique name
+"));
+}
+
+#[test]
+fn duplicate_bench_names() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "qqq"
+ version = "0.1.0"
+ authors = ["A <a@a.a>"]
+
+ [[bench]]
+ name = "ex"
+ path = "benches/ex.rs"
+
+ [[bench]]
+ name = "ex"
+ path = "benches/ex2.rs"
+ "#)
+ .file("benches/ex.rs", r#"fn main () {}"#)
+ .file("benches/ex2.rs", r#"fn main () {}"#)
+ .build();
+
+ assert_that(p.cargo("bench"),
+ execs().with_status(101).with_stderr("\
+[ERROR] failed to parse manifest at `[..]`
+
+Caused by:
+ found duplicate bench name ex, but all bench targets must have a unique name
+"));
+}
+
+#[test]
+fn duplicate_deps() {
+ let p = project("foo")
+ .file("shim-bar/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("shim-bar/src/lib.rs", r#"
+ pub fn a() {}
+ "#)
+ .file("linux-bar/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("linux-bar/src/lib.rs", r#"
+ pub fn a() {}
+ "#)
+ .file("Cargo.toml", r#"
+ [package]
+ name = "qqq"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ bar = { path = "shim-bar" }
+
+ [target.x86_64-unknown-linux-gnu.dependencies]
+ bar = { path = "linux-bar" }
+ "#)
+ .file("src/main.rs", r#"fn main () {}"#)
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101).with_stderr("\
+[ERROR] failed to parse manifest at `[..]`
+
+Caused by:
+ Dependency 'bar' has different source paths depending on the build target. Each dependency must \
+have a single canonical source path irrespective of build target.
+"));
+}
+
+#[test]
+fn duplicate_deps_diff_sources() {
+ let p = project("foo")
+ .file("shim-bar/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("shim-bar/src/lib.rs", r#"
+ pub fn a() {}
+ "#)
+ .file("linux-bar/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("linux-bar/src/lib.rs", r#"
+ pub fn a() {}
+ "#)
+ .file("Cargo.toml", r#"
+ [package]
+ name = "qqq"
+ version = "0.0.1"
+ authors = []
+
+ [target.i686-unknown-linux-gnu.dependencies]
+ bar = { path = "shim-bar" }
+
+ [target.x86_64-unknown-linux-gnu.dependencies]
+ bar = { path = "linux-bar" }
+ "#)
+ .file("src/main.rs", r#"fn main () {}"#)
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101).with_stderr("\
+[ERROR] failed to parse manifest at `[..]`
+
+Caused by:
+ Dependency 'bar' has different source paths depending on the build target. Each dependency must \
+have a single canonical source path irrespective of build target.
+"));
+}
+
+#[test]
+fn unused_keys() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+
+ [target.foo]
+ bar = "3"
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr("\
+warning: unused manifest key: target.foo.bar
+[COMPILING] foo v0.1.0 (file:///[..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+
+ name = "foo"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+ bulid = "foo"
+ "#)
+ .file("src/lib.rs", r#"
+ pub fn foo() {}
+ "#)
+ .build();
+ assert_that(p.cargo("build"),
+ execs().with_status(0)
+ .with_stderr("\
+warning: unused manifest key: project.bulid
+[COMPILING] foo [..]
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+
+ let p = project("bar")
+ .file("Cargo.toml", r#"
+ [project]
+
+ name = "foo"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+
+ [lib]
+ build = "foo"
+ "#)
+ .file("src/lib.rs", r#"
+ pub fn foo() {}
+ "#)
+ .build();
+ assert_that(p.cargo("build"),
+ execs().with_status(0)
+ .with_stderr("\
+warning: unused manifest key: lib.build
+[COMPILING] foo [..]
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+}
+
+
+#[test]
+fn empty_dependencies() {
+ let p = project("empty_deps")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "empty_deps"
+ version = "0.0.0"
+ authors = []
+
+ [dependencies]
+ foo = {}
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ Package::new("foo", "0.0.1").publish();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr_contains("\
+warning: dependency (foo) specified without providing a local path, Git repository, or version \
+to use. This will be considered an error in future versions
+"));
+}
+
+#[test]
+fn invalid_toml_historically_allowed_is_warned() {
+ let p = project("empty_deps")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "empty_deps"
+ version = "0.0.0"
+ authors = []
+ "#)
+ .file(".cargo/config", r#"
+ [foo] bar = 2
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr("\
+warning: TOML file found which contains invalid syntax and will soon not parse
+at `[..]config`.
+
+The TOML spec requires newlines after table definitions (e.g. `[a] b = 1` is
+invalid), but this file has a table header which does not have a newline after
+it. A newline needs to be added and this warning will soon become a hard error
+in the future.
+[COMPILING] empty_deps v0.0.0 ([..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+}
+
+#[test]
+fn ambiguous_git_reference() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.0"
+ authors = []
+
+ [dependencies.bar]
+ git = "https://127.0.0.1"
+ branch = "master"
+ tag = "some-tag"
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_stderr_contains("\
+[WARNING] dependency (bar) specification is ambiguous. \
+Only one of `branch`, `tag` or `rev` is allowed. \
+This will be considered an error in future versions
+"));
+}
+
+#[test]
+fn bad_source_config1() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.0"
+ authors = []
+ "#)
+ .file("src/lib.rs", "")
+ .file(".cargo/config", r#"
+ [source.foo]
+ "#)
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101).with_stderr("\
+error: no source URL specified for `source.foo`, need [..]
+"));
+}
+
+#[test]
+fn bad_source_config2() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.0"
+ authors = []
+
+ [dependencies]
+ bar = "*"
+ "#)
+ .file("src/lib.rs", "")
+ .file(".cargo/config", r#"
+ [source.crates-io]
+ registry = 'http://example.com'
+ replace-with = 'bar'
+ "#)
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101).with_stderr("\
+error: failed to load source for a dependency on `bar`
+
+Caused by:
+ Unable to update registry `https://[..]`
+
+Caused by:
+ could not find a configured source with the name `bar` \
+ when attempting to lookup `crates-io` (configuration in [..])
+"));
+}
+
+#[test]
+fn bad_source_config3() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.0"
+ authors = []
+
+ [dependencies]
+ bar = "*"
+ "#)
+ .file("src/lib.rs", "")
+ .file(".cargo/config", r#"
+ [source.crates-io]
+ registry = 'http://example.com'
+ replace-with = 'crates-io'
+ "#)
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101).with_stderr("\
+error: failed to load source for a dependency on `bar`
+
+Caused by:
+ Unable to update registry `https://[..]`
+
+Caused by:
+ detected a cycle of `replace-with` sources, [..]
+"));
+}
+
+#[test]
+fn bad_source_config4() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.0"
+ authors = []
+
+ [dependencies]
+ bar = "*"
+ "#)
+ .file("src/lib.rs", "")
+ .file(".cargo/config", r#"
+ [source.crates-io]
+ registry = 'http://example.com'
+ replace-with = 'bar'
+
+ [source.bar]
+ registry = 'http://example.com'
+ replace-with = 'crates-io'
+ "#)
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101).with_stderr("\
+error: failed to load source for a dependency on `bar`
+
+Caused by:
+ Unable to update registry `https://[..]`
+
+Caused by:
+ detected a cycle of `replace-with` sources, the source `crates-io` is \
+ eventually replaced with itself (configuration in [..])
+"));
+}
+
+#[test]
+fn bad_source_config5() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.0"
+ authors = []
+
+ [dependencies]
+ bar = "*"
+ "#)
+ .file("src/lib.rs", "")
+ .file(".cargo/config", r#"
+ [source.crates-io]
+ registry = 'http://example.com'
+ replace-with = 'bar'
+
+ [source.bar]
+ registry = 'not a url'
+ "#)
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101).with_stderr("\
+error: configuration key `source.bar.registry` specified an invalid URL (in [..])
+
+Caused by:
+ invalid url `not a url`: [..]
+"));
+}
+
+#[test]
+fn both_git_and_path_specified() {
+ let foo = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.0"
+ authors = []
+
+ [dependencies.bar]
+ git = "https://127.0.0.1"
+ path = "bar"
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(foo.cargo("build").arg("-v"),
+ execs().with_stderr_contains("\
+[WARNING] dependency (bar) specification is ambiguous. \
+Only one of `git` or `path` is allowed. \
+This will be considered an error in future versions
+"));
+}
+
+#[test]
+fn bad_source_config6() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.0"
+ authors = []
+
+ [dependencies]
+ bar = "*"
+ "#)
+ .file("src/lib.rs", "")
+ .file(".cargo/config", r#"
+ [source.crates-io]
+ registry = 'http://example.com'
+ replace-with = ['not', 'a', 'string']
+ "#)
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101).with_stderr("\
+error: expected a string, but found a array for `source.crates-io.replace-with` in [..]
+"));
+}
+
+#[test]
+fn ignored_git_revision() {
+ let foo = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.0"
+ authors = []
+
+ [dependencies.bar]
+ path = "bar"
+ branch = "spam"
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(foo.cargo("build").arg("-v"),
+ execs().with_stderr_contains("\
+[WARNING] key `branch` is ignored for dependency (bar). \
+This will be considered an error in future versions"));
+}
+
+#[test]
+fn bad_source_config7() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.0"
+ authors = []
+
+ [dependencies]
+ bar = "*"
+ "#)
+ .file("src/lib.rs", "")
+ .file(".cargo/config", r#"
+ [source.foo]
+ registry = 'http://example.com'
+ local-registry = 'file:///another/file'
+ "#)
+ .build();
+
+ Package::new("bar", "0.1.0").publish();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101).with_stderr("\
+error: more than one source URL specified for `source.foo`
+"));
+}
+
+#[test]
+fn bad_dependency() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.0"
+ authors = []
+
+ [dependencies]
+ bar = 3
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101).with_stderr("\
+error: failed to parse manifest at `[..]`
+
+Caused by:
+ invalid type: integer `3`, expected a version string like [..]
+"));
+}
+
+#[test]
+fn bad_debuginfo() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.0"
+ authors = []
+
+ [profile.dev]
+ debug = 'a'
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101).with_stderr("\
+error: failed to parse manifest at `[..]`
+
+Caused by:
+ invalid type: string \"a\", expected a boolean or an integer for [..]
+"));
+}
+
+#[test]
+fn bad_opt_level() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.0"
+ authors = []
+ build = 3
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101).with_stderr("\
+error: failed to parse manifest at `[..]`
+
+Caused by:
+ invalid type: integer `3`, expected a boolean or a string for key [..]
+"));
+}
--- /dev/null
+use cargotest::support::{project, execs, main_file, basic_bin_manifest};
+use hamcrest::{assert_that};
+
+fn assert_not_a_cargo_toml(command: &str, manifest_path_argument: &str) {
+ let p = project("foo")
+ .file("Cargo.toml", &basic_bin_manifest("foo"))
+ .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
+ .build();
+
+ assert_that(p.cargo(command)
+ .arg("--manifest-path").arg(manifest_path_argument)
+ .cwd(p.root().parent().unwrap()),
+ execs().with_status(101)
+ .with_stderr("[ERROR] the manifest-path must be a path \
+ to a Cargo.toml file"));
+}
+
+
+fn assert_cargo_toml_doesnt_exist(command: &str, manifest_path_argument: &str) {
+ let p = project("foo").build();
+ let expected_path = manifest_path_argument
+ .split('/').collect::<Vec<_>>().join("[..]");
+
+ assert_that(p.cargo(command)
+ .arg("--manifest-path").arg(manifest_path_argument)
+ .cwd(p.root().parent().unwrap()),
+ execs().with_status(101)
+ .with_stderr(
+ format!("[ERROR] manifest path `{}` does not exist",
+ expected_path)
+ ));
+}
+
+#[test]
+fn bench_dir_containing_cargo_toml() {
+ assert_not_a_cargo_toml("bench", "foo");
+}
+
+#[test]
+fn bench_dir_plus_file() {
+ assert_not_a_cargo_toml("bench", "foo/bar");
+}
+
+#[test]
+fn bench_dir_plus_path() {
+ assert_not_a_cargo_toml("bench", "foo/bar/baz");
+}
+
+#[test]
+fn bench_dir_to_nonexistent_cargo_toml() {
+ assert_cargo_toml_doesnt_exist("bench", "foo/bar/baz/Cargo.toml");
+}
+
+#[test]
+fn build_dir_containing_cargo_toml() {
+ assert_not_a_cargo_toml("build", "foo");
+}
+
+#[test]
+fn build_dir_plus_file() {
+ assert_not_a_cargo_toml("bench", "foo/bar");
+}
+
+#[test]
+fn build_dir_plus_path() {
+ assert_not_a_cargo_toml("bench", "foo/bar/baz");
+}
+
+#[test]
+fn build_dir_to_nonexistent_cargo_toml() {
+ assert_cargo_toml_doesnt_exist("build", "foo/bar/baz/Cargo.toml");
+}
+
+#[test]
+fn clean_dir_containing_cargo_toml() {
+ assert_not_a_cargo_toml("clean", "foo");
+}
+
+#[test]
+fn clean_dir_plus_file() {
+ assert_not_a_cargo_toml("clean", "foo/bar");
+}
+
+#[test]
+fn clean_dir_plus_path() {
+ assert_not_a_cargo_toml("clean", "foo/bar/baz");
+}
+
+#[test]
+fn clean_dir_to_nonexistent_cargo_toml() {
+ assert_cargo_toml_doesnt_exist("clean", "foo/bar/baz/Cargo.toml");
+}
+
+#[test]
+fn doc_dir_containing_cargo_toml() {
+ assert_not_a_cargo_toml("doc", "foo");
+}
+
+#[test]
+fn doc_dir_plus_file() {
+ assert_not_a_cargo_toml("doc", "foo/bar");
+}
+
+#[test]
+fn doc_dir_plus_path() {
+ assert_not_a_cargo_toml("doc", "foo/bar/baz");
+}
+
+#[test]
+fn doc_dir_to_nonexistent_cargo_toml() {
+ assert_cargo_toml_doesnt_exist("doc", "foo/bar/baz/Cargo.toml");
+}
+
+#[test]
+fn fetch_dir_containing_cargo_toml() {
+ assert_not_a_cargo_toml("fetch", "foo");
+}
+
+#[test]
+fn fetch_dir_plus_file() {
+ assert_not_a_cargo_toml("fetch", "foo/bar");
+}
+
+#[test]
+fn fetch_dir_plus_path() {
+ assert_not_a_cargo_toml("fetch", "foo/bar/baz");
+}
+
+#[test]
+fn fetch_dir_to_nonexistent_cargo_toml() {
+ assert_cargo_toml_doesnt_exist("fetch", "foo/bar/baz/Cargo.toml");
+}
+
+#[test]
+fn generate_lockfile_dir_containing_cargo_toml() {
+ assert_not_a_cargo_toml("generate-lockfile", "foo");
+}
+
+#[test]
+fn generate_lockfile_dir_plus_file() {
+ assert_not_a_cargo_toml("generate-lockfile", "foo/bar");
+}
+
+#[test]
+fn generate_lockfile_dir_plus_path() {
+ assert_not_a_cargo_toml("generate-lockfile", "foo/bar/baz");
+}
+
+#[test]
+fn generate_lockfile_dir_to_nonexistent_cargo_toml() {
+ assert_cargo_toml_doesnt_exist("generate-lockfile", "foo/bar/baz/Cargo.toml");
+}
+
+#[test]
+fn package_dir_containing_cargo_toml() {
+ assert_not_a_cargo_toml("package", "foo");
+}
+
+#[test]
+fn package_dir_plus_file() {
+ assert_not_a_cargo_toml("package", "foo/bar");
+}
+
+#[test]
+fn package_dir_plus_path() {
+ assert_not_a_cargo_toml("package", "foo/bar/baz");
+}
+
+#[test]
+fn package_dir_to_nonexistent_cargo_toml() {
+ assert_cargo_toml_doesnt_exist("package", "foo/bar/baz/Cargo.toml");
+}
+
+#[test]
+fn pkgid_dir_containing_cargo_toml() {
+ assert_not_a_cargo_toml("pkgid", "foo");
+}
+
+#[test]
+fn pkgid_dir_plus_file() {
+ assert_not_a_cargo_toml("pkgid", "foo/bar");
+}
+
+#[test]
+fn pkgid_dir_plus_path() {
+ assert_not_a_cargo_toml("pkgid", "foo/bar/baz");
+}
+
+#[test]
+fn pkgid_dir_to_nonexistent_cargo_toml() {
+ assert_cargo_toml_doesnt_exist("pkgid", "foo/bar/baz/Cargo.toml");
+}
+
+#[test]
+fn publish_dir_containing_cargo_toml() {
+ assert_not_a_cargo_toml("publish", "foo");
+}
+
+#[test]
+fn publish_dir_plus_file() {
+ assert_not_a_cargo_toml("publish", "foo/bar");
+}
+
+#[test]
+fn publish_dir_plus_path() {
+ assert_not_a_cargo_toml("publish", "foo/bar/baz");
+}
+
+#[test]
+fn publish_dir_to_nonexistent_cargo_toml() {
+ assert_cargo_toml_doesnt_exist("publish", "foo/bar/baz/Cargo.toml");
+}
+
+#[test]
+fn read_manifest_dir_containing_cargo_toml() {
+ assert_not_a_cargo_toml("read-manifest", "foo");
+}
+
+#[test]
+fn read_manifest_dir_plus_file() {
+ assert_not_a_cargo_toml("read-manifest", "foo/bar");
+}
+
+#[test]
+fn read_manifest_dir_plus_path() {
+ assert_not_a_cargo_toml("read-manifest", "foo/bar/baz");
+}
+
+#[test]
+fn read_manifest_dir_to_nonexistent_cargo_toml() {
+ assert_cargo_toml_doesnt_exist("read-manifest", "foo/bar/baz/Cargo.toml");
+}
+
+#[test]
+fn run_dir_containing_cargo_toml() {
+ assert_not_a_cargo_toml("run", "foo");
+}
+
+#[test]
+fn run_dir_plus_file() {
+ assert_not_a_cargo_toml("run", "foo/bar");
+}
+
+#[test]
+fn run_dir_plus_path() {
+ assert_not_a_cargo_toml("run", "foo/bar/baz");
+}
+
+#[test]
+fn run_dir_to_nonexistent_cargo_toml() {
+ assert_cargo_toml_doesnt_exist("run", "foo/bar/baz/Cargo.toml");
+}
+
+#[test]
+fn rustc_dir_containing_cargo_toml() {
+ assert_not_a_cargo_toml("rustc", "foo");
+}
+
+#[test]
+fn rustc_dir_plus_file() {
+ assert_not_a_cargo_toml("rustc", "foo/bar");
+}
+
+#[test]
+fn rustc_dir_plus_path() {
+ assert_not_a_cargo_toml("rustc", "foo/bar/baz");
+}
+
+#[test]
+fn rustc_dir_to_nonexistent_cargo_toml() {
+ assert_cargo_toml_doesnt_exist("rustc", "foo/bar/baz/Cargo.toml");
+}
+
+#[test]
+fn test_dir_containing_cargo_toml() {
+ assert_not_a_cargo_toml("test", "foo");
+}
+
+#[test]
+fn test_dir_plus_file() {
+ assert_not_a_cargo_toml("test", "foo/bar");
+}
+
+#[test]
+fn test_dir_plus_path() {
+ assert_not_a_cargo_toml("test", "foo/bar/baz");
+}
+
+#[test]
+fn test_dir_to_nonexistent_cargo_toml() {
+ assert_cargo_toml_doesnt_exist("test", "foo/bar/baz/Cargo.toml");
+}
+
+#[test]
+fn update_dir_containing_cargo_toml() {
+ assert_not_a_cargo_toml("update", "foo");
+}
+
+#[test]
+fn update_dir_plus_file() {
+ assert_not_a_cargo_toml("update", "foo/bar");
+}
+
+#[test]
+fn update_dir_plus_path() {
+ assert_not_a_cargo_toml("update", "foo/bar/baz");
+}
+
+#[test]
+fn update_dir_to_nonexistent_cargo_toml() {
+ assert_cargo_toml_doesnt_exist("update", "foo/bar/baz/Cargo.toml");
+}
+
+#[test]
+fn verify_project_dir_containing_cargo_toml() {
+ let p = project("foo")
+ .file("Cargo.toml", &basic_bin_manifest("foo"))
+ .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
+ .build();
+
+ assert_that(p.cargo("verify-project")
+ .arg("--manifest-path").arg("foo")
+ .cwd(p.root().parent().unwrap()),
+ execs().with_status(1)
+ .with_stdout("\
+{\"invalid\":\"the manifest-path must be a path to a Cargo.toml file\"}\
+ "));
+}
+
+#[test]
+fn verify_project_dir_plus_file() {
+ let p = project("foo")
+ .file("Cargo.toml", &basic_bin_manifest("foo"))
+ .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
+ .build();
+
+ assert_that(p.cargo("verify-project")
+ .arg("--manifest-path").arg("foo/bar")
+ .cwd(p.root().parent().unwrap()),
+ execs().with_status(1)
+ .with_stdout("\
+{\"invalid\":\"the manifest-path must be a path to a Cargo.toml file\"}\
+ "));
+}
+
+#[test]
+fn verify_project_dir_plus_path() {
+ let p = project("foo")
+ .file("Cargo.toml", &basic_bin_manifest("foo"))
+ .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
+ .build();
+
+ assert_that(p.cargo("verify-project")
+ .arg("--manifest-path").arg("foo/bar/baz")
+ .cwd(p.root().parent().unwrap()),
+ execs().with_status(1)
+ .with_stdout("\
+{\"invalid\":\"the manifest-path must be a path to a Cargo.toml file\"}\
+ "));
+}
+
+#[test]
+fn verify_project_dir_to_nonexistent_cargo_toml() {
+ let p = project("foo").build();
+ assert_that(p.cargo("verify-project")
+ .arg("--manifest-path").arg("foo/bar/baz/Cargo.toml")
+ .cwd(p.root().parent().unwrap()),
+ execs().with_status(1)
+ .with_stdout("\
+{\"invalid\":\"manifest path `foo[..]bar[..]baz[..]Cargo.toml` does not exist\"}\
+ "));
+}
--- /dev/null
+use std::str;
+
+use cargo::util::process;
+use cargotest::is_nightly;
+use cargotest::support::paths::CargoPathExt;
+use cargotest::support::{project, execs, basic_bin_manifest, basic_lib_manifest};
+use hamcrest::{assert_that, existing_file};
+
+#[test]
+fn cargo_bench_simple() {
+ if !is_nightly() { return }
+
+ let p = project("foo")
+ .file("Cargo.toml", &basic_bin_manifest("foo"))
+ .file("src/main.rs", r#"
+ #![feature(test)]
+ #[cfg(test)]
+ extern crate test;
+
+ fn hello() -> &'static str {
+ "hello"
+ }
+
+ pub fn main() {
+ println!("{}", hello())
+ }
+
+ #[bench]
+ fn bench_hello(_b: &mut test::Bencher) {
+ assert_eq!(hello(), "hello")
+ }"#)
+ .build();
+
+ assert_that(p.cargo("build"), execs());
+ assert_that(&p.bin("foo"), existing_file());
+
+ assert_that(process(&p.bin("foo")),
+ execs().with_stdout("hello\n"));
+
+ assert_that(p.cargo("bench"),
+ execs().with_stderr(&format!("\
+[COMPILING] foo v0.5.0 ({})
+[FINISHED] release [optimized] target(s) in [..]
+[RUNNING] target[/]release[/]deps[/]foo-[..][EXE]", p.url()))
+ .with_stdout_contains("test bench_hello ... bench: [..]"));
+}
+
+#[test]
+fn bench_bench_implicit() {
+ if !is_nightly() { return }
+
+ let p = project("foo")
+ .file("Cargo.toml" , r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/main.rs", r#"
+ #![cfg_attr(test, feature(test))]
+ #[cfg(test)]
+ extern crate test;
+ #[bench] fn run1(_ben: &mut test::Bencher) { }
+ fn main() { println!("Hello main!"); }"#)
+ .file("tests/other.rs", r#"
+ #![feature(test)]
+ extern crate test;
+ #[bench] fn run3(_ben: &mut test::Bencher) { }"#)
+ .file("benches/mybench.rs", r#"
+ #![feature(test)]
+ extern crate test;
+ #[bench] fn run2(_ben: &mut test::Bencher) { }"#)
+ .build();
+
+ assert_that(p.cargo("bench").arg("--benches"),
+ execs().with_status(0)
+ .with_stderr(format!("\
+[COMPILING] foo v0.0.1 ({dir})
+[FINISHED] release [optimized] target(s) in [..]
+[RUNNING] target[/]release[/]deps[/]foo-[..][EXE]
+[RUNNING] target[/]release[/]deps[/]mybench-[..][EXE]
+", dir = p.url()))
+ .with_stdout_contains("test run2 ... bench: [..]"));
+}
+
+#[test]
+fn bench_bin_implicit() {
+ if !is_nightly() { return }
+
+ let p = project("foo")
+ .file("Cargo.toml" , r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/main.rs", r#"
+ #![feature(test)]
+ #[cfg(test)]
+ extern crate test;
+ #[bench] fn run1(_ben: &mut test::Bencher) { }
+ fn main() { println!("Hello main!"); }"#)
+ .file("tests/other.rs", r#"
+ #![feature(test)]
+ extern crate test;
+ #[bench] fn run3(_ben: &mut test::Bencher) { }"#)
+ .file("benches/mybench.rs", r#"
+ #![feature(test)]
+ extern crate test;
+ #[bench] fn run2(_ben: &mut test::Bencher) { }"#)
+ .build();
+
+ assert_that(p.cargo("bench").arg("--bins"),
+ execs().with_status(0)
+ .with_stderr(format!("\
+[COMPILING] foo v0.0.1 ({dir})
+[FINISHED] release [optimized] target(s) in [..]
+[RUNNING] target[/]release[/]deps[/]foo-[..][EXE]
+", dir = p.url()))
+ .with_stdout_contains("test run1 ... bench: [..]"));
+}
+
+#[test]
+fn bench_tarname() {
+ if !is_nightly() { return }
+
+ let p = project("foo")
+ .file("Cargo.toml" , r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("benches/bin1.rs", r#"
+ #![feature(test)]
+ extern crate test;
+ #[bench] fn run1(_ben: &mut test::Bencher) { }"#)
+ .file("benches/bin2.rs", r#"
+ #![feature(test)]
+ extern crate test;
+ #[bench] fn run2(_ben: &mut test::Bencher) { }"#)
+ .build();
+
+ assert_that(p.cargo("bench").arg("--bench").arg("bin2"),
+ execs().with_status(0)
+ .with_stderr(format!("\
+[COMPILING] foo v0.0.1 ({dir})
+[FINISHED] release [optimized] target(s) in [..]
+[RUNNING] target[/]release[/]deps[/]bin2-[..][EXE]
+", dir = p.url()))
+ .with_stdout_contains("test run2 ... bench: [..]"));
+}
+
+#[test]
+fn bench_multiple_targets() {
+ if !is_nightly() { return }
+
+ let p = project("foo")
+ .file("Cargo.toml" , r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("benches/bin1.rs", r#"
+ #![feature(test)]
+ extern crate test;
+ #[bench] fn run1(_ben: &mut test::Bencher) { }"#)
+ .file("benches/bin2.rs", r#"
+ #![feature(test)]
+ extern crate test;
+ #[bench] fn run2(_ben: &mut test::Bencher) { }"#)
+ .file("benches/bin3.rs", r#"
+ #![feature(test)]
+ extern crate test;
+ #[bench] fn run3(_ben: &mut test::Bencher) { }"#)
+ .build();
+
+ assert_that(p.cargo("bench")
+ .arg("--bench").arg("bin1")
+ .arg("--bench").arg("bin2"),
+ execs()
+ .with_status(0)
+ .with_stdout_contains("test run1 ... bench: [..]")
+ .with_stdout_contains("test run2 ... bench: [..]")
+ .with_stdout_does_not_contain("run3"));
+}
+
+#[test]
+fn cargo_bench_verbose() {
+ if !is_nightly() { return }
+
+ let p = project("foo")
+ .file("Cargo.toml", &basic_bin_manifest("foo"))
+ .file("src/main.rs", r#"
+ #![feature(test)]
+ #[cfg(test)]
+ extern crate test;
+ fn main() {}
+ #[bench] fn bench_hello(_b: &mut test::Bencher) {}
+ "#)
+ .build();
+
+ assert_that(p.cargo("bench").arg("-v").arg("hello"),
+ execs().with_stderr(&format!("\
+[COMPILING] foo v0.5.0 ({url})
+[RUNNING] `rustc [..] src[/]main.rs [..]`
+[FINISHED] release [optimized] target(s) in [..]
+[RUNNING] `[..]target[/]release[/]deps[/]foo-[..][EXE] hello --bench`", url = p.url()))
+ .with_stdout_contains("test bench_hello ... bench: [..]"));
+}
+
+#[test]
+fn many_similar_names() {
+ if !is_nightly() { return }
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/lib.rs", "
+ #![feature(test)]
+ #[cfg(test)]
+ extern crate test;
+ pub fn foo() {}
+ #[bench] fn lib_bench(_b: &mut test::Bencher) {}
+ ")
+ .file("src/main.rs", "
+ #![feature(test)]
+ #[cfg(test)]
+ extern crate foo;
+ #[cfg(test)]
+ extern crate test;
+ fn main() {}
+ #[bench] fn bin_bench(_b: &mut test::Bencher) { foo::foo() }
+ ")
+ .file("benches/foo.rs", r#"
+ #![feature(test)]
+ extern crate foo;
+ extern crate test;
+ #[bench] fn bench_bench(_b: &mut test::Bencher) { foo::foo() }
+ "#)
+ .build();
+
+ let output = p.cargo("bench").exec_with_output().unwrap();
+ let output = str::from_utf8(&output.stdout).unwrap();
+ assert!(output.contains("test bin_bench"), "bin_bench missing\n{}", output);
+ assert!(output.contains("test lib_bench"), "lib_bench missing\n{}", output);
+ assert!(output.contains("test bench_bench"), "bench_bench missing\n{}", output);
+}
+
+#[test]
+fn cargo_bench_failing_test() {
+ if !is_nightly() { return }
+
+ let p = project("foo")
+ .file("Cargo.toml", &basic_bin_manifest("foo"))
+ .file("src/main.rs", r#"
+ #![feature(test)]
+ #[cfg(test)]
+ extern crate test;
+ fn hello() -> &'static str {
+ "hello"
+ }
+
+ pub fn main() {
+ println!("{}", hello())
+ }
+
+ #[bench]
+ fn bench_hello(_b: &mut test::Bencher) {
+ assert_eq!(hello(), "nope")
+ }"#)
+ .build();
+
+ assert_that(p.cargo("build"), execs());
+ assert_that(&p.bin("foo"), existing_file());
+
+ assert_that(process(&p.bin("foo")),
+ execs().with_stdout("hello\n"));
+
+ // Force libtest into serial execution so that the test header will be printed.
+ assert_that(p.cargo("bench").arg("--").arg("--test-threads=1"),
+ execs().with_stdout_contains("test bench_hello ...[..]")
+ .with_stderr_contains(format!("\
+[COMPILING] foo v0.5.0 ({})[..]
+[FINISHED] release [optimized] target(s) in [..]
+[RUNNING] target[/]release[/]deps[/]foo-[..][EXE]", p.url()))
+ .with_either_contains("[..]thread '[..]' panicked at 'assertion failed: `(left == right)`[..]")
+ .with_either_contains("[..]left: `\"hello\"`[..]")
+ .with_either_contains("[..]right: `\"nope\"`[..]")
+ .with_either_contains("[..]src[/]main.rs:15[..]")
+ .with_status(101));
+}
+
+#[test]
+fn bench_with_lib_dep() {
+ if !is_nightly() { return }
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [[bin]]
+ name = "baz"
+ path = "src/main.rs"
+ "#)
+ .file("src/lib.rs", r#"
+ #![cfg_attr(test, feature(test))]
+ #[cfg(test)]
+ extern crate test;
+ ///
+ /// ```rust
+ /// extern crate foo;
+ /// fn main() {
+ /// println!("{}", foo::foo());
+ /// }
+ /// ```
+ ///
+ pub fn foo(){}
+ #[bench] fn lib_bench(_b: &mut test::Bencher) {}
+ "#)
+ .file("src/main.rs", "
+ #![feature(test)]
+ #[allow(unused_extern_crates)]
+ extern crate foo;
+ #[cfg(test)]
+ extern crate test;
+
+ fn main() {}
+
+ #[bench]
+ fn bin_bench(_b: &mut test::Bencher) {}
+ ")
+ .build();
+
+ assert_that(p.cargo("bench"),
+ execs().with_stderr(&format!("\
+[COMPILING] foo v0.0.1 ({})
+[FINISHED] release [optimized] target(s) in [..]
+[RUNNING] target[/]release[/]deps[/]foo-[..][EXE]
+[RUNNING] target[/]release[/]deps[/]baz-[..][EXE]", p.url()))
+ .with_stdout_contains("test lib_bench ... bench: [..]")
+ .with_stdout_contains("test bin_bench ... bench: [..]"));
+}
+
+#[test]
+fn bench_with_deep_lib_dep() {
+ if !is_nightly() { return }
+
+ let p = project("bar")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.foo]
+ path = "../foo"
+ "#)
+ .file("src/lib.rs", "
+ #![cfg_attr(test, feature(test))]
+ #[cfg(test)]
+ extern crate foo;
+ #[cfg(test)]
+ extern crate test;
+ #[bench]
+ fn bar_bench(_b: &mut test::Bencher) {
+ foo::foo();
+ }
+ ")
+ .build();
+ let _p2 = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/lib.rs", "
+ #![cfg_attr(test, feature(test))]
+ #[cfg(test)]
+ extern crate test;
+
+ pub fn foo() {}
+
+ #[bench]
+ fn foo_bench(_b: &mut test::Bencher) {}
+ ")
+ .build();
+
+ assert_that(p.cargo("bench"),
+ execs().with_status(0)
+ .with_stderr(&format!("\
+[COMPILING] foo v0.0.1 ([..])
+[COMPILING] bar v0.0.1 ({dir})
+[FINISHED] release [optimized] target(s) in [..]
+[RUNNING] target[/]release[/]deps[/]bar-[..][EXE]", dir = p.url()))
+ .with_stdout_contains("test bar_bench ... bench: [..]"));
+}
+
+#[test]
+fn external_bench_explicit() {
+ if !is_nightly() { return }
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [[bench]]
+ name = "bench"
+ path = "src/bench.rs"
+ "#)
+ .file("src/lib.rs", r#"
+ #![cfg_attr(test, feature(test))]
+ #[cfg(test)]
+ extern crate test;
+ pub fn get_hello() -> &'static str { "Hello" }
+
+ #[bench]
+ fn internal_bench(_b: &mut test::Bencher) {}
+ "#)
+ .file("src/bench.rs", r#"
+ #![feature(test)]
+ #[allow(unused_extern_crates)]
+ extern crate foo;
+ extern crate test;
+
+ #[bench]
+ fn external_bench(_b: &mut test::Bencher) {}
+ "#)
+ .build();
+
+ assert_that(p.cargo("bench"),
+ execs().with_stderr(&format!("\
+[COMPILING] foo v0.0.1 ({})
+[FINISHED] release [optimized] target(s) in [..]
+[RUNNING] target[/]release[/]deps[/]foo-[..][EXE]
+[RUNNING] target[/]release[/]deps[/]bench-[..][EXE]", p.url()))
+ .with_stdout_contains("test internal_bench ... bench: [..]")
+ .with_stdout_contains("test external_bench ... bench: [..]"));
+}
+
+#[test]
+fn external_bench_implicit() {
+ if !is_nightly() { return }
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/lib.rs", r#"
+ #![cfg_attr(test, feature(test))]
+ #[cfg(test)]
+ extern crate test;
+
+ pub fn get_hello() -> &'static str { "Hello" }
+
+ #[bench]
+ fn internal_bench(_b: &mut test::Bencher) {}
+ "#)
+ .file("benches/external.rs", r#"
+ #![feature(test)]
+ #[allow(unused_extern_crates)]
+ extern crate foo;
+ extern crate test;
+
+ #[bench]
+ fn external_bench(_b: &mut test::Bencher) {}
+ "#)
+ .build();
+
+ assert_that(p.cargo("bench"),
+ execs().with_stderr(&format!("\
+[COMPILING] foo v0.0.1 ({})
+[FINISHED] release [optimized] target(s) in [..]
+[RUNNING] target[/]release[/]deps[/]foo-[..][EXE]
+[RUNNING] target[/]release[/]deps[/]external-[..][EXE]", p.url()))
+ .with_stdout_contains("test internal_bench ... bench: [..]")
+ .with_stdout_contains("test external_bench ... bench: [..]"));
+}
+
+#[test]
+fn dont_run_examples() {
+ if !is_nightly() { return }
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/lib.rs", r"")
+ .file("examples/dont-run-me-i-will-fail.rs", r#"
+ fn main() { panic!("Examples should not be run by 'cargo test'"); }
+ "#)
+ .build();
+ assert_that(p.cargo("bench"),
+ execs().with_status(0));
+}
+
+#[test]
+fn pass_through_command_line() {
+ if !is_nightly() { return }
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/lib.rs", "
+ #![feature(test)]
+ #[cfg(test)]
+ extern crate test;
+
+ #[bench] fn foo(_b: &mut test::Bencher) {}
+ #[bench] fn bar(_b: &mut test::Bencher) {}
+ ")
+ .build();
+
+ assert_that(p.cargo("bench").arg("bar"),
+ execs().with_status(0)
+ .with_stderr(&format!("\
+[COMPILING] foo v0.0.1 ({dir})
+[FINISHED] release [optimized] target(s) in [..]
+[RUNNING] target[/]release[/]deps[/]foo-[..][EXE]", dir = p.url()))
+ .with_stdout_contains("test bar ... bench: [..]"));
+
+ assert_that(p.cargo("bench").arg("foo"),
+ execs().with_status(0)
+ .with_stderr("[FINISHED] release [optimized] target(s) in [..]
+[RUNNING] target[/]release[/]deps[/]foo-[..][EXE]")
+ .with_stdout_contains("test foo ... bench: [..]"));
+}
+
+// Regression test for running cargo-bench twice with
+// tests in an rlib
+#[test]
+fn cargo_bench_twice() {
+ if !is_nightly() { return }
+
+ let p = project("test_twice")
+ .file("Cargo.toml", &basic_lib_manifest("test_twice"))
+ .file("src/test_twice.rs", r#"
+ #![crate_type = "rlib"]
+ #![feature(test)]
+ #[cfg(test)]
+ extern crate test;
+
+ #[bench]
+ fn dummy_bench(b: &mut test::Bencher) { }
+ "#)
+ .build();
+
+ p.cargo("build");
+
+ for _ in 0..2 {
+ assert_that(p.cargo("bench"),
+ execs().with_status(0));
+ }
+}
+
+#[test]
+fn lib_bin_same_name() {
+ if !is_nightly() { return }
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [lib]
+ name = "foo"
+ [[bin]]
+ name = "foo"
+ "#)
+ .file("src/lib.rs", "
+ #![cfg_attr(test, feature(test))]
+ #[cfg(test)]
+ extern crate test;
+ #[bench] fn lib_bench(_b: &mut test::Bencher) {}
+ ")
+ .file("src/main.rs", "
+ #![cfg_attr(test, feature(test))]
+ #[allow(unused_extern_crates)]
+ extern crate foo;
+ #[cfg(test)]
+ extern crate test;
+
+ #[bench]
+ fn bin_bench(_b: &mut test::Bencher) {}
+ ")
+ .build();
+
+ assert_that(p.cargo("bench"),
+ execs().with_stderr(&format!("\
+[COMPILING] foo v0.0.1 ({})
+[FINISHED] release [optimized] target(s) in [..]
+[RUNNING] target[/]release[/]deps[/]foo-[..][EXE]
+[RUNNING] target[/]release[/]deps[/]foo-[..][EXE]", p.url()))
+ .with_stdout_contains_n("test [..] ... bench: [..]", 2));
+}
+
+#[test]
+fn lib_with_standard_name() {
+ if !is_nightly() { return }
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "syntax"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/lib.rs", "
+ #![cfg_attr(test, feature(test))]
+ #[cfg(test)]
+ extern crate test;
+
+ /// ```
+ /// syntax::foo();
+ /// ```
+ pub fn foo() {}
+
+ #[bench]
+ fn foo_bench(_b: &mut test::Bencher) {}
+ ")
+ .file("benches/bench.rs", "
+ #![feature(test)]
+ extern crate syntax;
+ extern crate test;
+
+ #[bench]
+ fn bench(_b: &mut test::Bencher) { syntax::foo() }
+ ")
+ .build();
+
+ assert_that(p.cargo("bench"),
+ execs().with_status(0)
+ .with_stderr(&format!("\
+[COMPILING] syntax v0.0.1 ({dir})
+[FINISHED] release [optimized] target(s) in [..]
+[RUNNING] target[/]release[/]deps[/]syntax-[..][EXE]
+[RUNNING] target[/]release[/]deps[/]bench-[..][EXE]", dir = p.url()))
+ .with_stdout_contains("test foo_bench ... bench: [..]")
+ .with_stdout_contains("test bench ... bench: [..]"));
+}
+
+#[test]
+fn lib_with_standard_name2() {
+ if !is_nightly() { return }
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "syntax"
+ version = "0.0.1"
+ authors = []
+
+ [lib]
+ name = "syntax"
+ bench = false
+ doctest = false
+ "#)
+ .file("src/lib.rs", "
+ pub fn foo() {}
+ ")
+ .file("src/main.rs", "
+ #![feature(test)]
+ #[cfg(test)]
+ extern crate syntax;
+ #[cfg(test)]
+ extern crate test;
+
+ fn main() {}
+
+ #[bench]
+ fn bench(_b: &mut test::Bencher) { syntax::foo() }
+ ")
+ .build();
+
+ assert_that(p.cargo("bench"),
+ execs().with_status(0)
+ .with_stderr(&format!("\
+[COMPILING] syntax v0.0.1 ({dir})
+[FINISHED] release [optimized] target(s) in [..]
+[RUNNING] target[/]release[/]deps[/]syntax-[..][EXE]", dir = p.url()))
+ .with_stdout_contains("test bench ... bench: [..]"));
+}
+
+#[test]
+fn bench_dylib() {
+ if !is_nightly() { return }
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [lib]
+ name = "foo"
+ crate_type = ["dylib"]
+
+ [dependencies.bar]
+ path = "bar"
+ "#)
+ .file("src/lib.rs", r#"
+ #![cfg_attr(test, feature(test))]
+ extern crate bar as the_bar;
+ #[cfg(test)]
+ extern crate test;
+
+ pub fn bar() { the_bar::baz(); }
+
+ #[bench]
+ fn foo(_b: &mut test::Bencher) {}
+ "#)
+ .file("benches/bench.rs", r#"
+ #![feature(test)]
+ extern crate foo as the_foo;
+ extern crate test;
+
+ #[bench]
+ fn foo(_b: &mut test::Bencher) { the_foo::bar(); }
+ "#)
+ .file("bar/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+
+ [lib]
+ name = "bar"
+ crate_type = ["dylib"]
+ "#)
+ .file("bar/src/lib.rs", "
+ pub fn baz() {}
+ ")
+ .build();
+
+ assert_that(p.cargo("bench").arg("-v"),
+ execs().with_status(0)
+ .with_stderr(&format!("\
+[COMPILING] bar v0.0.1 ({dir}/bar)
+[RUNNING] [..] -C opt-level=3 [..]
+[COMPILING] foo v0.0.1 ({dir})
+[RUNNING] [..] -C opt-level=3 [..]
+[RUNNING] [..] -C opt-level=3 [..]
+[RUNNING] [..] -C opt-level=3 [..]
+[FINISHED] release [optimized] target(s) in [..]
+[RUNNING] `[..]target[/]release[/]deps[/]foo-[..][EXE] --bench`
+[RUNNING] `[..]target[/]release[/]deps[/]bench-[..][EXE] --bench`", dir = p.url()))
+ .with_stdout_contains_n("test foo ... bench: [..]", 2));
+
+ p.root().move_into_the_past();
+ assert_that(p.cargo("bench").arg("-v"),
+ execs().with_status(0)
+ .with_stderr(&format!("\
+[FRESH] bar v0.0.1 ({dir}/bar)
+[FRESH] foo v0.0.1 ({dir})
+[FINISHED] release [optimized] target(s) in [..]
+[RUNNING] `[..]target[/]release[/]deps[/]foo-[..][EXE] --bench`
+[RUNNING] `[..]target[/]release[/]deps[/]bench-[..][EXE] --bench`", dir = p.url()))
+ .with_stdout_contains_n("test foo ... bench: [..]", 2));
+}
+
+#[test]
+fn bench_twice_with_build_cmd() {
+ if !is_nightly() { return }
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ build = "build.rs"
+ "#)
+ .file("build.rs", "fn main() {}")
+ .file("src/lib.rs", "
+ #![feature(test)]
+ #[cfg(test)]
+ extern crate test;
+ #[bench]
+ fn foo(_b: &mut test::Bencher) {}
+ ")
+ .build();
+
+ assert_that(p.cargo("bench"),
+ execs().with_status(0)
+ .with_stderr(&format!("\
+[COMPILING] foo v0.0.1 ({dir})
+[FINISHED] release [optimized] target(s) in [..]
+[RUNNING] target[/]release[/]deps[/]foo-[..][EXE]", dir = p.url()))
+ .with_stdout_contains("test foo ... bench: [..]"));
+
+ assert_that(p.cargo("bench"),
+ execs().with_status(0)
+ .with_stderr("[FINISHED] release [optimized] target(s) in [..]
+[RUNNING] target[/]release[/]deps[/]foo-[..][EXE]")
+ .with_stdout_contains("test foo ... bench: [..]"));
+}
+
+#[test]
+fn bench_with_examples() {
+ if !is_nightly() { return }
+
+ let p = project("testbench")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "testbench"
+ version = "6.6.6"
+ authors = []
+
+ [[example]]
+ name = "teste1"
+
+ [[bench]]
+ name = "testb1"
+ "#)
+ .file("src/lib.rs", r#"
+ #![cfg_attr(test, feature(test))]
+ #[cfg(test)]
+ extern crate test;
+ #[cfg(test)]
+ use test::Bencher;
+
+ pub fn f1() {
+ println!("f1");
+ }
+
+ pub fn f2() {}
+
+ #[bench]
+ fn bench_bench1(_b: &mut Bencher) {
+ f2();
+ }
+ "#)
+ .file("benches/testb1.rs", "
+ #![feature(test)]
+ extern crate testbench;
+ extern crate test;
+
+ use test::Bencher;
+
+ #[bench]
+ fn bench_bench2(_b: &mut Bencher) {
+ testbench::f2();
+ }
+ ")
+ .file("examples/teste1.rs", r#"
+ extern crate testbench;
+
+ fn main() {
+ println!("example1");
+ testbench::f1();
+ }
+ "#)
+ .build();
+
+ assert_that(p.cargo("bench").arg("-v"),
+ execs().with_status(0)
+ .with_stderr(&format!("\
+[COMPILING] testbench v6.6.6 ({url})
+[RUNNING] `rustc [..]`
+[RUNNING] `rustc [..]`
+[RUNNING] `rustc [..]`
+[FINISHED] release [optimized] target(s) in [..]
+[RUNNING] `{dir}[/]target[/]release[/]deps[/]testbench-[..][EXE] --bench`
+[RUNNING] `{dir}[/]target[/]release[/]deps[/]testb1-[..][EXE] --bench`",
+ dir = p.root().display(), url = p.url()))
+ .with_stdout_contains("test bench_bench1 ... bench: [..]")
+ .with_stdout_contains("test bench_bench2 ... bench: [..]"));
+}
+
+#[test]
+fn test_a_bench() {
+ if !is_nightly() { return }
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ authors = []
+ version = "0.1.0"
+
+ [lib]
+ name = "foo"
+ test = false
+ doctest = false
+
+ [[bench]]
+ name = "b"
+ test = true
+ "#)
+ .file("src/lib.rs", "")
+ .file("benches/b.rs", r#"
+ #[test]
+ fn foo() {}
+ "#)
+ .build();
+
+ assert_that(p.cargo("test"),
+ execs().with_status(0)
+ .with_stderr("\
+[COMPILING] foo v0.1.0 ([..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] target[/]debug[/]deps[/]b-[..][EXE]")
+ .with_stdout_contains("test foo ... ok"));
+}
+
+#[test]
+fn test_bench_no_run() {
+ if !is_nightly() { return }
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ authors = []
+ version = "0.1.0"
+ "#)
+ .file("src/lib.rs", "")
+ .file("benches/bbaz.rs", r#"
+ #![feature(test)]
+
+ extern crate test;
+
+ use test::Bencher;
+
+ #[bench]
+ fn bench_baz(_: &mut Bencher) {}
+ "#)
+ .build();
+
+ assert_that(p.cargo("bench").arg("--no-run"),
+ execs().with_status(0)
+ .with_stderr("\
+[COMPILING] foo v0.1.0 ([..])
+[FINISHED] release [optimized] target(s) in [..]
+"));
+}
+
+#[test]
+fn test_bench_no_fail_fast() {
+ if !is_nightly() { return }
+
+ let p = project("foo")
+ .file("Cargo.toml", &basic_bin_manifest("foo"))
+ .file("src/foo.rs", r#"
+ #![feature(test)]
+ #[cfg(test)]
+ extern crate test;
+ fn hello() -> &'static str {
+ "hello"
+ }
+
+ pub fn main() {
+ println!("{}", hello())
+ }
+
+ #[bench]
+ fn bench_hello(_b: &mut test::Bencher) {
+ assert_eq!(hello(), "hello")
+ }
+
+ #[bench]
+ fn bench_nope(_b: &mut test::Bencher) {
+ assert_eq!("nope", hello())
+ }"#)
+ .build();
+
+ assert_that(p.cargo("bench").arg("--no-fail-fast").arg("--").arg("--test-threads=1"),
+ execs().with_status(101)
+ .with_stderr_contains("\
+[RUNNING] target[/]release[/]deps[/]foo-[..][EXE]")
+ .with_stdout_contains("running 2 tests")
+ .with_stderr_contains("\
+[RUNNING] target[/]release[/]deps[/]foo-[..][EXE]")
+ .with_stdout_contains("test bench_hello [..]")
+ .with_stdout_contains("test bench_nope [..]"));
+}
+
+#[test]
+fn test_bench_multiple_packages() {
+ if !is_nightly() { return }
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ authors = []
+ version = "0.1.0"
+
+ [dependencies.bar]
+ path = "../bar"
+
+ [dependencies.baz]
+ path = "../baz"
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+
+ let _bar = project("bar")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "bar"
+ authors = []
+ version = "0.1.0"
+
+ [[bench]]
+ name = "bbar"
+ test = true
+ "#)
+ .file("src/lib.rs", "")
+ .file("benches/bbar.rs", r#"
+ #![feature(test)]
+ extern crate test;
+
+ use test::Bencher;
+
+ #[bench]
+ fn bench_bar(_b: &mut Bencher) {}
+ "#)
+ .build();
+
+ let _baz = project("baz")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "baz"
+ authors = []
+ version = "0.1.0"
+
+ [[bench]]
+ name = "bbaz"
+ test = true
+ "#)
+ .file("src/lib.rs", "")
+ .file("benches/bbaz.rs", r#"
+ #![feature(test)]
+ extern crate test;
+
+ use test::Bencher;
+
+ #[bench]
+ fn bench_baz(_b: &mut Bencher) {}
+ "#)
+ .build();
+
+
+ assert_that(p.cargo("bench").arg("-p").arg("bar").arg("-p").arg("baz"),
+ execs().with_status(0)
+ .with_stderr_contains("\
+[RUNNING] target[/]release[/]deps[/]bbaz-[..][EXE]")
+ .with_stdout_contains("test bench_baz ... bench: [..]")
+ .with_stderr_contains("\
+[RUNNING] target[/]release[/]deps[/]bbar-[..][EXE]")
+ .with_stdout_contains("test bench_bar ... bench: [..]"));
+}
+
+#[test]
+fn bench_all_workspace() {
+ if !is_nightly() { return }
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+
+ [dependencies]
+ bar = { path = "bar" }
+
+ [workspace]
+ "#)
+ .file("src/main.rs", r#"
+ fn main() {}
+ "#)
+ .file("benches/foo.rs", r#"
+ #![feature(test)]
+ extern crate test;
+
+ use test::Bencher;
+
+ #[bench]
+ fn bench_foo(_: &mut Bencher) -> () { () }
+ "#)
+ .file("bar/Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.1.0"
+ "#)
+ .file("bar/src/lib.rs", r#"
+ pub fn bar() {}
+ "#)
+ .file("bar/benches/bar.rs", r#"
+ #![feature(test)]
+ extern crate test;
+
+ use test::Bencher;
+
+ #[bench]
+ fn bench_bar(_: &mut Bencher) -> () { () }
+ "#)
+ .build();
+
+ assert_that(p.cargo("bench")
+ .arg("--all"),
+ execs().with_status(0)
+ .with_stderr_contains("\
+[RUNNING] target[/]release[/]deps[/]bar-[..][EXE]")
+ .with_stdout_contains("test bench_bar ... bench: [..]")
+ .with_stderr_contains("\
+[RUNNING] target[/]release[/]deps[/]foo-[..][EXE]")
+ .with_stdout_contains("test bench_foo ... bench: [..]"));
+}
+
+#[test]
+fn bench_all_exclude() {
+ if !is_nightly() { return }
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+
+ [workspace]
+ members = ["bar", "baz"]
+ "#)
+ .file("src/main.rs", r#"
+ fn main() {}
+ "#)
+ .file("bar/Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.1.0"
+ "#)
+ .file("bar/src/lib.rs", r#"
+ #![feature(test)]
+ #[cfg(test)]
+ extern crate test;
+
+ #[bench]
+ pub fn bar(b: &mut test::Bencher) {
+ b.iter(|| {});
+ }
+ "#)
+ .file("baz/Cargo.toml", r#"
+ [project]
+ name = "baz"
+ version = "0.1.0"
+ "#)
+ .file("baz/src/lib.rs", r#"
+ #[test]
+ pub fn baz() {
+ break_the_build();
+ }
+ "#)
+ .build();
+
+ assert_that(p.cargo("bench")
+ .arg("--all")
+ .arg("--exclude")
+ .arg("baz"),
+ execs().with_status(0)
+ .with_stdout_contains("\
+running 1 test
+test bar ... bench: [..] ns/iter (+/- [..])"));
+}
+
+#[test]
+fn bench_all_virtual_manifest() {
+ if !is_nightly() { return }
+
+ let p = project("workspace")
+ .file("Cargo.toml", r#"
+ [workspace]
+ members = ["foo", "bar"]
+ "#)
+ .file("foo/Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+ "#)
+ .file("foo/src/lib.rs", r#"
+ pub fn foo() {}
+ "#)
+ .file("foo/benches/foo.rs", r#"
+ #![feature(test)]
+ extern crate test;
+
+ use test::Bencher;
+
+ #[bench]
+ fn bench_foo(_: &mut Bencher) -> () { () }
+ "#)
+ .file("bar/Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.1.0"
+ "#)
+ .file("bar/src/lib.rs", r#"
+ pub fn bar() {}
+ "#)
+ .file("bar/benches/bar.rs", r#"
+ #![feature(test)]
+ extern crate test;
+
+ use test::Bencher;
+
+ #[bench]
+ fn bench_bar(_: &mut Bencher) -> () { () }
+ "#)
+ .build();
+
+ // The order in which foo and bar are built is not guaranteed
+ assert_that(p.cargo("bench")
+ .arg("--all"),
+ execs().with_status(0)
+ .with_stderr_contains("\
+[RUNNING] target[/]release[/]deps[/]bar-[..][EXE]")
+ .with_stdout_contains("test bench_bar ... bench: [..]")
+ .with_stderr_contains("\
+[RUNNING] target[/]release[/]deps[/]foo-[..][EXE]")
+ .with_stdout_contains("test bench_foo ... bench: [..]"));
+}
+
+// https://github.com/rust-lang/cargo/issues/4287
+#[test]
+fn legacy_bench_name() {
+ if !is_nightly() { return }
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+
+ [[bench]]
+ name = "bench"
+ "#)
+ .file("src/lib.rs", r#"
+ pub fn foo() {}
+ "#)
+ .file("src/bench.rs", r#"
+ #![feature(test)]
+ extern crate test;
+
+ use test::Bencher;
+
+ #[bench]
+ fn bench_foo(_: &mut Bencher) -> () { () }
+ "#)
+ .build();
+
+ assert_that(p.cargo("bench"), execs().with_status(0).with_stderr_contains("\
+[WARNING] path `[..]src[/]bench.rs` was erroneously implicitly accepted for benchmark `bench`,
+please set bench.path in Cargo.toml"));
+}
+
+#[test]
+fn bench_virtual_manifest_all_implied() {
+ if !is_nightly() { return }
+
+ let p = project("workspace")
+ .file("Cargo.toml", r#"
+ [workspace]
+ members = ["foo", "bar"]
+ "#)
+ .file("foo/Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+ "#)
+ .file("foo/src/lib.rs", r#"
+ pub fn foo() {}
+ "#)
+ .file("foo/benches/foo.rs", r#"
+ #![feature(test)]
+ extern crate test;
+ use test::Bencher;
+ #[bench]
+ fn bench_foo(_: &mut Bencher) -> () { () }
+ "#)
+ .file("bar/Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.1.0"
+ "#)
+ .file("bar/src/lib.rs", r#"
+ pub fn bar() {}
+ "#)
+ .file("bar/benches/bar.rs", r#"
+ #![feature(test)]
+ extern crate test;
+ use test::Bencher;
+ #[bench]
+ fn bench_bar(_: &mut Bencher) -> () { () }
+ "#)
+ .build();
+
+ // The order in which foo and bar are built is not guaranteed
+
+ assert_that(p.cargo("bench"),
+ execs().with_status(0)
+ .with_stderr_contains("\
+[RUNNING] target[/]release[/]deps[/]bar-[..][EXE]")
+ .with_stdout_contains("test bench_bar ... bench: [..]")
+ .with_stderr_contains("\
+[RUNNING] target[/]release[/]deps[/]foo-[..][EXE]")
+ .with_stdout_contains("test bench_foo ... bench: [..]"));
+}
--- /dev/null
+use std::env;
+use std::fs::{self, File};
+use std::io::prelude::*;
+
+use cargo::util::paths::dylib_path_envvar;
+use cargo::util::{process, ProcessBuilder};
+use cargotest::{is_nightly, rustc_host, sleep_ms};
+use cargotest::support::paths::{CargoPathExt,root};
+use cargotest::support::{ProjectBuilder};
+use cargotest::support::{project, execs, main_file, basic_bin_manifest};
+use cargotest::support::registry::Package;
+use cargotest::ChannelChanger;
+use hamcrest::{assert_that, existing_file, existing_dir, is_not};
+use tempdir::TempDir;
+
+#[test]
+fn cargo_compile_simple() {
+ let p = project("foo")
+ .file("Cargo.toml", &basic_bin_manifest("foo"))
+ .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
+ .build();
+
+ assert_that(p.cargo("build"), execs().with_status(0));
+ assert_that(&p.bin("foo"), existing_file());
+
+ assert_that(process(&p.bin("foo")),
+ execs().with_status(0).with_stdout("i am foo\n"));
+}
+
+#[test]
+fn cargo_fail_with_no_stderr() {
+ let p = project("foo")
+ .file("Cargo.toml", &basic_bin_manifest("foo"))
+ .file("src/foo.rs", &String::from("refusal"))
+ .build();
+ assert_that(p.cargo("build").arg("--message-format=json"), execs().with_status(101)
+ .with_stderr_does_not_contain("--- stderr"));
+}
+
+/// Check that the `CARGO_INCREMENTAL` environment variable results in
+/// `rustc` getting `-Zincremental` passed to it.
+#[test]
+fn cargo_compile_incremental() {
+ if !is_nightly() {
+ return
+ }
+
+ let p = project("foo")
+ .file("Cargo.toml", &basic_bin_manifest("foo"))
+ .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
+ .build();
+
+ assert_that(
+ p.cargo("build").arg("-v").env("CARGO_INCREMENTAL", "1"),
+ execs().with_stderr_contains(
+ "[RUNNING] `rustc [..] -C incremental=[..][/]target[/]debug[/]incremental[..]`\n")
+ .with_status(0));
+
+ assert_that(
+ p.cargo("test").arg("-v").env("CARGO_INCREMENTAL", "1"),
+ execs().with_stderr_contains(
+ "[RUNNING] `rustc [..] -C incremental=[..][/]target[/]debug[/]incremental[..]`\n")
+ .with_status(0));
+}
+
+#[test]
+fn incremental_profile() {
+ if !is_nightly() {
+ return
+ }
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+
+ [profile.dev]
+ incremental = false
+
+ [profile.release]
+ incremental = true
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ assert_that(
+ p.cargo("build").arg("-v").env_remove("CARGO_INCREMENTAL"),
+ execs().with_stderr_does_not_contain("[..]C incremental=[..]")
+ .with_status(0));
+
+ assert_that(
+ p.cargo("build").arg("-v").env("CARGO_INCREMENTAL", "1"),
+ execs().with_stderr_contains("[..]C incremental=[..]")
+ .with_status(0));
+
+ assert_that(
+ p.cargo("build").arg("--release").arg("-v").env_remove("CARGO_INCREMENTAL"),
+ execs().with_stderr_contains("[..]C incremental=[..]")
+ .with_status(0));
+
+ assert_that(
+ p.cargo("build").arg("--release").arg("-v").env("CARGO_INCREMENTAL", "0"),
+ execs().with_stderr_does_not_contain("[..]C incremental=[..]")
+ .with_status(0));
+}
+
+#[test]
+fn incremental_config() {
+ if !is_nightly() {
+ return
+ }
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .file(".cargo/config", r#"
+ [build]
+ incremental = false
+ "#)
+ .build();
+
+ assert_that(
+ p.cargo("build").arg("-v").env_remove("CARGO_INCREMENTAL"),
+ execs().with_stderr_does_not_contain("[..]C incremental=[..]")
+ .with_status(0));
+
+ assert_that(
+ p.cargo("build").arg("-v").env("CARGO_INCREMENTAL", "1"),
+ execs().with_stderr_contains("[..]C incremental=[..]")
+ .with_status(0));
+}
+
+#[test]
+fn cargo_compile_manifest_path() {
+ let p = project("foo")
+ .file("Cargo.toml", &basic_bin_manifest("foo"))
+ .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
+ .build();
+
+ assert_that(p.cargo("build")
+ .arg("--manifest-path").arg("foo/Cargo.toml")
+ .cwd(p.root().parent().unwrap()),
+ execs().with_status(0));
+ assert_that(&p.bin("foo"), existing_file());
+}
+
+#[test]
+fn cargo_compile_with_invalid_manifest() {
+ let p = project("foo")
+ .file("Cargo.toml", "")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs()
+ .with_status(101)
+ .with_stderr("\
+[ERROR] failed to parse manifest at `[..]`
+
+Caused by:
+ virtual manifests must be configured with [workspace]
+"))
+}
+
+#[test]
+fn cargo_compile_with_invalid_manifest2() {
+ let p = project("foo")
+ .file("Cargo.toml", r"
+ [project]
+ foo = bar
+ ")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs()
+ .with_status(101)
+ .with_stderr("\
+[ERROR] failed to parse manifest at `[..]`
+
+Caused by:
+ could not parse input as TOML
+
+Caused by:
+ invalid number at line 3
+"))
+}
+
+#[test]
+fn cargo_compile_with_invalid_manifest3() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/Cargo.toml", "a = bar")
+ .build();
+
+ assert_that(p.cargo("build").arg("--manifest-path")
+ .arg("src/Cargo.toml"),
+ execs()
+ .with_status(101)
+ .with_stderr("\
+[ERROR] failed to parse manifest at `[..]`
+
+Caused by:
+ could not parse input as TOML
+
+Caused by:
+ invalid number at line 1
+"))
+}
+
+#[test]
+fn cargo_compile_duplicate_build_targets() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [lib]
+ name = "main"
+ path = "src/main.rs"
+ crate-type = ["dylib"]
+
+ [dependencies]
+ "#)
+ .file("src/main.rs", r#"
+ #![allow(warnings)]
+ fn main() {}
+ "#)
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs()
+ .with_status(0)
+ .with_stderr("\
+warning: file found to be present in multiple build targets: [..]main.rs
+[COMPILING] foo v0.0.1 ([..])
+[FINISHED] [..]
+"));
+}
+
+#[test]
+fn cargo_compile_with_invalid_version() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ authors = []
+ version = "1.0"
+ "#)
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs()
+ .with_status(101)
+ .with_stderr("\
+[ERROR] failed to parse manifest at `[..]`
+
+Caused by:
+ Expected dot for key `project.version`
+"))
+
+}
+
+#[test]
+fn cargo_compile_with_invalid_package_name() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = ""
+ authors = []
+ version = "0.0.0"
+ "#)
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs()
+ .with_status(101)
+ .with_stderr("\
+[ERROR] failed to parse manifest at `[..]`
+
+Caused by:
+ package name cannot be an empty string
+"))
+}
+
+#[test]
+fn cargo_compile_with_invalid_bin_target_name() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ authors = []
+ version = "0.0.0"
+
+ [[bin]]
+ name = ""
+ "#)
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs()
+ .with_status(101)
+ .with_stderr("\
+[ERROR] failed to parse manifest at `[..]`
+
+Caused by:
+ binary target names cannot be empty
+"))
+}
+
+#[test]
+fn cargo_compile_with_forbidden_bin_target_name() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ authors = []
+ version = "0.0.0"
+
+ [[bin]]
+ name = "build"
+ "#)
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs()
+ .with_status(101)
+ .with_stderr("\
+[ERROR] failed to parse manifest at `[..]`
+
+Caused by:
+ the binary target name `build` is forbidden
+"))
+}
+
+#[test]
+fn cargo_compile_with_invalid_lib_target_name() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ authors = []
+ version = "0.0.0"
+
+ [lib]
+ name = ""
+ "#)
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs()
+ .with_status(101)
+ .with_stderr("\
+[ERROR] failed to parse manifest at `[..]`
+
+Caused by:
+ library target names cannot be empty
+"))
+}
+
+#[test]
+fn cargo_compile_without_manifest() {
+ let tmpdir = TempDir::new("cargo").unwrap();
+ let p = ProjectBuilder::new("foo", tmpdir.path().to_path_buf()).build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101)
+ .with_stderr("\
+[ERROR] could not find `Cargo.toml` in `[..]` or any parent directory
+"));
+}
+
+#[test]
+fn cargo_compile_with_invalid_code() {
+ let p = project("foo")
+ .file("Cargo.toml", &basic_bin_manifest("foo"))
+ .file("src/foo.rs", "invalid rust code!")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs()
+ .with_status(101)
+ .with_stderr_contains("\
+[ERROR] Could not compile `foo`.
+
+To learn more, run the command again with --verbose.\n"));
+ assert_that(&p.root().join("Cargo.lock"), existing_file());
+}
+
+#[test]
+fn cargo_compile_with_invalid_code_in_deps() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.bar]
+ path = "../bar"
+ [dependencies.baz]
+ path = "../baz"
+ "#)
+ .file("src/main.rs", "invalid rust code!")
+ .build();
+ let _bar = project("bar")
+ .file("Cargo.toml", &basic_bin_manifest("bar"))
+ .file("src/lib.rs", "invalid rust code!")
+ .build();
+ let _baz = project("baz")
+ .file("Cargo.toml", &basic_bin_manifest("baz"))
+ .file("src/lib.rs", "invalid rust code!")
+ .build();
+ assert_that(p.cargo("build"), execs().with_status(101));
+}
+
+#[test]
+fn cargo_compile_with_warnings_in_the_root_package() {
+ let p = project("foo")
+ .file("Cargo.toml", &basic_bin_manifest("foo"))
+ .file("src/foo.rs", "fn main() {} fn dead() {}")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr_contains("\
+[..]function is never used: `dead`[..]
+"));
+}
+
+#[test]
+fn cargo_compile_with_warnings_in_a_dep_package() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+
+ name = "foo"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+
+ [dependencies.bar]
+ path = "bar"
+
+ [[bin]]
+
+ name = "foo"
+ "#)
+ .file("src/foo.rs",
+ &main_file(r#""{}", bar::gimme()"#, &["bar"]))
+ .file("bar/Cargo.toml", r#"
+ [project]
+
+ name = "bar"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+
+ [lib]
+
+ name = "bar"
+ "#)
+ .file("bar/src/bar.rs", r#"
+ pub fn gimme() -> &'static str {
+ "test passed"
+ }
+
+ fn dead() {}
+ "#)
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr_contains("\
+[..]function is never used: `dead`[..]
+"));
+
+ assert_that(&p.bin("foo"), existing_file());
+
+ assert_that(
+ process(&p.bin("foo")),
+ execs().with_status(0).with_stdout("test passed\n"));
+}
+
+#[test]
+fn cargo_compile_with_nested_deps_inferred() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+
+ name = "foo"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+
+ [dependencies.bar]
+ path = 'bar'
+
+ [[bin]]
+ name = "foo"
+ "#)
+ .file("src/foo.rs",
+ &main_file(r#""{}", bar::gimme()"#, &["bar"]))
+ .file("bar/Cargo.toml", r#"
+ [project]
+
+ name = "bar"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+
+ [dependencies.baz]
+ path = "../baz"
+ "#)
+ .file("bar/src/lib.rs", r#"
+ extern crate baz;
+
+ pub fn gimme() -> String {
+ baz::gimme()
+ }
+ "#)
+ .file("baz/Cargo.toml", r#"
+ [project]
+
+ name = "baz"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+ "#)
+ .file("baz/src/lib.rs", r#"
+ pub fn gimme() -> String {
+ "test passed".to_string()
+ }
+ "#)
+ .build();
+
+ p.cargo("build")
+ .exec_with_output()
+ .unwrap();
+
+ assert_that(&p.bin("foo"), existing_file());
+ assert_that(&p.bin("libbar.rlib"), is_not(existing_file()));
+ assert_that(&p.bin("libbaz.rlib"), is_not(existing_file()));
+
+ assert_that(
+ process(&p.bin("foo")),
+ execs().with_status(0).with_stdout("test passed\n"));
+}
+
+#[test]
+fn cargo_compile_with_nested_deps_correct_bin() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+
+ name = "foo"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+
+ [dependencies.bar]
+ path = "bar"
+
+ [[bin]]
+ name = "foo"
+ "#)
+ .file("src/main.rs",
+ &main_file(r#""{}", bar::gimme()"#, &["bar"]))
+ .file("bar/Cargo.toml", r#"
+ [project]
+
+ name = "bar"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+
+ [dependencies.baz]
+ path = "../baz"
+ "#)
+ .file("bar/src/lib.rs", r#"
+ extern crate baz;
+
+ pub fn gimme() -> String {
+ baz::gimme()
+ }
+ "#)
+ .file("baz/Cargo.toml", r#"
+ [project]
+
+ name = "baz"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+ "#)
+ .file("baz/src/lib.rs", r#"
+ pub fn gimme() -> String {
+ "test passed".to_string()
+ }
+ "#)
+ .build();
+
+ p.cargo("build")
+ .exec_with_output()
+ .unwrap();
+
+ assert_that(&p.bin("foo"), existing_file());
+ assert_that(&p.bin("libbar.rlib"), is_not(existing_file()));
+ assert_that(&p.bin("libbaz.rlib"), is_not(existing_file()));
+
+ assert_that(
+ process(&p.bin("foo")),
+ execs().with_status(0).with_stdout("test passed\n"));
+}
+
+#[test]
+fn cargo_compile_with_nested_deps_shorthand() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+
+ name = "foo"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+
+ [dependencies.bar]
+ path = "bar"
+ "#)
+ .file("src/main.rs",
+ &main_file(r#""{}", bar::gimme()"#, &["bar"]))
+ .file("bar/Cargo.toml", r#"
+ [project]
+
+ name = "bar"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+
+ [dependencies.baz]
+ path = "../baz"
+
+ [lib]
+
+ name = "bar"
+ "#)
+ .file("bar/src/bar.rs", r#"
+ extern crate baz;
+
+ pub fn gimme() -> String {
+ baz::gimme()
+ }
+ "#)
+ .file("baz/Cargo.toml", r#"
+ [project]
+
+ name = "baz"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+
+ [lib]
+
+ name = "baz"
+ "#)
+ .file("baz/src/baz.rs", r#"
+ pub fn gimme() -> String {
+ "test passed".to_string()
+ }
+ "#)
+ .build();
+
+ p.cargo("build")
+ .exec_with_output()
+ .unwrap();
+
+ assert_that(&p.bin("foo"), existing_file());
+ assert_that(&p.bin("libbar.rlib"), is_not(existing_file()));
+ assert_that(&p.bin("libbaz.rlib"), is_not(existing_file()));
+
+ assert_that(
+ process(&p.bin("foo")),
+ execs().with_status(0).with_stdout("test passed\n"));
+}
+
+#[test]
+fn cargo_compile_with_nested_deps_longhand() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+
+ name = "foo"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+
+ [dependencies.bar]
+ path = "bar"
+ version = "0.5.0"
+
+ [[bin]]
+
+ name = "foo"
+ "#)
+ .file("src/foo.rs",
+ &main_file(r#""{}", bar::gimme()"#, &["bar"]))
+ .file("bar/Cargo.toml", r#"
+ [project]
+
+ name = "bar"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+
+ [dependencies.baz]
+ path = "../baz"
+ version = "0.5.0"
+
+ [lib]
+
+ name = "bar"
+ "#)
+ .file("bar/src/bar.rs", r#"
+ extern crate baz;
+
+ pub fn gimme() -> String {
+ baz::gimme()
+ }
+ "#)
+ .file("baz/Cargo.toml", r#"
+ [project]
+
+ name = "baz"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+
+ [lib]
+
+ name = "baz"
+ "#)
+ .file("baz/src/baz.rs", r#"
+ pub fn gimme() -> String {
+ "test passed".to_string()
+ }
+ "#)
+ .build();
+
+ assert_that(p.cargo("build"), execs());
+
+ assert_that(&p.bin("foo"), existing_file());
+ assert_that(&p.bin("libbar.rlib"), is_not(existing_file()));
+ assert_that(&p.bin("libbaz.rlib"), is_not(existing_file()));
+
+ assert_that(process(&p.bin("foo")),
+ execs().with_status(0).with_stdout("test passed\n"));
+}
+
+// Check that Cargo gives a sensible error if a dependency can't be found
+// because of a name mismatch.
+#[test]
+fn cargo_compile_with_dep_name_mismatch() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+
+ name = "foo"
+ version = "0.0.1"
+ authors = ["wycats@example.com"]
+
+ [[bin]]
+
+ name = "foo"
+
+ [dependencies.notquitebar]
+
+ path = "bar"
+ "#)
+ .file("src/bin/foo.rs", &main_file(r#""i am foo""#, &["bar"]))
+ .file("bar/Cargo.toml", &basic_bin_manifest("bar"))
+ .file("bar/src/bar.rs", &main_file(r#""i am bar""#, &[]))
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101).with_stderr(&format!(
+r#"error: no matching package named `notquitebar` found
+location searched: {proj_dir}/bar
+required by package `foo v0.0.1 ({proj_dir})`
+"#, proj_dir = p.url())));
+}
+
+#[test]
+fn cargo_compile_with_filename() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/lib.rs", "")
+ .file("src/bin/a.rs", r#"
+ extern crate foo;
+ fn main() { println!("hello a.rs"); }
+ "#)
+ .file("examples/a.rs", r#"
+ fn main() { println!("example"); }
+ "#)
+ .build();
+
+ assert_that(p.cargo("build").arg("--bin").arg("bin.rs"),
+ execs().with_status(101).with_stderr("\
+[ERROR] no bin target named `bin.rs`"));
+
+ assert_that(p.cargo("build").arg("--bin").arg("a.rs"),
+ execs().with_status(101).with_stderr("\
+[ERROR] no bin target named `a.rs`
+
+Did you mean `a`?"));
+
+ assert_that(p.cargo("build").arg("--example").arg("example.rs"),
+ execs().with_status(101).with_stderr("\
+[ERROR] no example target named `example.rs`"));
+
+ assert_that(p.cargo("build").arg("--example").arg("a.rs"),
+ execs().with_status(101).with_stderr("\
+[ERROR] no example target named `a.rs`
+
+Did you mean `a`?"));
+}
+
+#[test]
+fn cargo_compile_path_with_offline() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.bar]
+ path = "bar"
+ "#)
+ .file("src/lib.rs", "")
+ .file("bar/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("bar/src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build").masquerade_as_nightly_cargo().arg("-Zoffline"),
+ execs().with_status(0));
+}
+
+#[test]
+fn cargo_compile_with_downloaded_dependency_with_offline() {
+ Package::new("present_dep", "1.2.3")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "present_dep"
+ version = "1.2.3"
+ "#)
+ .file("src/lib.rs", "")
+ .publish();
+
+ {
+ // make package downloaded
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+
+ [dependencies]
+ present_dep = "1.2.3"
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+ assert_that(p.cargo("build"),execs().with_status(0));
+ }
+
+ let p2 = project("bar")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.1.0"
+
+ [dependencies]
+ present_dep = "1.2.3"
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(p2.cargo("build").masquerade_as_nightly_cargo().arg("-Zoffline"),
+ execs().with_status(0)
+ .with_stderr(format!("\
+[COMPILING] present_dep v1.2.3
+[COMPILING] bar v0.1.0 ([..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]")));
+
+}
+
+#[test]
+fn cargo_compile_offline_not_try_update() {
+ let p = project("bar")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.1.0"
+
+ [dependencies]
+ not_cached_dep = "1.2.5"
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build").masquerade_as_nightly_cargo().arg("-Zoffline"),
+ execs().with_status(101)
+ .with_stderr("\
+error: no matching package named `not_cached_dep` found
+location searched: registry `[..]`
+required by package `bar v0.1.0 ([..])`
+As a reminder, you're using offline mode (-Z offline) \
+which can sometimes cause surprising resolution failures, \
+if this error is too confusing you may with to retry \
+without the offline flag."));
+}
+
+#[test]
+fn compile_offline_without_maxvers_cached(){
+ Package::new("present_dep", "1.2.1").publish();
+ Package::new("present_dep", "1.2.2").publish();
+
+ Package::new("present_dep", "1.2.3")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "present_dep"
+ version = "1.2.3"
+ "#)
+ .file("src/lib.rs", r#"pub fn get_version()->&'static str {"1.2.3"}"#)
+ .publish();
+
+ Package::new("present_dep", "1.2.5")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "present_dep"
+ version = "1.2.5"
+ "#)
+ .file("src/lib.rs", r#"pub fn get_version(){"1.2.5"}"#)
+ .publish();
+
+ {
+ // make package cached
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+
+ [dependencies]
+ present_dep = "=1.2.3"
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+ assert_that(p.cargo("build"),execs().with_status(0));
+ }
+
+ let p2 = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+
+ [dependencies]
+ present_dep = "1.2"
+ "#)
+ .file("src/main.rs", "\
+extern crate present_dep;
+fn main(){
+ println!(\"{}\", present_dep::get_version());
+}")
+ .build();
+
+ assert_that(p2.cargo("run").masquerade_as_nightly_cargo().arg("-Zoffline"),
+ execs().with_status(0)
+ .with_stderr(format!("\
+[COMPILING] present_dep v1.2.3
+[COMPILING] foo v0.1.0 ({url})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+ Running `[..]`", url = p2.url()))
+ .with_stdout("1.2.3")
+ );
+}
+
+#[test]
+fn incompatible_dependencies() {
+ Package::new("bad", "0.1.0").publish();
+ Package::new("bad", "1.0.0").publish();
+ Package::new("bad", "1.0.1").publish();
+ Package::new("bad", "1.0.2").publish();
+ Package::new("foo", "0.1.0").dep("bad", "0.1.0").publish();
+ Package::new("bar", "0.1.1").dep("bad", "=1.0.0").publish();
+ Package::new("bar", "0.1.0").dep("bad", "=1.0.0").publish();
+ Package::new("baz", "0.1.2").dep("bad", ">=1.0.1").publish();
+ Package::new("baz", "0.1.1").dep("bad", ">=1.0.1").publish();
+ Package::new("baz", "0.1.0").dep("bad", ">=1.0.1").publish();
+
+ let p = project("transitive_load_test")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "incompatible_dependencies"
+ version = "0.0.1"
+
+ [dependencies]
+ foo = "0.1.0"
+ bar = "0.1.0"
+ baz = "0.1.0"
+ "#)
+ .file("src/main.rs", "fn main(){}")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101)
+ .with_stderr_contains("\
+error: failed to select a version for `bad`.
+all possible versions conflict with previously selected packages.
+required by package `baz v0.1.0`
+ ... which is depended on by `incompatible_dependencies v0.0.1 ([..])`
+ previously selected package `bad v1.0.0`
+ ... which is depended on by `bar v0.1.0`
+ ... which is depended on by `incompatible_dependencies v0.0.1 ([..])`
+ possible versions to select: 1.0.2, 1.0.1"));
+}
+
+#[test]
+fn incompatible_dependencies_with_multi_semver() {
+ Package::new("bad", "1.0.0").publish();
+ Package::new("bad", "1.0.1").publish();
+ Package::new("bad", "2.0.0").publish();
+ Package::new("bad", "2.0.1").publish();
+ Package::new("bar", "0.1.0").dep("bad", "=1.0.0").publish();
+ Package::new("baz", "0.1.0").dep("bad", ">=2.0.1").publish();
+
+ let p = project("transitive_load_test")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "incompatible_dependencies"
+ version = "0.0.1"
+
+ [dependencies]
+ bar = "0.1.0"
+ baz = "0.1.0"
+ bad = ">=1.0.1, <=2.0.0"
+ "#)
+ .file("src/main.rs", "fn main(){}")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101)
+ .with_stderr_contains("\
+error: failed to select a version for `bad`.
+all possible versions conflict with previously selected packages.
+required by package `incompatible_dependencies v0.0.1 ([..])`
+ previously selected package `bad v2.0.1`
+ ... which is depended on by `baz v0.1.0`
+ ... which is depended on by `incompatible_dependencies v0.0.1 ([..])`
+ previously selected package `bad v1.0.0`
+ ... which is depended on by `bar v0.1.0`
+ ... which is depended on by `incompatible_dependencies v0.0.1 ([..])`
+ possible versions to select: 2.0.0, 1.0.1"));
+}
+
+#[test]
+fn compile_offline_while_transitive_dep_not_cached() {
+ let bar = Package::new("bar", "1.0.0");
+ let bar_path = bar.archive_dst();
+ bar.publish();
+
+ let mut content = Vec::new();
+
+ let mut file = File::open(bar_path.clone()).ok().unwrap();
+ let _ok = file.read_to_end(&mut content).ok().unwrap();
+ drop(file);
+ drop(File::create(bar_path.clone()).ok().unwrap() );
+
+ Package::new("foo", "0.1.0").dep("bar", "1.0.0").publish();
+
+ let p = project("transitive_load_test")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "transitive_load_test"
+ version = "0.0.1"
+
+ [dependencies]
+ foo = "0.1.0"
+ "#)
+ .file("src/main.rs", "fn main(){}")
+ .build();
+
+ // simulate download foo, but fail to download bar
+ let _out = p.cargo("build").exec_with_output();
+
+ drop( File::create(bar_path).ok().unwrap().write_all(&content) );
+
+ assert_that(p.cargo("build").masquerade_as_nightly_cargo().arg("-Zoffline"),
+ execs().with_status(101)
+ .with_stderr("\
+error: no matching package named `bar` found
+location searched: registry `[..]`
+required by package `foo v0.1.0`
+ ... which is depended on by `transitive_load_test v0.0.1 ([..]/transitive_load_test)`
+As a reminder, you're using offline mode (-Z offline) \
+which can sometimes cause surprising resolution failures, \
+if this error is too confusing you may with to retry \
+without the offline flag."));
+}
+
+#[test]
+fn compile_path_dep_then_change_version() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.bar]
+ path = "bar"
+ "#)
+ .file("src/lib.rs", "")
+ .file("bar/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("bar/src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"), execs().with_status(0));
+
+ File::create(&p.root().join("bar/Cargo.toml")).unwrap().write_all(br#"
+ [package]
+ name = "bar"
+ version = "0.0.2"
+ authors = []
+ "#).unwrap();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101).with_stderr("\
+error: no matching version `= 0.0.1` found for package `bar`
+location searched: [..]
+versions found: 0.0.2
+required by package `foo v0.0.1 ([..]/foo)`
+consider running `cargo update` to update a path dependency's locked version
+"));
+}
+
+#[test]
+fn ignores_carriage_return_in_lockfile() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ authors = []
+ version = "0.0.1"
+ "#)
+ .file("src/main.rs", r#"
+ mod a; fn main() {}
+ "#)
+ .file("src/a.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0));
+
+ let lockfile = p.root().join("Cargo.lock");
+ let mut lock = String::new();
+ File::open(&lockfile).unwrap().read_to_string(&mut lock).unwrap();
+ let lock = lock.replace("\n", "\r\n");
+ File::create(&lockfile).unwrap().write_all(lock.as_bytes()).unwrap();
+ assert_that(p.cargo("build"),
+ execs().with_status(0));
+}
+
+#[test]
+fn cargo_default_env_metadata_env_var() {
+ // Ensure that path dep + dylib + env_var get metadata
+ // (even though path_dep + dylib should not)
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.bar]
+ path = "bar"
+ "#)
+ .file("src/lib.rs", "// hi")
+ .file("bar/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+
+ [lib]
+ name = "bar"
+ crate_type = ["dylib"]
+ "#)
+ .file("bar/src/lib.rs", "// hello")
+ .build();
+
+ // No metadata on libbar since it's a dylib path dependency
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(0).with_stderr(&format!("\
+[COMPILING] bar v0.0.1 ({url}/bar)
+[RUNNING] `rustc --crate-name bar bar[/]src[/]lib.rs --crate-type dylib \
+ --emit=dep-info,link \
+ -C prefer-dynamic -C debuginfo=2 \
+ -C metadata=[..] \
+ --out-dir [..] \
+ -L dependency={dir}[/]target[/]debug[/]deps`
+[COMPILING] foo v0.0.1 ({url})
+[RUNNING] `rustc --crate-name foo src[/]lib.rs --crate-type lib \
+ --emit=dep-info,link -C debuginfo=2 \
+ -C metadata=[..] \
+ -C extra-filename=[..] \
+ --out-dir [..] \
+ -L dependency={dir}[/]target[/]debug[/]deps \
+ --extern bar={dir}[/]target[/]debug[/]deps[/]{prefix}bar{suffix}`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]",
+dir = p.root().display(),
+url = p.url(),
+prefix = env::consts::DLL_PREFIX,
+suffix = env::consts::DLL_SUFFIX,
+)));
+
+ assert_that(p.cargo("clean"), execs().with_status(0));
+
+ // If you set the env-var, then we expect metadata on libbar
+ assert_that(p.cargo("build").arg("-v").env("__CARGO_DEFAULT_LIB_METADATA", "stable"),
+ execs().with_status(0).with_stderr(&format!("\
+[COMPILING] bar v0.0.1 ({url}/bar)
+[RUNNING] `rustc --crate-name bar bar[/]src[/]lib.rs --crate-type dylib \
+ --emit=dep-info,link \
+ -C prefer-dynamic -C debuginfo=2 \
+ -C metadata=[..] \
+ --out-dir [..] \
+ -L dependency={dir}[/]target[/]debug[/]deps`
+[COMPILING] foo v0.0.1 ({url})
+[RUNNING] `rustc --crate-name foo src[/]lib.rs --crate-type lib \
+ --emit=dep-info,link -C debuginfo=2 \
+ -C metadata=[..] \
+ -C extra-filename=[..] \
+ --out-dir [..] \
+ -L dependency={dir}[/]target[/]debug[/]deps \
+ --extern bar={dir}[/]target[/]debug[/]deps[/]{prefix}bar-[..]{suffix}`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+",
+dir = p.root().display(),
+url = p.url(),
+prefix = env::consts::DLL_PREFIX,
+suffix = env::consts::DLL_SUFFIX,
+)));
+}
+
+#[test]
+fn crate_env_vars() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.5.1-alpha.1"
+ description = "This is foo"
+ homepage = "http://example.com"
+ authors = ["wycats@example.com"]
+ "#)
+ .file("src/main.rs", r#"
+ extern crate foo;
+
+
+ static VERSION_MAJOR: &'static str = env!("CARGO_PKG_VERSION_MAJOR");
+ static VERSION_MINOR: &'static str = env!("CARGO_PKG_VERSION_MINOR");
+ static VERSION_PATCH: &'static str = env!("CARGO_PKG_VERSION_PATCH");
+ static VERSION_PRE: &'static str = env!("CARGO_PKG_VERSION_PRE");
+ static VERSION: &'static str = env!("CARGO_PKG_VERSION");
+ static CARGO_MANIFEST_DIR: &'static str = env!("CARGO_MANIFEST_DIR");
+ static PKG_NAME: &'static str = env!("CARGO_PKG_NAME");
+ static HOMEPAGE: &'static str = env!("CARGO_PKG_HOMEPAGE");
+ static DESCRIPTION: &'static str = env!("CARGO_PKG_DESCRIPTION");
+
+ fn main() {
+ let s = format!("{}-{}-{} @ {} in {}", VERSION_MAJOR,
+ VERSION_MINOR, VERSION_PATCH, VERSION_PRE,
+ CARGO_MANIFEST_DIR);
+ assert_eq!(s, foo::version());
+ println!("{}", s);
+ assert_eq!("foo", PKG_NAME);
+ assert_eq!("http://example.com", HOMEPAGE);
+ assert_eq!("This is foo", DESCRIPTION);
+ let s = format!("{}.{}.{}-{}", VERSION_MAJOR,
+ VERSION_MINOR, VERSION_PATCH, VERSION_PRE);
+ assert_eq!(s, VERSION);
+ }
+ "#)
+ .file("src/lib.rs", r#"
+ pub fn version() -> String {
+ format!("{}-{}-{} @ {} in {}",
+ env!("CARGO_PKG_VERSION_MAJOR"),
+ env!("CARGO_PKG_VERSION_MINOR"),
+ env!("CARGO_PKG_VERSION_PATCH"),
+ env!("CARGO_PKG_VERSION_PRE"),
+ env!("CARGO_MANIFEST_DIR"))
+ }
+ "#)
+ .build();
+
+ println!("build");
+ assert_that(p.cargo("build").arg("-v"), execs().with_status(0));
+
+ println!("bin");
+ assert_that(process(&p.bin("foo")),
+ execs().with_status(0).with_stdout(&format!("0-5-1 @ alpha.1 in {}\n",
+ p.root().display())));
+
+ println!("test");
+ assert_that(p.cargo("test").arg("-v"),
+ execs().with_status(0));
+}
+
+#[test]
+fn crate_authors_env_vars() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.5.1-alpha.1"
+ authors = ["wycats@example.com", "neikos@example.com"]
+ "#)
+ .file("src/main.rs", r#"
+ extern crate foo;
+
+ static AUTHORS: &'static str = env!("CARGO_PKG_AUTHORS");
+
+ fn main() {
+ let s = "wycats@example.com:neikos@example.com";
+ assert_eq!(AUTHORS, foo::authors());
+ println!("{}", AUTHORS);
+ assert_eq!(s, AUTHORS);
+ }
+ "#)
+ .file("src/lib.rs", r#"
+ pub fn authors() -> String {
+ format!("{}", env!("CARGO_PKG_AUTHORS"))
+ }
+ "#)
+ .build();
+
+ println!("build");
+ assert_that(p.cargo("build").arg("-v"), execs().with_status(0));
+
+ println!("bin");
+ assert_that(process(&p.bin("foo")),
+ execs().with_status(0).with_stdout("wycats@example.com:neikos@example.com"));
+
+ println!("test");
+ assert_that(p.cargo("test").arg("-v"),
+ execs().with_status(0));
+}
+
+// The tester may already have LD_LIBRARY_PATH=::/foo/bar which leads to a false positive error
+fn setenv_for_removing_empty_component(mut p: ProcessBuilder) -> ProcessBuilder {
+ let v = dylib_path_envvar();
+ if let Ok(search_path) = env::var(v) {
+ let new_search_path =
+ env::join_paths(env::split_paths(&search_path).filter(|e| !e.as_os_str().is_empty()))
+ .expect("join_paths");
+ p.env(v, new_search_path); // build_command() will override LD_LIBRARY_PATH accordingly
+ }
+ p
+}
+
+// Regression test for #4277
+#[test]
+fn crate_library_path_env_var() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/main.rs", &format!(r##"
+ fn main() {{
+ let search_path = env!("{}");
+ let paths = std::env::split_paths(&search_path).collect::<Vec<_>>();
+ assert!(!paths.contains(&"".into()));
+ }}
+ "##, dylib_path_envvar()))
+ .build();
+
+ assert_that(setenv_for_removing_empty_component(p.cargo("run")),
+ execs().with_status(0));
+}
+
+// Regression test for #4277
+#[test]
+fn build_with_fake_libc_not_loading() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/main.rs", r#"
+ fn main() {}
+ "#)
+ .file("src/lib.rs", r#" "#)
+ .file("libc.so.6", r#""#)
+ .build();
+
+ assert_that(setenv_for_removing_empty_component(p.cargo("build")),
+ execs().with_status(0));
+}
+
+// this is testing that src/<pkg-name>.rs still works (for now)
+#[test]
+fn many_crate_types_old_style_lib_location() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+
+ name = "foo"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+
+ [lib]
+
+ name = "foo"
+ crate_type = ["rlib", "dylib"]
+ "#)
+ .file("src/foo.rs", r#"
+ pub fn foo() {}
+ "#)
+ .build();
+ assert_that(p.cargo("build"), execs().with_status(0).with_stderr_contains("\
+[WARNING] path `[..]src[/]foo.rs` was erroneously implicitly accepted for library `foo`,
+please rename the file to `src/lib.rs` or set lib.path in Cargo.toml"));
+
+ assert_that(&p.root().join("target/debug/libfoo.rlib"), existing_file());
+ let fname = format!("{}foo{}", env::consts::DLL_PREFIX,
+ env::consts::DLL_SUFFIX);
+ assert_that(&p.root().join("target/debug").join(&fname), existing_file());
+}
+
+#[test]
+fn many_crate_types_correct() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+
+ name = "foo"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+
+ [lib]
+
+ name = "foo"
+ crate_type = ["rlib", "dylib"]
+ "#)
+ .file("src/lib.rs", r#"
+ pub fn foo() {}
+ "#)
+ .build();
+ assert_that(p.cargo("build"),
+ execs().with_status(0));
+
+ assert_that(&p.root().join("target/debug/libfoo.rlib"), existing_file());
+ let fname = format!("{}foo{}", env::consts::DLL_PREFIX,
+ env::consts::DLL_SUFFIX);
+ assert_that(&p.root().join("target/debug").join(&fname), existing_file());
+}
+
+#[test]
+fn self_dependency() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+
+ name = "test"
+ version = "0.0.0"
+ authors = []
+
+ [dependencies.test]
+
+ path = "."
+
+ [lib]
+ name = "test"
+ path = "src/test.rs"
+ "#)
+ .file("src/test.rs", "fn main() {}")
+ .build();
+ assert_that(p.cargo("build"),
+ execs().with_status(101)
+ .with_stderr("\
+[ERROR] cyclic package dependency: package `test v0.0.0 ([..])` depends on itself
+"));
+}
+
+#[test]
+fn ignore_broken_symlinks() {
+ // windows and symlinks don't currently agree that well
+ if cfg!(windows) { return }
+
+ let p = project("foo")
+ .file("Cargo.toml", &basic_bin_manifest("foo"))
+ .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
+ .symlink("Notafile", "bar")
+ .build();
+
+ assert_that(p.cargo("build"), execs().with_status(0));
+ assert_that(&p.bin("foo"), existing_file());
+
+ assert_that(process(&p.bin("foo")),
+ execs().with_status(0).with_stdout("i am foo\n"));
+}
+
+#[test]
+fn missing_lib_and_bin() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+
+ name = "test"
+ version = "0.0.0"
+ authors = []
+ "#)
+ .build();
+ assert_that(p.cargo("build"),
+ execs().with_status(101)
+ .with_stderr("\
+[ERROR] failed to parse manifest at `[..]Cargo.toml`
+
+Caused by:
+ no targets specified in the manifest
+ either src/lib.rs, src/main.rs, a [lib] section, or [[bin]] section must be present\n"));
+}
+
+#[test]
+fn lto_build() {
+ // FIXME: currently this hits a linker bug on 32-bit MSVC
+ if cfg!(all(target_env = "msvc", target_pointer_width = "32")) {
+ return
+ }
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+
+ name = "test"
+ version = "0.0.0"
+ authors = []
+
+ [profile.release]
+ lto = true
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+ assert_that(p.cargo("build").arg("-v").arg("--release"),
+ execs().with_status(0).with_stderr(&format!("\
+[COMPILING] test v0.0.0 ({url})
+[RUNNING] `rustc --crate-name test src[/]main.rs --crate-type bin \
+ --emit=dep-info,link \
+ -C opt-level=3 \
+ -C lto \
+ -C metadata=[..] \
+ --out-dir {dir}[/]target[/]release[/]deps \
+ -L dependency={dir}[/]target[/]release[/]deps`
+[FINISHED] release [optimized] target(s) in [..]
+",
+dir = p.root().display(),
+url = p.url(),
+)));
+}
+
+#[test]
+fn verbose_build() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+
+ name = "test"
+ version = "0.0.0"
+ authors = []
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(0).with_stderr(&format!("\
+[COMPILING] test v0.0.0 ({url})
+[RUNNING] `rustc --crate-name test src[/]lib.rs --crate-type lib \
+ --emit=dep-info,link -C debuginfo=2 \
+ -C metadata=[..] \
+ --out-dir [..] \
+ -L dependency={dir}[/]target[/]debug[/]deps`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+",
+dir = p.root().display(),
+url = p.url(),
+)));
+}
+
+#[test]
+fn verbose_release_build() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+
+ name = "test"
+ version = "0.0.0"
+ authors = []
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+ assert_that(p.cargo("build").arg("-v").arg("--release"),
+ execs().with_status(0).with_stderr(&format!("\
+[COMPILING] test v0.0.0 ({url})
+[RUNNING] `rustc --crate-name test src[/]lib.rs --crate-type lib \
+ --emit=dep-info,link \
+ -C opt-level=3 \
+ -C metadata=[..] \
+ --out-dir [..] \
+ -L dependency={dir}[/]target[/]release[/]deps`
+[FINISHED] release [optimized] target(s) in [..]
+",
+dir = p.root().display(),
+url = p.url(),
+)));
+}
+
+#[test]
+fn verbose_release_build_deps() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+
+ name = "test"
+ version = "0.0.0"
+ authors = []
+
+ [dependencies.foo]
+ path = "foo"
+ "#)
+ .file("src/lib.rs", "")
+ .file("foo/Cargo.toml", r#"
+ [package]
+
+ name = "foo"
+ version = "0.0.0"
+ authors = []
+
+ [lib]
+ name = "foo"
+ crate_type = ["dylib", "rlib"]
+ "#)
+ .file("foo/src/lib.rs", "")
+ .build();
+ assert_that(p.cargo("build").arg("-v").arg("--release"),
+ execs().with_status(0).with_stderr(&format!("\
+[COMPILING] foo v0.0.0 ({url}/foo)
+[RUNNING] `rustc --crate-name foo foo[/]src[/]lib.rs \
+ --crate-type dylib --crate-type rlib \
+ --emit=dep-info,link \
+ -C prefer-dynamic \
+ -C opt-level=3 \
+ -C metadata=[..] \
+ --out-dir [..] \
+ -L dependency={dir}[/]target[/]release[/]deps`
+[COMPILING] test v0.0.0 ({url})
+[RUNNING] `rustc --crate-name test src[/]lib.rs --crate-type lib \
+ --emit=dep-info,link \
+ -C opt-level=3 \
+ -C metadata=[..] \
+ --out-dir [..] \
+ -L dependency={dir}[/]target[/]release[/]deps \
+ --extern foo={dir}[/]target[/]release[/]deps[/]{prefix}foo{suffix} \
+ --extern foo={dir}[/]target[/]release[/]deps[/]libfoo.rlib`
+[FINISHED] release [optimized] target(s) in [..]
+",
+ dir = p.root().display(),
+ url = p.url(),
+ prefix = env::consts::DLL_PREFIX,
+ suffix = env::consts::DLL_SUFFIX)));
+}
+
+#[test]
+fn explicit_examples() {
+ let p = project("world")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "world"
+ version = "1.0.0"
+ authors = []
+
+ [lib]
+ name = "world"
+ path = "src/lib.rs"
+
+ [[example]]
+ name = "hello"
+ path = "examples/ex-hello.rs"
+
+ [[example]]
+ name = "goodbye"
+ path = "examples/ex-goodbye.rs"
+ "#)
+ .file("src/lib.rs", r#"
+ pub fn get_hello() -> &'static str { "Hello" }
+ pub fn get_goodbye() -> &'static str { "Goodbye" }
+ pub fn get_world() -> &'static str { "World" }
+ "#)
+ .file("examples/ex-hello.rs", r#"
+ extern crate world;
+ fn main() { println!("{}, {}!", world::get_hello(), world::get_world()); }
+ "#)
+ .file("examples/ex-goodbye.rs", r#"
+ extern crate world;
+ fn main() { println!("{}, {}!", world::get_goodbye(), world::get_world()); }
+ "#)
+ .build();
+
+ assert_that(p.cargo("test").arg("-v"), execs().with_status(0));
+ assert_that(process(&p.bin("examples/hello")),
+ execs().with_status(0).with_stdout("Hello, World!\n"));
+ assert_that(process(&p.bin("examples/goodbye")),
+ execs().with_status(0).with_stdout("Goodbye, World!\n"));
+}
+
+#[test]
+fn non_existing_example() {
+ let p = project("world")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "world"
+ version = "1.0.0"
+ authors = []
+
+ [lib]
+ name = "world"
+ path = "src/lib.rs"
+
+ [[example]]
+ name = "hello"
+ "#)
+ .file("src/lib.rs", "")
+ .file("examples/ehlo.rs", "")
+ .build();
+
+ assert_that(p.cargo("test").arg("-v"), execs().with_status(101).with_stderr("\
+[ERROR] failed to parse manifest at `[..]`
+
+Caused by:
+ can't find `hello` example, specify example.path"));
+}
+
+#[test]
+fn non_existing_binary() {
+ let p = project("world")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "world"
+ version = "1.0.0"
+ authors = []
+
+ [[bin]]
+ name = "hello"
+ "#)
+ .file("src/lib.rs", "")
+ .file("src/bin/ehlo.rs", "")
+ .build();
+
+ assert_that(p.cargo("build").arg("-v"), execs().with_status(101).with_stderr("\
+[ERROR] failed to parse manifest at `[..]`
+
+Caused by:
+ can't find `hello` bin, specify bin.path"));
+}
+
+#[test]
+fn legacy_binary_paths_warinigs() {
+ let p = project("world")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "1.0.0"
+ authors = []
+
+ [[bin]]
+ name = "bar"
+ "#)
+ .file("src/lib.rs", "")
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("build").arg("-v"), execs().with_status(0).with_stderr_contains("\
+[WARNING] path `[..]src[/]main.rs` was erroneously implicitly accepted for binary `bar`,
+please set bin.path in Cargo.toml"));
+
+ let p = project("world")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "1.0.0"
+ authors = []
+
+ [[bin]]
+ name = "bar"
+ "#)
+ .file("src/lib.rs", "")
+ .file("src/bin/main.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("build").arg("-v"), execs().with_status(0).with_stderr_contains("\
+[WARNING] path `[..]src[/]bin[/]main.rs` was erroneously implicitly accepted for binary `bar`,
+please set bin.path in Cargo.toml"));
+
+ let p = project("world")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "1.0.0"
+ authors = []
+
+ [[bin]]
+ name = "bar"
+ "#)
+ .file("src/bar.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("build").arg("-v"), execs().with_status(0).with_stderr_contains("\
+[WARNING] path `[..]src[/]bar.rs` was erroneously implicitly accepted for binary `bar`,
+please set bin.path in Cargo.toml"));
+}
+
+#[test]
+fn implicit_examples() {
+ let p = project("world")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "world"
+ version = "1.0.0"
+ authors = []
+ "#)
+ .file("src/lib.rs", r#"
+ pub fn get_hello() -> &'static str { "Hello" }
+ pub fn get_goodbye() -> &'static str { "Goodbye" }
+ pub fn get_world() -> &'static str { "World" }
+ "#)
+ .file("examples/hello.rs", r#"
+ extern crate world;
+ fn main() {
+ println!("{}, {}!", world::get_hello(), world::get_world());
+ }
+ "#)
+ .file("examples/goodbye.rs", r#"
+ extern crate world;
+ fn main() {
+ println!("{}, {}!", world::get_goodbye(), world::get_world());
+ }
+ "#)
+ .build();
+
+ assert_that(p.cargo("test"), execs().with_status(0));
+ assert_that(process(&p.bin("examples/hello")),
+ execs().with_status(0).with_stdout("Hello, World!\n"));
+ assert_that(process(&p.bin("examples/goodbye")),
+ execs().with_status(0).with_stdout("Goodbye, World!\n"));
+}
+
+#[test]
+fn standard_build_no_ndebug() {
+ let p = project("world")
+ .file("Cargo.toml", &basic_bin_manifest("foo"))
+ .file("src/foo.rs", r#"
+ fn main() {
+ if cfg!(debug_assertions) {
+ println!("slow")
+ } else {
+ println!("fast")
+ }
+ }
+ "#)
+ .build();
+
+ assert_that(p.cargo("build"), execs().with_status(0));
+ assert_that(process(&p.bin("foo")),
+ execs().with_status(0).with_stdout("slow\n"));
+}
+
+#[test]
+fn release_build_ndebug() {
+ let p = project("world")
+ .file("Cargo.toml", &basic_bin_manifest("foo"))
+ .file("src/foo.rs", r#"
+ fn main() {
+ if cfg!(debug_assertions) {
+ println!("slow")
+ } else {
+ println!("fast")
+ }
+ }
+ "#)
+ .build();
+
+ assert_that(p.cargo("build").arg("--release"),
+ execs().with_status(0));
+ assert_that(process(&p.release_bin("foo")),
+ execs().with_status(0).with_stdout("fast\n"));
+}
+
+#[test]
+fn inferred_main_bin() {
+ let p = project("world")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/main.rs", r#"
+ fn main() {}
+ "#)
+ .build();
+
+ assert_that(p.cargo("build"), execs().with_status(0));
+ assert_that(process(&p.bin("foo")), execs().with_status(0));
+}
+
+#[test]
+fn deletion_causes_failure() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.bar]
+ path = "bar"
+ "#)
+ .file("src/main.rs", r#"
+ extern crate bar;
+ fn main() {}
+ "#)
+ .file("bar/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("bar/src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"), execs().with_status(0));
+ p.change_file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#);
+ assert_that(p.cargo("build"), execs().with_status(101));
+}
+
+#[test]
+fn bad_cargo_toml_in_target_dir() {
+ let p = project("world")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/main.rs", r#"
+ fn main() {}
+ "#)
+ .file("target/Cargo.toml", "bad-toml")
+ .build();
+
+ assert_that(p.cargo("build"), execs().with_status(0));
+ assert_that(process(&p.bin("foo")), execs().with_status(0));
+}
+
+#[test]
+fn lib_with_standard_name() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "syntax"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/lib.rs", "
+ pub fn foo() {}
+ ")
+ .file("src/main.rs", "
+ extern crate syntax;
+ fn main() { syntax::foo() }
+ ")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0)
+ .with_stderr(&format!("\
+[COMPILING] syntax v0.0.1 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+",
+ dir = p.url())));
+}
+
+#[test]
+fn simple_staticlib() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ authors = []
+ version = "0.0.1"
+
+ [lib]
+ name = "foo"
+ crate-type = ["staticlib"]
+ "#)
+ .file("src/lib.rs", "pub fn foo() {}")
+ .build();
+
+ // env var is a test for #1381
+ assert_that(p.cargo("build").env("RUST_LOG", "nekoneko=trace"),
+ execs().with_status(0));
+}
+
+#[test]
+fn staticlib_rlib_and_bin() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ authors = []
+ version = "0.0.1"
+
+ [lib]
+ name = "foo"
+ crate-type = ["staticlib", "rlib"]
+ "#)
+ .file("src/lib.rs", "pub fn foo() {}")
+ .file("src/main.rs", r#"
+ extern crate foo;
+
+ fn main() {
+ foo::foo();
+ }"#)
+ .build();
+
+ assert_that(p.cargo("build").arg("-v"), execs().with_status(0));
+}
+
+#[test]
+fn opt_out_of_bin() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ bin = []
+
+ [package]
+ name = "foo"
+ authors = []
+ version = "0.0.1"
+ "#)
+ .file("src/lib.rs", "")
+ .file("src/main.rs", "bad syntax")
+ .build();
+ assert_that(p.cargo("build"), execs().with_status(0));
+}
+
+#[test]
+fn single_lib() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ authors = []
+ version = "0.0.1"
+
+ [lib]
+ name = "foo"
+ path = "src/bar.rs"
+ "#)
+ .file("src/bar.rs", "")
+ .build();
+ assert_that(p.cargo("build"), execs().with_status(0));
+}
+
+#[test]
+fn freshness_ignores_excluded() {
+ let foo = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.0"
+ authors = []
+ build = "build.rs"
+ exclude = ["src/b*.rs"]
+ "#)
+ .file("build.rs", "fn main() {}")
+ .file("src/lib.rs", "pub fn bar() -> i32 { 1 }")
+ .build();
+ foo.root().move_into_the_past();
+
+ assert_that(foo.cargo("build"),
+ execs().with_status(0)
+ .with_stderr(&format!("\
+[COMPILING] foo v0.0.0 ({url})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+", url = foo.url())));
+
+ // Smoke test to make sure it doesn't compile again
+ println!("first pass");
+ assert_that(foo.cargo("build"),
+ execs().with_status(0)
+ .with_stdout(""));
+
+ // Modify an ignored file and make sure we don't rebuild
+ println!("second pass");
+ File::create(&foo.root().join("src/bar.rs")).unwrap();
+ assert_that(foo.cargo("build"),
+ execs().with_status(0)
+ .with_stdout(""));
+}
+
+#[test]
+fn rebuild_preserves_out_dir() {
+ let foo = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.0"
+ authors = []
+ build = 'build.rs'
+ "#)
+ .file("build.rs", r#"
+ use std::env;
+ use std::fs::File;
+ use std::path::Path;
+
+ fn main() {
+ let path = Path::new(&env::var("OUT_DIR").unwrap()).join("foo");
+ if env::var_os("FIRST").is_some() {
+ File::create(&path).unwrap();
+ } else {
+ File::create(&path).unwrap();
+ }
+ }
+ "#)
+ .file("src/lib.rs", "pub fn bar() -> i32 { 1 }")
+ .build();
+ foo.root().move_into_the_past();
+
+ assert_that(foo.cargo("build").env("FIRST", "1"),
+ execs().with_status(0)
+ .with_stderr(&format!("\
+[COMPILING] foo v0.0.0 ({url})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+", url = foo.url())));
+
+ File::create(&foo.root().join("src/bar.rs")).unwrap();
+ assert_that(foo.cargo("build"),
+ execs().with_status(0)
+ .with_stderr(&format!("\
+[COMPILING] foo v0.0.0 ({url})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+", url = foo.url())));
+}
+
+#[test]
+fn dep_no_libs() {
+ let foo = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.0"
+ authors = []
+
+ [dependencies.bar]
+ path = "bar"
+ "#)
+ .file("src/lib.rs", "pub fn bar() -> i32 { 1 }")
+ .file("bar/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.0"
+ authors = []
+ "#)
+ .file("bar/src/main.rs", "")
+ .build();
+ assert_that(foo.cargo("build"),
+ execs().with_status(0));
+}
+
+#[test]
+fn recompile_space_in_name() {
+ let foo = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.0"
+ authors = []
+
+ [lib]
+ name = "foo"
+ path = "src/my lib.rs"
+ "#)
+ .file("src/my lib.rs", "")
+ .build();
+ assert_that(foo.cargo("build"), execs().with_status(0));
+ foo.root().move_into_the_past();
+ assert_that(foo.cargo("build"),
+ execs().with_status(0).with_stdout(""));
+}
+
+#[cfg(unix)]
+#[test]
+fn ignore_bad_directories() {
+ use std::os::unix::prelude::*;
+ let foo = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.0"
+ authors = []
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+ let dir = foo.root().join("tmp");
+ fs::create_dir(&dir).unwrap();
+ let stat = fs::metadata(&dir).unwrap();
+ let mut perms = stat.permissions();
+ perms.set_mode(0o644);
+ fs::set_permissions(&dir, perms.clone()).unwrap();
+ assert_that(foo.cargo("build"),
+ execs().with_status(0));
+ perms.set_mode(0o755);
+ fs::set_permissions(&dir, perms).unwrap();
+}
+
+#[test]
+fn bad_cargo_config() {
+ let foo = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.0"
+ authors = []
+ "#)
+ .file("src/lib.rs", "")
+ .file(".cargo/config", r#"
+ this is not valid toml
+ "#)
+ .build();
+ assert_that(foo.cargo("build").arg("-v"),
+ execs().with_status(101).with_stderr("\
+[ERROR] Couldn't load Cargo configuration
+
+Caused by:
+ could not parse TOML configuration in `[..]`
+
+Caused by:
+ could not parse input as TOML
+
+Caused by:
+ expected an equals, found an identifier at line 2
+"));
+}
+
+#[test]
+fn cargo_platform_specific_dependency() {
+ let host = rustc_host();
+ let p = project("foo")
+ .file("Cargo.toml", &format!(r#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+ build = "build.rs"
+
+ [target.{host}.dependencies]
+ dep = {{ path = "dep" }}
+ [target.{host}.build-dependencies]
+ build = {{ path = "build" }}
+ [target.{host}.dev-dependencies]
+ dev = {{ path = "dev" }}
+ "#, host = host))
+ .file("src/main.rs", r#"
+ extern crate dep;
+ fn main() { dep::dep() }
+ "#)
+ .file("tests/foo.rs", r#"
+ extern crate dev;
+ #[test]
+ fn foo() { dev::dev() }
+ "#)
+ .file("build.rs", r#"
+ extern crate build;
+ fn main() { build::build(); }
+ "#)
+ .file("dep/Cargo.toml", r#"
+ [project]
+ name = "dep"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+ "#)
+ .file("dep/src/lib.rs", "pub fn dep() {}")
+ .file("build/Cargo.toml", r#"
+ [project]
+ name = "build"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+ "#)
+ .file("build/src/lib.rs", "pub fn build() {}")
+ .file("dev/Cargo.toml", r#"
+ [project]
+ name = "dev"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+ "#)
+ .file("dev/src/lib.rs", "pub fn dev() {}")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0));
+
+ assert_that(&p.bin("foo"), existing_file());
+ assert_that(p.cargo("test"),
+ execs().with_status(0));
+}
+
+#[test]
+fn bad_platform_specific_dependency() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+
+ name = "foo"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+
+ [target.wrong-target.dependencies.bar]
+ path = "bar"
+ "#)
+ .file("src/main.rs",
+ &main_file(r#""{}", bar::gimme()"#, &["bar"]))
+ .file("bar/Cargo.toml", r#"
+ [project]
+
+ name = "bar"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+ "#)
+ .file("bar/src/lib.rs", r#"
+ extern crate baz;
+
+ pub fn gimme() -> String {
+ format!("")
+ }
+ "#)
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101));
+}
+
+#[test]
+fn cargo_platform_specific_dependency_wrong_platform() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+
+ name = "foo"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+
+ [target.non-existing-triplet.dependencies.bar]
+ path = "bar"
+ "#)
+ .file("src/main.rs", r#"
+ fn main() {}
+ "#)
+ .file("bar/Cargo.toml", r#"
+ [project]
+
+ name = "bar"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+ "#)
+ .file("bar/src/lib.rs", r#"
+ invalid rust file, should not be compiled
+ "#)
+ .build();
+
+ p.cargo("build").exec_with_output().unwrap();
+
+ assert_that(&p.bin("foo"), existing_file());
+ assert_that(process(&p.bin("foo")),
+ execs().with_status(0));
+
+ let loc = p.root().join("Cargo.lock");
+ let mut lockfile = String::new();
+ File::open(&loc).unwrap().read_to_string(&mut lockfile).unwrap();
+ assert!(lockfile.contains("bar"))
+}
+
+#[test]
+fn example_as_lib() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [[example]]
+ name = "ex"
+ crate-type = ["lib"]
+ "#)
+ .file("src/lib.rs", "")
+ .file("examples/ex.rs", "")
+ .build();
+
+ assert_that(p.cargo("build").arg("--example=ex"), execs().with_status(0));
+ assert_that(&p.example_lib("ex", "lib"), existing_file());
+}
+
+#[test]
+fn example_as_rlib() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [[example]]
+ name = "ex"
+ crate-type = ["rlib"]
+ "#)
+ .file("src/lib.rs", "")
+ .file("examples/ex.rs", "")
+ .build();
+
+ assert_that(p.cargo("build").arg("--example=ex"), execs().with_status(0));
+ assert_that(&p.example_lib("ex", "rlib"), existing_file());
+}
+
+#[test]
+fn example_as_dylib() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [[example]]
+ name = "ex"
+ crate-type = ["dylib"]
+ "#)
+ .file("src/lib.rs", "")
+ .file("examples/ex.rs", "")
+ .build();
+
+ assert_that(p.cargo("build").arg("--example=ex"), execs().with_status(0));
+ assert_that(&p.example_lib("ex", "dylib"), existing_file());
+}
+
+#[test]
+fn example_as_proc_macro() {
+ if !is_nightly() {
+ return;
+ }
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [[example]]
+ name = "ex"
+ crate-type = ["proc-macro"]
+ "#)
+ .file("src/lib.rs", "")
+ .file("examples/ex.rs", "#![feature(proc_macro)]")
+ .build();
+
+ assert_that(p.cargo("build").arg("--example=ex"), execs().with_status(0));
+ assert_that(&p.example_lib("ex", "proc-macro"), existing_file());
+}
+
+#[test]
+fn example_bin_same_name() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .file("examples/foo.rs", "fn main() {}")
+ .build();
+
+ p.cargo("test").arg("--no-run").arg("-v")
+ .exec_with_output()
+ .unwrap();
+
+ assert_that(&p.bin("foo"), is_not(existing_file()));
+ // We expect a file of the form bin/foo-{metadata_hash}
+ assert_that(&p.bin("examples/foo"), existing_file());
+
+ p.cargo("test").arg("--no-run").arg("-v")
+ .exec_with_output()
+ .unwrap();
+
+ assert_that(&p.bin("foo"), is_not(existing_file()));
+ // We expect a file of the form bin/foo-{metadata_hash}
+ assert_that(&p.bin("examples/foo"), existing_file());
+}
+
+#[test]
+fn compile_then_delete() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("run").arg("-v"), execs().with_status(0));
+ assert_that(&p.bin("foo"), existing_file());
+ if cfg!(windows) {
+ // On windows unlinking immediately after running often fails, so sleep
+ sleep_ms(100);
+ }
+ fs::remove_file(&p.bin("foo")).unwrap();
+ assert_that(p.cargo("run").arg("-v"),
+ execs().with_status(0));
+}
+
+#[test]
+fn transitive_dependencies_not_available() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.aaaaa]
+ path = "a"
+ "#)
+ .file("src/main.rs", "extern crate bbbbb; extern crate aaaaa; fn main() {}")
+ .file("a/Cargo.toml", r#"
+ [package]
+ name = "aaaaa"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.bbbbb]
+ path = "../b"
+ "#)
+ .file("a/src/lib.rs", "extern crate bbbbb;")
+ .file("b/Cargo.toml", r#"
+ [package]
+ name = "bbbbb"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("b/src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(101)
+ .with_stderr_contains("\
+[..] can't find crate for `bbbbb`[..]
+"));
+}
+
+#[test]
+fn cyclic_deps_rejected() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.a]
+ path = "a"
+ "#)
+ .file("src/lib.rs", "")
+ .file("a/Cargo.toml", r#"
+ [package]
+ name = "a"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.foo]
+ path = ".."
+ "#)
+ .file("a/src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(101)
+ .with_stderr("\
+[ERROR] cyclic package dependency: package `a v0.0.1 ([..])` depends on itself
+"));
+}
+
+#[test]
+fn predictable_filenames() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [lib]
+ name = "foo"
+ crate-type = ["dylib", "rlib"]
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(0));
+ assert_that(&p.root().join("target/debug/libfoo.rlib"), existing_file());
+ let dylib_name = format!("{}foo{}", env::consts::DLL_PREFIX,
+ env::consts::DLL_SUFFIX);
+ assert_that(&p.root().join("target/debug").join(dylib_name),
+ existing_file());
+}
+
+#[test]
+fn dashes_to_underscores() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo-bar"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/lib.rs", "")
+ .file("src/main.rs", "extern crate foo_bar; fn main() {}")
+ .build();
+
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(0));
+ assert_that(&p.bin("foo-bar"), existing_file());
+}
+
+#[test]
+fn dashes_in_crate_name_bad() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [lib]
+ name = "foo-bar"
+ "#)
+ .file("src/lib.rs", "")
+ .file("src/main.rs", "extern crate foo_bar; fn main() {}")
+ .build();
+
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(101));
+}
+
+#[test]
+fn rustc_env_var() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build")
+ .env("RUSTC", "rustc-that-does-not-exist").arg("-v"),
+ execs().with_status(101)
+ .with_stderr("\
+[ERROR] could not execute process `rustc-that-does-not-exist -vV` ([..])
+
+Caused by:
+[..]
+"));
+ assert_that(&p.bin("a"), is_not(existing_file()));
+}
+
+#[test]
+fn filtering() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/lib.rs", "")
+ .file("src/bin/a.rs", "fn main() {}")
+ .file("src/bin/b.rs", "fn main() {}")
+ .file("examples/a.rs", "fn main() {}")
+ .file("examples/b.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("build").arg("--lib"),
+ execs().with_status(0));
+ assert_that(&p.bin("a"), is_not(existing_file()));
+
+ assert_that(p.cargo("build").arg("--bin=a").arg("--example=a"),
+ execs().with_status(0));
+ assert_that(&p.bin("a"), existing_file());
+ assert_that(&p.bin("b"), is_not(existing_file()));
+ assert_that(&p.bin("examples/a"), existing_file());
+ assert_that(&p.bin("examples/b"), is_not(existing_file()));
+}
+
+#[test]
+fn filtering_implicit_bins() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/lib.rs", "")
+ .file("src/bin/a.rs", "fn main() {}")
+ .file("src/bin/b.rs", "fn main() {}")
+ .file("examples/a.rs", "fn main() {}")
+ .file("examples/b.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("build").arg("--bins"),
+ execs().with_status(0));
+ assert_that(&p.bin("a"), existing_file());
+ assert_that(&p.bin("b"), existing_file());
+ assert_that(&p.bin("examples/a"), is_not(existing_file()));
+ assert_that(&p.bin("examples/b"), is_not(existing_file()));
+}
+
+#[test]
+fn filtering_implicit_examples() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/lib.rs", "")
+ .file("src/bin/a.rs", "fn main() {}")
+ .file("src/bin/b.rs", "fn main() {}")
+ .file("examples/a.rs", "fn main() {}")
+ .file("examples/b.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("build").arg("--examples"),
+ execs().with_status(0));
+ assert_that(&p.bin("a"), is_not(existing_file()));
+ assert_that(&p.bin("b"), is_not(existing_file()));
+ assert_that(&p.bin("examples/a"), existing_file());
+ assert_that(&p.bin("examples/b"), existing_file());
+}
+
+#[test]
+fn ignore_dotfile() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/bin/.a.rs", "")
+ .file("src/bin/a.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0));
+}
+
+#[test]
+fn ignore_dotdirs() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/bin/a.rs", "fn main() {}")
+ .file(".git/Cargo.toml", "")
+ .file(".pc/dummy-fix.patch/Cargo.toml", "")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0));
+}
+
+#[test]
+fn dotdir_root() {
+ let p = ProjectBuilder::new("foo", root().join(".foo"))
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/bin/a.rs", "fn main() {}")
+ .build();
+ assert_that(p.cargo("build"),
+ execs().with_status(0));
+}
+
+
+#[test]
+fn custom_target_dir() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ let exe_name = format!("foo{}", env::consts::EXE_SUFFIX);
+
+ assert_that(p.cargo("build").env("CARGO_TARGET_DIR", "foo/target"),
+ execs().with_status(0));
+ assert_that(&p.root().join("foo/target/debug").join(&exe_name),
+ existing_file());
+ assert_that(&p.root().join("target/debug").join(&exe_name),
+ is_not(existing_file()));
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0));
+ assert_that(&p.root().join("foo/target/debug").join(&exe_name),
+ existing_file());
+ assert_that(&p.root().join("target/debug").join(&exe_name),
+ existing_file());
+
+ fs::create_dir(p.root().join(".cargo")).unwrap();
+ File::create(p.root().join(".cargo/config")).unwrap().write_all(br#"
+ [build]
+ target-dir = "foo/target"
+ "#).unwrap();
+ assert_that(p.cargo("build").env("CARGO_TARGET_DIR", "bar/target"),
+ execs().with_status(0));
+ assert_that(&p.root().join("bar/target/debug").join(&exe_name),
+ existing_file());
+ assert_that(&p.root().join("foo/target/debug").join(&exe_name),
+ existing_file());
+ assert_that(&p.root().join("target/debug").join(&exe_name),
+ existing_file());
+}
+
+#[test]
+fn rustc_no_trans() {
+ if !is_nightly() { return }
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("rustc").arg("-v").arg("--").arg("-Zno-trans"),
+ execs().with_status(0));
+}
+
+#[test]
+fn build_multiple_packages() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.d1]
+ path = "d1"
+ [dependencies.d2]
+ path = "d2"
+
+ [[bin]]
+ name = "foo"
+ "#)
+ .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
+ .file("d1/Cargo.toml", r#"
+ [package]
+ name = "d1"
+ version = "0.0.1"
+ authors = []
+
+ [[bin]]
+ name = "d1"
+ "#)
+ .file("d1/src/lib.rs", "")
+ .file("d1/src/main.rs", "fn main() { println!(\"d1\"); }")
+ .file("d2/Cargo.toml", r#"
+ [package]
+ name = "d2"
+ version = "0.0.1"
+ authors = []
+
+ [[bin]]
+ name = "d2"
+ doctest = false
+ "#)
+ .file("d2/src/main.rs", "fn main() { println!(\"d2\"); }")
+ .build();
+
+ assert_that(p.cargo("build").arg("-p").arg("d1").arg("-p").arg("d2")
+ .arg("-p").arg("foo"),
+ execs().with_status(0));
+
+ assert_that(&p.bin("foo"), existing_file());
+ assert_that(process(&p.bin("foo")),
+ execs().with_status(0).with_stdout("i am foo\n"));
+
+ let d1_path = &p.build_dir().join("debug")
+ .join(format!("d1{}", env::consts::EXE_SUFFIX));
+ let d2_path = &p.build_dir().join("debug")
+ .join(format!("d2{}", env::consts::EXE_SUFFIX));
+
+ assert_that(d1_path, existing_file());
+ assert_that(process(d1_path), execs().with_status(0).with_stdout("d1"));
+
+ assert_that(d2_path, existing_file());
+ assert_that(process(d2_path),
+ execs().with_status(0).with_stdout("d2"));
+}
+
+#[test]
+fn invalid_spec() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.d1]
+ path = "d1"
+
+ [[bin]]
+ name = "foo"
+ "#)
+ .file("src/bin/foo.rs", &main_file(r#""i am foo""#, &[]))
+ .file("d1/Cargo.toml", r#"
+ [package]
+ name = "d1"
+ version = "0.0.1"
+ authors = []
+
+ [[bin]]
+ name = "d1"
+ "#)
+ .file("d1/src/lib.rs", "")
+ .file("d1/src/main.rs", "fn main() { println!(\"d1\"); }")
+ .build();
+
+ assert_that(p.cargo("build").arg("-p").arg("notAValidDep"),
+ execs().with_status(101).with_stderr("\
+[ERROR] package id specification `notAValidDep` matched no packages
+"));
+
+ assert_that(p.cargo("build").arg("-p").arg("d1").arg("-p").arg("notAValidDep"),
+ execs().with_status(101).with_stderr("\
+[ERROR] package id specification `notAValidDep` matched no packages
+"));
+}
+
+#[test]
+fn manifest_with_bom_is_ok() {
+ let p = project("foo")
+ .file("Cargo.toml", "\u{FEFF}
+ [package]
+ name = \"foo\"
+ version = \"0.0.1\"
+ authors = []
+ ")
+ .file("src/lib.rs", "")
+ .build();
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(0));
+}
+
+#[test]
+fn panic_abort_compiles_with_panic_abort() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [profile.dev]
+ panic = 'abort'
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(0)
+ .with_stderr_contains("[..] -C panic=abort [..]"));
+}
+
+#[test]
+fn explicit_color_config_is_propagated_to_rustc() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+
+ name = "test"
+ version = "0.0.0"
+ authors = []
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+ assert_that(p.cargo("build").arg("-v").arg("--color").arg("always"),
+ execs().with_status(0).with_stderr_contains(
+ "[..]rustc [..] src[/]lib.rs --color always[..]"));
+
+ assert_that(p.cargo("clean"), execs().with_status(0));
+
+ assert_that(p.cargo("build").arg("-v").arg("--color").arg("never"),
+ execs().with_status(0).with_stderr("\
+[COMPILING] test v0.0.0 ([..])
+[RUNNING] `rustc [..] --color never [..]`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+}
+
+#[test]
+fn compiler_json_error_format() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+
+ name = "foo"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+
+ [profile.dev]
+ debug = false # prevent the *.dSYM from affecting the test result
+
+ [dependencies.bar]
+ path = "bar"
+ "#)
+ .file("src/main.rs", "fn main() { let unused = 92; }")
+ .file("bar/Cargo.toml", r#"
+ [project]
+
+ name = "bar"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+ "#)
+ .file("bar/src/lib.rs", r#"fn dead() {}"#)
+ .build();
+
+ assert_that(p.cargo("build").arg("-v")
+ .arg("--message-format").arg("json"),
+ execs().with_status(0).with_json(r#"
+ {
+ "reason":"compiler-message",
+ "package_id":"bar 0.5.0 ([..])",
+ "target":{
+ "kind":["lib"],
+ "crate_types":["lib"],
+ "name":"bar",
+ "src_path":"[..]lib.rs"
+ },
+ "message":"{...}"
+ }
+
+ {
+ "reason":"compiler-artifact",
+ "profile": {
+ "debug_assertions": true,
+ "debuginfo": null,
+ "opt_level": "0",
+ "overflow_checks": true,
+ "test": false
+ },
+ "features": [],
+ "package_id":"bar 0.5.0 ([..])",
+ "target":{
+ "kind":["lib"],
+ "crate_types":["lib"],
+ "name":"bar",
+ "src_path":"[..]lib.rs"
+ },
+ "filenames":["[..].rlib"],
+ "fresh": false
+ }
+
+ {
+ "reason":"compiler-message",
+ "package_id":"foo 0.5.0 ([..])",
+ "target":{
+ "kind":["bin"],
+ "crate_types":["bin"],
+ "name":"foo",
+ "src_path":"[..]main.rs"
+ },
+ "message":"{...}"
+ }
+
+ {
+ "reason":"compiler-artifact",
+ "package_id":"foo 0.5.0 ([..])",
+ "target":{
+ "kind":["bin"],
+ "crate_types":["bin"],
+ "name":"foo",
+ "src_path":"[..]main.rs"
+ },
+ "profile": {
+ "debug_assertions": true,
+ "debuginfo": null,
+ "opt_level": "0",
+ "overflow_checks": true,
+ "test": false
+ },
+ "features": [],
+ "filenames": ["[..]"],
+ "fresh": false
+ }
+"#));
+
+ // With fresh build, we should repeat the artifacts,
+ // but omit compiler warnings.
+ assert_that(p.cargo("build").arg("-v")
+ .arg("--message-format").arg("json"),
+ execs().with_status(0).with_json(r#"
+ {
+ "reason":"compiler-artifact",
+ "profile": {
+ "debug_assertions": true,
+ "debuginfo": null,
+ "opt_level": "0",
+ "overflow_checks": true,
+ "test": false
+ },
+ "features": [],
+ "package_id":"bar 0.5.0 ([..])",
+ "target":{
+ "kind":["lib"],
+ "crate_types":["lib"],
+ "name":"bar",
+ "src_path":"[..]lib.rs"
+ },
+ "filenames":["[..].rlib"],
+ "fresh": true
+ }
+
+ {
+ "reason":"compiler-artifact",
+ "package_id":"foo 0.5.0 ([..])",
+ "target":{
+ "kind":["bin"],
+ "crate_types":["bin"],
+ "name":"foo",
+ "src_path":"[..]main.rs"
+ },
+ "profile": {
+ "debug_assertions": true,
+ "debuginfo": null,
+ "opt_level": "0",
+ "overflow_checks": true,
+ "test": false
+ },
+ "features": [],
+ "filenames": ["[..]"],
+ "fresh": true
+ }
+"#));
+}
+
+#[test]
+fn wrong_message_format_option() {
+ let p = project("foo")
+ .file("Cargo.toml", &basic_bin_manifest("foo"))
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("build").arg("--message-format").arg("XML"),
+ execs().with_status(1)
+ .with_stderr_contains(
+r#"[ERROR] Could not match 'xml' with any of the allowed variants: ["Human", "Json"]"#));
+}
+
+#[test]
+fn message_format_json_forward_stderr() {
+ let p = project("foo")
+ .file("Cargo.toml", &basic_bin_manifest("foo"))
+ .file("src/main.rs", "fn main() { let unused = 0; }")
+ .build();
+
+ assert_that(p.cargo("rustc").arg("--release").arg("--bin").arg("foo")
+ .arg("--message-format").arg("JSON"),
+ execs().with_status(0)
+ .with_json(r#"
+ {
+ "reason":"compiler-message",
+ "package_id":"foo 0.5.0 ([..])",
+ "target":{
+ "kind":["bin"],
+ "crate_types":["bin"],
+ "name":"foo",
+ "src_path":"[..]"
+ },
+ "message":"{...}"
+ }
+
+ {
+ "reason":"compiler-artifact",
+ "package_id":"foo 0.5.0 ([..])",
+ "target":{
+ "kind":["bin"],
+ "crate_types":["bin"],
+ "name":"foo",
+ "src_path":"[..]"
+ },
+ "profile":{
+ "debug_assertions":false,
+ "debuginfo":null,
+ "opt_level":"3",
+ "overflow_checks": false,
+ "test":false
+ },
+ "features":[],
+ "filenames":["[..]"],
+ "fresh": false
+ }
+"#));
+}
+
+#[test]
+fn no_warn_about_package_metadata() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [package.metadata]
+ foo = "bar"
+ a = true
+ b = 3
+
+ [package.metadata.another]
+ bar = 3
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+ assert_that(p.cargo("build"),
+ execs().with_status(0)
+ .with_stderr("[..] foo v0.0.1 ([..])\n\
+ [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]\n"));
+}
+
+#[test]
+fn cargo_build_empty_target() {
+ let p = project("foo")
+ .file("Cargo.toml", &basic_bin_manifest("foo"))
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("build").arg("--target").arg(""),
+ execs().with_status(101)
+ .with_stderr_contains("[..] target was empty"));
+}
+
+#[test]
+fn build_all_workspace() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+
+ [dependencies]
+ bar = { path = "bar" }
+
+ [workspace]
+ "#)
+ .file("src/main.rs", r#"
+ fn main() {}
+ "#)
+ .file("bar/Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.1.0"
+ "#)
+ .file("bar/src/lib.rs", r#"
+ pub fn bar() {}
+ "#)
+ .build();
+
+ assert_that(p.cargo("build")
+ .arg("--all"),
+ execs().with_status(0)
+ .with_stderr("[..] Compiling bar v0.1.0 ([..])\n\
+ [..] Compiling foo v0.1.0 ([..])\n\
+ [..] Finished dev [unoptimized + debuginfo] target(s) in [..]\n"));
+}
+
+#[test]
+fn build_all_exclude() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+
+ [workspace]
+ members = ["bar", "baz"]
+ "#)
+ .file("src/main.rs", r#"
+ fn main() {}
+ "#)
+ .file("bar/Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.1.0"
+ "#)
+ .file("bar/src/lib.rs", r#"
+ pub fn bar() {}
+ "#)
+ .file("baz/Cargo.toml", r#"
+ [project]
+ name = "baz"
+ version = "0.1.0"
+ "#)
+ .file("baz/src/lib.rs", r#"
+ pub fn baz() {
+ break_the_build();
+ }
+ "#)
+ .build();
+
+ assert_that(p.cargo("build")
+ .arg("--all")
+ .arg("--exclude")
+ .arg("baz"),
+ execs().with_status(0)
+ .with_stderr_contains("[..]Compiling foo v0.1.0 [..]")
+ .with_stderr_contains("[..]Compiling bar v0.1.0 [..]")
+ .with_stderr_does_not_contain("[..]Compiling baz v0.1.0 [..]"));
+}
+
+#[test]
+fn build_all_workspace_implicit_examples() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+
+ [dependencies]
+ bar = { path = "bar" }
+
+ [workspace]
+ "#)
+ .file("src/lib.rs", "")
+ .file("src/bin/a.rs", "fn main() {}")
+ .file("src/bin/b.rs", "fn main() {}")
+ .file("examples/c.rs", "fn main() {}")
+ .file("examples/d.rs", "fn main() {}")
+ .file("bar/Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.1.0"
+ "#)
+ .file("bar/src/lib.rs", "")
+ .file("bar/src/bin/e.rs", "fn main() {}")
+ .file("bar/src/bin/f.rs", "fn main() {}")
+ .file("bar/examples/g.rs", "fn main() {}")
+ .file("bar/examples/h.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("build")
+ .arg("--all").arg("--examples"),
+ execs().with_status(0)
+ .with_stderr("[..] Compiling bar v0.1.0 ([..])\n\
+ [..] Compiling foo v0.1.0 ([..])\n\
+ [..] Finished dev [unoptimized + debuginfo] target(s) in [..]\n"));
+ assert_that(&p.bin("a"), is_not(existing_file()));
+ assert_that(&p.bin("b"), is_not(existing_file()));
+ assert_that(&p.bin("examples/c"), existing_file());
+ assert_that(&p.bin("examples/d"), existing_file());
+ assert_that(&p.bin("e"), is_not(existing_file()));
+ assert_that(&p.bin("f"), is_not(existing_file()));
+ assert_that(&p.bin("examples/g"), existing_file());
+ assert_that(&p.bin("examples/h"), existing_file());
+}
+
+#[test]
+fn build_all_virtual_manifest() {
+ let p = project("workspace")
+ .file("Cargo.toml", r#"
+ [workspace]
+ members = ["foo", "bar"]
+ "#)
+ .file("foo/Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+ "#)
+ .file("foo/src/lib.rs", r#"
+ pub fn foo() {}
+ "#)
+ .file("bar/Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.1.0"
+ "#)
+ .file("bar/src/lib.rs", r#"
+ pub fn bar() {}
+ "#)
+ .build();
+
+ // The order in which foo and bar are built is not guaranteed
+ assert_that(p.cargo("build")
+ .arg("--all"),
+ execs().with_status(0)
+ .with_stderr_contains("[..] Compiling bar v0.1.0 ([..])")
+ .with_stderr_contains("[..] Compiling foo v0.1.0 ([..])")
+ .with_stderr("[..] Compiling [..] v0.1.0 ([..])\n\
+ [..] Compiling [..] v0.1.0 ([..])\n\
+ [..] Finished dev [unoptimized + debuginfo] target(s) in [..]\n"));
+}
+
+#[test]
+fn build_virtual_manifest_all_implied() {
+ let p = project("workspace")
+ .file("Cargo.toml", r#"
+ [workspace]
+ members = ["foo", "bar"]
+ "#)
+ .file("foo/Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+ "#)
+ .file("foo/src/lib.rs", r#"
+ pub fn foo() {}
+ "#)
+ .file("bar/Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.1.0"
+ "#)
+ .file("bar/src/lib.rs", r#"
+ pub fn bar() {}
+ "#)
+ .build();
+
+ // The order in which foo and bar are built is not guaranteed
+ assert_that(p.cargo("build"),
+ execs().with_status(0)
+ .with_stderr_contains("[..] Compiling bar v0.1.0 ([..])")
+ .with_stderr_contains("[..] Compiling foo v0.1.0 ([..])")
+ .with_stderr("[..] Compiling [..] v0.1.0 ([..])\n\
+ [..] Compiling [..] v0.1.0 ([..])\n\
+ [..] Finished dev [unoptimized + debuginfo] target(s) in [..]\n"));
+}
+
+#[test]
+fn build_virtual_manifest_one_project() {
+ let p = project("workspace")
+ .file("Cargo.toml", r#"
+ [workspace]
+ members = ["foo", "bar"]
+ "#)
+ .file("foo/Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+ "#)
+ .file("foo/src/lib.rs", r#"
+ pub fn foo() {}
+ "#)
+ .file("bar/Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.1.0"
+ "#)
+ .file("bar/src/lib.rs", r#"
+ pub fn bar() {}
+ "#)
+ .build();
+
+ assert_that(p.cargo("build")
+ .arg("-p").arg("foo"),
+ execs().with_status(0)
+ .with_stderr_does_not_contain("bar")
+ .with_stderr_contains("[..] Compiling foo v0.1.0 ([..])")
+ .with_stderr("[..] Compiling [..] v0.1.0 ([..])\n\
+ [..] Finished dev [unoptimized + debuginfo] target(s) in [..]\n"));
+}
+
+#[test]
+fn build_all_virtual_manifest_implicit_examples() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [workspace]
+ members = ["foo", "bar"]
+ "#)
+ .file("foo/Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+ "#)
+ .file("foo/src/lib.rs", "")
+ .file("foo/src/bin/a.rs", "fn main() {}")
+ .file("foo/src/bin/b.rs", "fn main() {}")
+ .file("foo/examples/c.rs", "fn main() {}")
+ .file("foo/examples/d.rs", "fn main() {}")
+ .file("bar/Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.1.0"
+ "#)
+ .file("bar/src/lib.rs", "")
+ .file("bar/src/bin/e.rs", "fn main() {}")
+ .file("bar/src/bin/f.rs", "fn main() {}")
+ .file("bar/examples/g.rs", "fn main() {}")
+ .file("bar/examples/h.rs", "fn main() {}")
+ .build();
+
+ // The order in which foo and bar are built is not guaranteed
+ assert_that(p.cargo("build")
+ .arg("--all").arg("--examples"),
+ execs().with_status(0)
+ .with_stderr_contains("[..] Compiling bar v0.1.0 ([..])")
+ .with_stderr_contains("[..] Compiling foo v0.1.0 ([..])")
+ .with_stderr("[..] Compiling [..] v0.1.0 ([..])\n\
+ [..] Compiling [..] v0.1.0 ([..])\n\
+ [..] Finished dev [unoptimized + debuginfo] target(s) in [..]\n"));
+ assert_that(&p.bin("a"), is_not(existing_file()));
+ assert_that(&p.bin("b"), is_not(existing_file()));
+ assert_that(&p.bin("examples/c"), existing_file());
+ assert_that(&p.bin("examples/d"), existing_file());
+ assert_that(&p.bin("e"), is_not(existing_file()));
+ assert_that(&p.bin("f"), is_not(existing_file()));
+ assert_that(&p.bin("examples/g"), existing_file());
+ assert_that(&p.bin("examples/h"), existing_file());
+}
+
+#[test]
+fn build_all_member_dependency_same_name() {
+ let p = project("workspace")
+ .file("Cargo.toml", r#"
+ [workspace]
+ members = ["a"]
+ "#)
+ .file("a/Cargo.toml", r#"
+ [project]
+ name = "a"
+ version = "0.1.0"
+
+ [dependencies]
+ a = "0.1.0"
+ "#)
+ .file("a/src/lib.rs", r#"
+ pub fn a() {}
+ "#)
+ .build();
+
+ Package::new("a", "0.1.0").publish();
+
+ assert_that(p.cargo("build")
+ .arg("--all"),
+ execs().with_status(0)
+ .with_stderr("[..] Updating registry `[..]`\n\
+ [..] Downloading a v0.1.0 ([..])\n\
+ [..] Compiling a v0.1.0\n\
+ [..] Compiling a v0.1.0 ([..])\n\
+ [..] Finished dev [unoptimized + debuginfo] target(s) in [..]\n"));
+}
+
+#[test]
+fn run_proper_binary() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ authors = []
+ version = "0.0.0"
+ [[bin]]
+ name = "main"
+ [[bin]]
+ name = "other"
+ "#)
+ .file("src/lib.rs", "")
+ .file("src/bin/main.rs", r#"
+ fn main() {
+ panic!("This should never be run.");
+ }
+ "#)
+ .file("src/bin/other.rs", r#"
+ fn main() {
+ }
+ "#)
+ .build();
+
+ assert_that(p.cargo("run").arg("--bin").arg("other"),
+ execs().with_status(0));
+}
+
+#[test]
+fn run_proper_binary_main_rs() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ authors = []
+ version = "0.0.0"
+ [[bin]]
+ name = "foo"
+ "#)
+ .file("src/lib.rs", "")
+ .file("src/bin/main.rs", r#"
+ fn main() {
+ }
+ "#)
+ .build();
+
+ assert_that(p.cargo("run").arg("--bin").arg("foo"),
+ execs().with_status(0));
+}
+
+#[test]
+fn run_proper_alias_binary_from_src() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ authors = []
+ version = "0.0.0"
+ [[bin]]
+ name = "foo"
+ [[bin]]
+ name = "bar"
+ "#)
+ .file("src/foo.rs", r#"
+ fn main() {
+ println!("foo");
+ }
+ "#).file("src/bar.rs", r#"
+ fn main() {
+ println!("bar");
+ }
+ "#)
+ .build();
+
+ assert_that(p.cargo("build")
+ .arg("--all"),
+ execs().with_status(0)
+ );
+ assert_that(process(&p.bin("foo")),
+ execs().with_status(0).with_stdout("foo\n"));
+ assert_that(process(&p.bin("bar")),
+ execs().with_status(0).with_stdout("bar\n"));
+}
+
+#[test]
+fn run_proper_alias_binary_main_rs() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ authors = []
+ version = "0.0.0"
+ [[bin]]
+ name = "foo"
+ [[bin]]
+ name = "bar"
+ "#)
+ .file("src/main.rs", r#"
+ fn main() {
+ println!("main");
+ }
+ "#)
+ .build();
+
+ assert_that(p.cargo("build")
+ .arg("--all"),
+ execs().with_status(0)
+ );
+ assert_that(process(&p.bin("foo")),
+ execs().with_status(0).with_stdout("main\n"));
+ assert_that(process(&p.bin("bar")),
+ execs().with_status(0).with_stdout("main\n"));
+}
+
+#[test]
+fn run_proper_binary_main_rs_as_foo() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ authors = []
+ version = "0.0.0"
+ [[bin]]
+ name = "foo"
+ "#)
+ .file("src/foo.rs", r#"
+ fn main() {
+ panic!("This should never be run.");
+ }
+ "#)
+ .file("src/main.rs", r#"
+ fn main() {
+ }
+ "#)
+ .build();
+
+ assert_that(p.cargo("run").arg("--bin").arg("foo"),
+ execs().with_status(0));
+}
+
+#[test]
+fn rustc_wrapper() {
+ // We don't have /usr/bin/env on Windows.
+ if cfg!(windows) { return }
+
+ let p = project("foo")
+ .file("Cargo.toml", &basic_bin_manifest("foo"))
+ .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
+ .build();
+
+ assert_that(p.cargo("build").arg("-v").env("RUSTC_WRAPPER", "/usr/bin/env"),
+ execs().with_stderr_contains(
+ "[RUNNING] `/usr/bin/env rustc --crate-name foo [..]")
+ .with_status(0));
+}
+
+#[test]
+fn cdylib_not_lifted() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ authors = []
+ version = "0.1.0"
+
+ [lib]
+ crate-type = ["cdylib"]
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"), execs().with_status(0));
+
+ let files = if cfg!(windows) {
+ vec!["foo.dll.lib", "foo.dll.exp", "foo.dll"]
+ } else if cfg!(target_os = "macos") {
+ vec!["libfoo.dylib"]
+ } else {
+ vec!["libfoo.so"]
+ };
+
+ for file in files {
+ println!("checking: {}", file);
+ assert_that(&p.root().join("target/debug/deps").join(&file),
+ existing_file());
+ }
+}
+
+#[test]
+fn cdylib_final_outputs() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo-bar"
+ authors = []
+ version = "0.1.0"
+
+ [lib]
+ crate-type = ["cdylib"]
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"), execs().with_status(0));
+
+ let files = if cfg!(windows) {
+ vec!["foo_bar.dll.lib", "foo_bar.dll"]
+ } else if cfg!(target_os = "macos") {
+ vec!["libfoo_bar.dylib"]
+ } else {
+ vec!["libfoo_bar.so"]
+ };
+
+ for file in files {
+ println!("checking: {}", file);
+ assert_that(&p.root().join("target/debug").join(&file), existing_file());
+ }
+}
+
+#[test]
+fn deterministic_cfg_flags() {
+ // This bug is non-deterministic
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ build = "build.rs"
+
+ [features]
+ default = ["f_a", "f_b", "f_c", "f_d"]
+ f_a = []
+ f_b = []
+ f_c = []
+ f_d = []
+ "#)
+ .file("build.rs", r#"
+ fn main() {
+ println!("cargo:rustc-cfg=cfg_a");
+ println!("cargo:rustc-cfg=cfg_b");
+ println!("cargo:rustc-cfg=cfg_c");
+ println!("cargo:rustc-cfg=cfg_d");
+ println!("cargo:rustc-cfg=cfg_e");
+ }
+ "#)
+ .file("src/main.rs", r#"
+ fn main() {}
+ "#)
+ .build();
+
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(0)
+ .with_stderr("\
+[COMPILING] foo v0.1.0 [..]
+[RUNNING] [..]
+[RUNNING] [..]
+[RUNNING] `rustc --crate-name foo [..] \
+--cfg[..]default[..]--cfg[..]f_a[..]--cfg[..]f_b[..]\
+--cfg[..]f_c[..]--cfg[..]f_d[..] \
+--cfg cfg_a --cfg cfg_b --cfg cfg_c --cfg cfg_d --cfg cfg_e`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]"));
+}
+
+#[test]
+fn explicit_bins_without_paths() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+
+ [[bin]]
+ name = "foo"
+
+ [[bin]]
+ name = "bar"
+ "#)
+ .file("src/lib.rs", "")
+ .file("src/main.rs", "fn main() {}")
+ .file("src/bin/bar.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("build"), execs().with_status(0));
+}
+
+#[test]
+fn no_bin_in_src_with_lib() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+
+ [[bin]]
+ name = "foo"
+ "#)
+ .file("src/lib.rs", "")
+ .file("src/foo.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101)
+ .with_stderr_contains("\
+[ERROR] failed to parse manifest at `[..]`
+
+Caused by:
+ can't find `foo` bin, specify bin.path"));
+}
+
+
+#[test]
+fn inferred_bins() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .file("src/bin/bar.rs", "fn main() {}")
+ .file("src/bin/baz/main.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("build"), execs().with_status(0));
+ assert_that(&p.bin("foo"), existing_file());
+ assert_that(&p.bin("bar"), existing_file());
+ assert_that(&p.bin("baz"), existing_file());
+}
+
+#[test]
+fn inferred_bins_duplicate_name() {
+ // this should fail, because we have two binaries with the same name
+ let p = project("bar")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .file("src/bin/foo.rs", "fn main() {}")
+ .file("src/bin/foo/main.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101)
+ .with_stderr_contains("\
+[..]found duplicate binary name foo, but all binary targets must have a unique name[..]
+"));
+}
+
+#[test]
+fn inferred_bin_path() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+
+ [[bin]]
+ name = "bar"
+ # Note, no `path` key!
+ "#)
+ .file("src/bin/bar/main.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("build"), execs().with_status(0));
+ assert_that(&p.bin("bar"), existing_file());
+}
+
+#[test]
+fn inferred_examples() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("src/lib.rs", "fn main() {}")
+ .file("examples/bar.rs", "fn main() {}")
+ .file("examples/baz/main.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("test"), execs().with_status(0));
+ assert_that(&p.bin("examples/bar"), existing_file());
+ assert_that(&p.bin("examples/baz"), existing_file());
+}
+
+#[test]
+fn inferred_tests() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("src/lib.rs", "fn main() {}")
+ .file("tests/bar.rs", "fn main() {}")
+ .file("tests/baz/main.rs", "fn main() {}")
+ .build();
+
+ assert_that(
+ p.cargo("test").arg("--test=bar").arg("--test=baz"),
+ execs().with_status(0));
+}
+
+#[test]
+fn inferred_benchmarks() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("src/lib.rs", "fn main() {}")
+ .file("benches/bar.rs", "fn main() {}")
+ .file("benches/baz/main.rs", "fn main() {}")
+ .build();
+
+ assert_that(
+ p.cargo("bench").arg("--bench=bar").arg("--bench=baz"),
+ execs().with_status(0));
+}
+
+#[test]
+fn same_metadata_different_directory() {
+ // A top-level crate built in two different workspaces should have the
+ // same metadata hash.
+ let p = project("foo1")
+ .file("Cargo.toml", &basic_bin_manifest("foo"))
+ .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
+ .build();
+ let output = t!(String::from_utf8(
+ t!(p.cargo("build").arg("-v").exec_with_output())
+ .stderr,
+ ));
+ let metadata = output
+ .split_whitespace()
+ .find(|arg| arg.starts_with("metadata="))
+ .unwrap();
+
+ let p = project("foo2")
+ .file("Cargo.toml", &basic_bin_manifest("foo"))
+ .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
+ .build();
+
+ assert_that(
+ p.cargo("build").arg("-v"),
+ execs().with_status(0).with_stderr_contains(
+ format!("[..]{}[..]", metadata),
+ ),
+ );
+}
+
+#[test]
+fn building_a_dependent_crate_witout_bin_should_fail() {
+ Package::new("testless", "0.1.0")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "testless"
+ version = "0.1.0"
+
+ [[bin]]
+ name = "a_bin"
+ "#)
+ .file("src/lib.rs", "")
+ .publish();
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+
+ [dependencies]
+ testless = "0.1.0"
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101).with_stderr_contains(
+ "[..]can't find `a_bin` bin, specify bin.path"
+ ));
+}
+
+#[test]
+fn uplift_dsym_of_bin_on_mac() {
+ if !cfg!(any(target_os = "macos", target_os = "ios")) {
+ return
+ }
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+ "#)
+ .file("src/main.rs", "fn main() { panic!(); }")
+ .file("src/bin/b.rs", "fn main() { panic!(); }")
+ .file("examples/c.rs", "fn main() { panic!(); }")
+ .file("tests/d.rs", "fn main() { panic!(); }")
+ .build();
+
+ assert_that(
+ p.cargo("build").arg("--bins").arg("--examples").arg("--tests"),
+ execs().with_status(0)
+ );
+ assert_that(&p.bin("foo.dSYM"), existing_dir());
+ assert_that(&p.bin("b.dSYM"), existing_dir());
+ assert!(
+ p.bin("b.dSYM")
+ .symlink_metadata()
+ .expect("read metadata from b.dSYM")
+ .file_type()
+ .is_symlink()
+ );
+ assert_that(&p.bin("c.dSYM"), is_not(existing_dir()));
+ assert_that(&p.bin("d.dSYM"), is_not(existing_dir()));
+}
+
+// Make sure that `cargo build` chooses the correct profile for building
+// targets based on filters (assuming --profile is not specified).
+#[test]
+fn build_filter_infer_profile() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("src/lib.rs", "")
+ .file("src/main.rs", "fn main() {}")
+ .file("tests/t1.rs", "")
+ .file("benches/b1.rs", "")
+ .file("examples/ex1.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(0)
+ .with_stderr_contains("\
+ [RUNNING] `rustc --crate-name foo src[/]lib.rs --crate-type lib \
+ --emit=dep-info,link[..]")
+ .with_stderr_contains("\
+ [RUNNING] `rustc --crate-name foo src[/]main.rs --crate-type bin \
+ --emit=dep-info,link[..]")
+ );
+
+ p.root().join("target").rm_rf();
+ assert_that(p.cargo("build").arg("-v").arg("--test=t1"),
+ execs().with_status(0)
+ .with_stderr_contains("\
+ [RUNNING] `rustc --crate-name foo src[/]lib.rs --crate-type lib \
+ --emit=dep-info,link[..]")
+ .with_stderr_contains("\
+ [RUNNING] `rustc --crate-name t1 tests[/]t1.rs --emit=dep-info,link[..]")
+ .with_stderr_contains("\
+ [RUNNING] `rustc --crate-name foo src[/]main.rs --crate-type bin \
+ --emit=dep-info,link[..]")
+ );
+
+ p.root().join("target").rm_rf();
+ assert_that(p.cargo("build").arg("-v").arg("--bench=b1"),
+ execs().with_status(0)
+ .with_stderr_contains("\
+ [RUNNING] `rustc --crate-name foo src[/]lib.rs --crate-type lib \
+ --emit=dep-info,link[..]")
+ .with_stderr_contains("\
+ [RUNNING] `rustc --crate-name b1 benches[/]b1.rs --emit=dep-info,link \
+ -C opt-level=3[..]")
+ .with_stderr_contains("\
+ [RUNNING] `rustc --crate-name foo src[/]main.rs --crate-type bin \
+ --emit=dep-info,link[..]")
+ );
+}
+
+#[test]
+fn all_targets_no_lib() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+ assert_that(p.cargo("build").arg("-v").arg("--all-targets"),
+ execs().with_status(0)
+ // bin
+ .with_stderr_contains("\
+ [RUNNING] `rustc --crate-name foo src[/]main.rs --crate-type bin \
+ --emit=dep-info,link[..]")
+ // bench
+ .with_stderr_contains("\
+ [RUNNING] `rustc --crate-name foo src[/]main.rs --emit=dep-info,link \
+ -C opt-level=3 --test [..]")
+ // unit test
+ .with_stderr_contains("\
+ [RUNNING] `rustc --crate-name foo src[/]main.rs --emit=dep-info,link \
+ -C debuginfo=2 --test [..]")
+ );
+}
+
+#[test]
+fn no_linkable_target() {
+ // Issue 3169. This is currently not an error as per discussion in PR #4797
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ [dependencies]
+ the_lib = { path = "the_lib" }
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .file("the_lib/Cargo.toml", r#"
+ [package]
+ name = "the_lib"
+ version = "0.1.0"
+ [lib]
+ name = "the_lib"
+ crate-type = ["staticlib"]
+ "#)
+ .file("the_lib/src/lib.rs", "pub fn foo() {}")
+ .build();
+ assert_that(p.cargo("build"),
+ execs()
+ .with_status(0)
+ .with_stderr_contains("\
+ [WARNING] The package `the_lib` provides no linkable [..] \
+while compiling `foo`. [..] in `the_lib`'s Cargo.toml. [..]"));
+}
--- /dev/null
+use std;
+use std::collections::HashSet;
+use std::io::prelude::*;
+use std::net::TcpListener;
+use std::thread;
+
+use git2;
+use bufstream::BufStream;
+use cargotest::support::paths;
+use cargotest::support::{project, execs};
+use hamcrest::assert_that;
+
+// Test that HTTP auth is offered from `credential.helper`
+#[test]
+fn http_auth_offered() {
+ let server = TcpListener::bind("127.0.0.1:0").unwrap();
+ let addr = server.local_addr().unwrap();
+
+ fn headers(rdr: &mut BufRead) -> HashSet<String> {
+ let valid = ["GET", "Authorization", "Accept", "User-Agent"];
+ rdr.lines().map(|s| s.unwrap())
+ .take_while(|s| s.len() > 2)
+ .map(|s| s.trim().to_string())
+ .filter(|s| {
+ valid.iter().any(|prefix| s.starts_with(*prefix))
+ })
+ .collect()
+ }
+
+ let t = thread::spawn(move|| {
+ let mut conn = BufStream::new(server.accept().unwrap().0);
+ let req = headers(&mut conn);
+ let user_agent = if cfg!(windows) {
+ "User-Agent: git/1.0 (libgit2 0.26.0)"
+ } else {
+ "User-Agent: git/2.0 (libgit2 0.26.0)"
+ };
+ conn.write_all(b"\
+ HTTP/1.1 401 Unauthorized\r\n\
+ WWW-Authenticate: Basic realm=\"wheee\"\r\n
+ \r\n\
+ ").unwrap();
+ assert_eq!(req, vec![
+ "GET /foo/bar/info/refs?service=git-upload-pack HTTP/1.1",
+ "Accept: */*",
+ user_agent,
+ ].into_iter().map(|s| s.to_string()).collect());
+ drop(conn);
+
+ let mut conn = BufStream::new(server.accept().unwrap().0);
+ let req = headers(&mut conn);
+ conn.write_all(b"\
+ HTTP/1.1 401 Unauthorized\r\n\
+ WWW-Authenticate: Basic realm=\"wheee\"\r\n
+ \r\n\
+ ").unwrap();
+ assert_eq!(req, vec![
+ "GET /foo/bar/info/refs?service=git-upload-pack HTTP/1.1",
+ "Authorization: Basic Zm9vOmJhcg==",
+ "Accept: */*",
+ user_agent,
+ ].into_iter().map(|s| s.to_string()).collect());
+ });
+
+ let script = project("script")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "script"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/main.rs", r#"
+ fn main() {
+ println!("username=foo");
+ println!("password=bar");
+ }
+ "#)
+ .build();
+
+ assert_that(script.cargo("build").arg("-v"),
+ execs().with_status(0));
+ let script = script.bin("script");
+
+ let config = paths::home().join(".gitconfig");
+ let mut config = git2::Config::open(&config).unwrap();
+ config.set_str("credential.helper",
+ &script.display().to_string()).unwrap();
+
+ let p = project("foo")
+ .file("Cargo.toml", &format!(r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.bar]
+ git = "http://127.0.0.1:{}/foo/bar"
+ "#, addr.port()))
+ .file("src/main.rs", "")
+ .file(".cargo/config","\
+ [net]
+ retry = 0
+ ")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101).with_stderr(&format!("\
+[UPDATING] git repository `http://{addr}/foo/bar`
+[ERROR] failed to load source for a dependency on `bar`
+
+Caused by:
+ Unable to update http://{addr}/foo/bar
+
+Caused by:
+ failed to clone into: [..]
+
+Caused by:
+ failed to authenticate when downloading repository
+attempted to find username/password via `credential.helper`, but [..]
+
+To learn more, run the command again with --verbose.
+",
+ addr = addr)));
+
+ t.join().ok().unwrap();
+}
+
+// Boy, sure would be nice to have a TLS implementation in rust!
+#[test]
+fn https_something_happens() {
+ let server = TcpListener::bind("127.0.0.1:0").unwrap();
+ let addr = server.local_addr().unwrap();
+ let t = thread::spawn(move|| {
+ let mut conn = server.accept().unwrap().0;
+ drop(conn.write(b"1234"));
+ drop(conn.shutdown(std::net::Shutdown::Write));
+ drop(conn.read(&mut [0; 16]));
+ });
+
+ let p = project("foo")
+ .file("Cargo.toml", &format!(r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.bar]
+ git = "https://127.0.0.1:{}/foo/bar"
+ "#, addr.port()))
+ .file("src/main.rs", "")
+ .file(".cargo/config","\
+ [net]
+ retry = 0
+ ")
+ .build();
+
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(101).with_stderr_contains(&format!("\
+[UPDATING] git repository `https://{addr}/foo/bar`
+", addr = addr))
+ .with_stderr_contains(&format!("\
+Caused by:
+ {errmsg}
+",
+ errmsg = if cfg!(windows) {
+ "[..]failed to send request: [..]"
+ } else if cfg!(target_os = "macos") {
+ // OSX is difficult to tests as some builds may use
+ // Security.framework and others may use OpenSSL. In that case let's
+ // just not verify the error message here.
+ "[..]"
+ } else {
+ "[..]SSL error: [..]"
+ })));
+
+ t.join().ok().unwrap();
+}
+
+// Boy, sure would be nice to have an SSH implementation in rust!
+#[test]
+fn ssh_something_happens() {
+ let server = TcpListener::bind("127.0.0.1:0").unwrap();
+ let addr = server.local_addr().unwrap();
+ let t = thread::spawn(move|| {
+ drop(server.accept().unwrap());
+ });
+
+ let p = project("foo")
+ .file("Cargo.toml", &format!(r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.bar]
+ git = "ssh://127.0.0.1:{}/foo/bar"
+ "#, addr.port()))
+ .file("src/main.rs", "")
+ .build();
+
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(101).with_stderr_contains(&format!("\
+[UPDATING] git repository `ssh://{addr}/foo/bar`
+", addr = addr))
+ .with_stderr_contains("\
+Caused by:
+ [..]failed to start SSH session: Failed getting banner[..]
+"));
+ t.join().ok().unwrap();
+}
--- /dev/null
+extern crate cargotest;
+extern crate hamcrest;
+
+use cargotest::support::{basic_bin_manifest, execs, project, Project};
+use hamcrest::{assert_that};
+
+fn verbose_output_for_lib(p: &Project) -> String {
+ format!("\
+[COMPILING] {name} v{version} ({url})
+[RUNNING] `rustc --crate-name {name} src[/]lib.rs --crate-type lib \
+ --emit=dep-info,link -C debuginfo=2 \
+ -C metadata=[..] \
+ --out-dir [..] \
+ -L dependency={dir}[/]target[/]debug[/]deps`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+",
+ dir = p.root().display(), url = p.url(),
+ name = "foo", version = "0.0.1")
+}
+
+#[test]
+fn build_lib_only() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+
+ name = "foo"
+ version = "0.0.1"
+ authors = ["wycats@example.com"]
+ "#)
+ .file("src/main.rs", r#"
+ fn main() {}
+ "#)
+ .file("src/lib.rs", r#" "#)
+ .build();
+
+ assert_that(p.cargo("build").arg("--lib").arg("-v"),
+ execs()
+ .with_status(0)
+ .with_stderr(verbose_output_for_lib(&p)));
+}
+
+
+#[test]
+fn build_with_no_lib() {
+ let p = project("foo")
+ .file("Cargo.toml", &basic_bin_manifest("foo"))
+ .file("src/main.rs", r#"
+ fn main() {}
+ "#)
+ .build();
+
+ assert_that(p.cargo("build").arg("--lib"),
+ execs().with_status(101)
+ .with_stderr("[ERROR] no library targets found"));
+}
+
+#[test]
+fn build_with_relative_cargo_home_path() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+
+ name = "foo"
+ version = "0.0.1"
+ authors = ["wycats@example.com"]
+
+ [dependencies]
+
+ "test-dependency" = { path = "src/test_dependency" }
+ "#)
+ .file("src/main.rs", r#"
+ fn main() {}
+ "#)
+ .file("src/test_dependency/src/lib.rs", r#" "#)
+ .file("src/test_dependency/Cargo.toml", r#"
+ [package]
+
+ name = "test-dependency"
+ version = "0.0.1"
+ authors = ["wycats@example.com"]
+ "#)
+ .build();
+
+ assert_that(p.cargo("build").env("CARGO_HOME", "./cargo_home/"),
+ execs()
+ .with_status(0));
+}
--- /dev/null
+use std::env;
+use std::fs::{self, File};
+use std::io::prelude::*;
+use std::path::PathBuf;
+
+use cargotest::{rustc_host, sleep_ms};
+use cargotest::support::{project, execs};
+use cargotest::support::paths::CargoPathExt;
+use cargotest::support::registry::Package;
+use hamcrest::{assert_that, existing_file, existing_dir};
+
+#[test]
+fn custom_build_script_failed() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+
+ name = "foo"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+ build = "build.rs"
+ "#)
+ .file("src/main.rs", r#"
+ fn main() {}
+ "#)
+ .file("build.rs", r#"
+ fn main() {
+ std::process::exit(101);
+ }
+ "#)
+ .build();
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(101)
+ .with_stderr(&format!("\
+[COMPILING] foo v0.5.0 ({url})
+[RUNNING] `rustc --crate-name build_script_build build.rs --crate-type bin [..]`
+[RUNNING] `[..][/]build-script-build`
+[ERROR] failed to run custom build command for `foo v0.5.0 ({url})`
+process didn't exit successfully: `[..][/]build-script-build` (exit code: 101)",
+url = p.url())));
+}
+
+#[test]
+fn custom_build_env_vars() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+
+ name = "foo"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+
+ [features]
+ bar_feat = ["bar/foo"]
+
+ [dependencies.bar]
+ path = "bar"
+ "#)
+ .file("src/main.rs", r#"
+ fn main() {}
+ "#)
+ .file("bar/Cargo.toml", r#"
+ [project]
+
+ name = "bar"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+ build = "build.rs"
+
+ [features]
+ foo = []
+ "#)
+ .file("bar/src/lib.rs", r#"
+ pub fn hello() {}
+ "#);
+
+ let file_content = format!(r#"
+ use std::env;
+ use std::io::prelude::*;
+ use std::path::Path;
+ use std::fs;
+
+ fn main() {{
+ let _target = env::var("TARGET").unwrap();
+ let _ncpus = env::var("NUM_JOBS").unwrap();
+ let _dir = env::var("CARGO_MANIFEST_DIR").unwrap();
+
+ let opt = env::var("OPT_LEVEL").unwrap();
+ assert_eq!(opt, "0");
+
+ let opt = env::var("PROFILE").unwrap();
+ assert_eq!(opt, "debug");
+
+ let debug = env::var("DEBUG").unwrap();
+ assert_eq!(debug, "true");
+
+ let out = env::var("OUT_DIR").unwrap();
+ assert!(out.starts_with(r"{0}"));
+ assert!(fs::metadata(&out).map(|m| m.is_dir()).unwrap_or(false));
+
+ let _host = env::var("HOST").unwrap();
+
+ let _feat = env::var("CARGO_FEATURE_FOO").unwrap();
+
+ let _cargo = env::var("CARGO").unwrap();
+
+ let rustc = env::var("RUSTC").unwrap();
+ assert_eq!(rustc, "rustc");
+
+ let rustdoc = env::var("RUSTDOC").unwrap();
+ assert_eq!(rustdoc, "rustdoc");
+ }}
+ "#,
+ p.root().join("target").join("debug").join("build").display());
+
+ let p = p.file("bar/build.rs", &file_content).build();
+
+ assert_that(p.cargo("build").arg("--features").arg("bar_feat"),
+ execs().with_status(0));
+}
+
+#[test]
+fn custom_build_script_wrong_rustc_flags() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+
+ name = "foo"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+ build = "build.rs"
+ "#)
+ .file("src/main.rs", r#"
+ fn main() {}
+ "#)
+ .file("build.rs", r#"
+ fn main() {
+ println!("cargo:rustc-flags=-aaa -bbb");
+ }
+ "#)
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101)
+ .with_stderr_contains(&format!("\
+[ERROR] Only `-l` and `-L` flags are allowed in build script of `foo v0.5.0 ({})`: \
+`-aaa -bbb`",
+p.url())));
+}
+
+/*
+#[test]
+fn custom_build_script_rustc_flags() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+
+ name = "bar"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+
+ [dependencies.foo]
+ path = "foo"
+ "#)
+ .file("src/main.rs", r#"
+ fn main() {}
+ "#)
+ .file("foo/Cargo.toml", r#"
+ [project]
+
+ name = "foo"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+ build = "build.rs"
+ "#)
+ .file("foo/src/lib.rs", r#"
+ "#)
+ .file("foo/build.rs", r#"
+ fn main() {
+ println!("cargo:rustc-flags=-l nonexistinglib -L /dummy/path1 -L /dummy/path2");
+ }
+ "#)
+ .build();
+
+ // TODO: TEST FAILS BECAUSE OF WRONG STDOUT (but otherwise, the build works)
+ assert_that(p.cargo("build").arg("--verbose"),
+ execs().with_status(101)
+ .with_stderr(&format!("\
+[COMPILING] bar v0.5.0 ({url})
+[RUNNING] `rustc --crate-name test {dir}{sep}src{sep}lib.rs --crate-type lib -C debuginfo=2 \
+ -C metadata=[..] \
+ -C extra-filename=-[..] \
+ --out-dir {dir}{sep}target \
+ --emit=dep-info,link \
+ -L {dir}{sep}target \
+ -L {dir}{sep}target{sep}deps`
+", sep = path::SEP,
+dir = p.root().display(),
+url = p.url(),
+)));
+}
+*/
+
+#[test]
+fn links_no_build_cmd() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+ authors = []
+ links = "a"
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101)
+ .with_stderr("\
+[ERROR] package `foo v0.5.0 (file://[..])` specifies that it links to `a` but does \
+not have a custom build script
+"));
+}
+
+#[test]
+fn links_duplicates() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+ authors = []
+ links = "a"
+ build = "build.rs"
+
+ [dependencies.a-sys]
+ path = "a-sys"
+ "#)
+ .file("src/lib.rs", "")
+ .file("build.rs", "")
+ .file("a-sys/Cargo.toml", r#"
+ [project]
+ name = "a-sys"
+ version = "0.5.0"
+ authors = []
+ links = "a"
+ build = "build.rs"
+ "#)
+ .file("a-sys/src/lib.rs", "")
+ .file("a-sys/build.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101)
+ .with_stderr("\
+[ERROR] multiple packages link to native library `a`, but a native library can \
+be linked only once
+
+package `foo v0.5.0 ([..])`
+links to native library `a`
+
+package `a-sys v0.5.0 ([..])`
+ ... which is depended on by `foo v0.5.0 ([..])`
+also links to native library `a`
+"));
+}
+
+#[test]
+fn links_duplicates_deep_dependency() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+ authors = []
+ links = "a"
+ build = "build.rs"
+
+ [dependencies.a]
+ path = "a"
+ "#)
+ .file("src/lib.rs", "")
+ .file("build.rs", "")
+ .file("a/Cargo.toml", r#"
+ [project]
+ name = "a"
+ version = "0.5.0"
+ authors = []
+ build = "build.rs"
+
+ [dependencies.a-sys]
+ path = "a-sys"
+ "#)
+ .file("a/src/lib.rs", "")
+ .file("a/build.rs", "")
+ .file("a/a-sys/Cargo.toml", r#"
+ [project]
+ name = "a-sys"
+ version = "0.5.0"
+ authors = []
+ links = "a"
+ build = "build.rs"
+ "#)
+ .file("a/a-sys/src/lib.rs", "")
+ .file("a/a-sys/build.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101)
+ .with_stderr("\
+[ERROR] multiple packages link to native library `a`, but a native library can \
+be linked only once
+
+package `foo v0.5.0 ([..])`
+links to native library `a`
+
+package `a-sys v0.5.0 ([..])`
+ ... which is depended on by `a v0.5.0 ([..])`
+ ... which is depended on by `foo v0.5.0 ([..])`
+also links to native library `a`
+"));
+}
+
+#[test]
+fn overrides_and_links() {
+ let target = rustc_host();
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+ authors = []
+ build = "build.rs"
+
+ [dependencies.a]
+ path = "a"
+ "#)
+ .file("src/lib.rs", "")
+ .file("build.rs", r#"
+ use std::env;
+ fn main() {
+ assert_eq!(env::var("DEP_FOO_FOO").ok().expect("FOO missing"),
+ "bar");
+ assert_eq!(env::var("DEP_FOO_BAR").ok().expect("BAR missing"),
+ "baz");
+ }
+ "#)
+ .file(".cargo/config", &format!(r#"
+ [target.{}.foo]
+ rustc-flags = "-L foo -L bar"
+ foo = "bar"
+ bar = "baz"
+ "#, target))
+ .file("a/Cargo.toml", r#"
+ [project]
+ name = "a"
+ version = "0.5.0"
+ authors = []
+ links = "foo"
+ build = "build.rs"
+ "#)
+ .file("a/src/lib.rs", "")
+ .file("a/build.rs", "not valid rust code")
+ .build();
+
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(0)
+ .with_stderr("\
+[..]
+[..]
+[..]
+[..]
+[..]
+[RUNNING] `rustc --crate-name foo [..] -L foo -L bar`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+}
+
+#[test]
+fn unused_overrides() {
+ let target = rustc_host();
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+ authors = []
+ build = "build.rs"
+ "#)
+ .file("src/lib.rs", "")
+ .file("build.rs", "fn main() {}")
+ .file(".cargo/config", &format!(r#"
+ [target.{}.foo]
+ rustc-flags = "-L foo -L bar"
+ foo = "bar"
+ bar = "baz"
+ "#, target))
+ .build();
+
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(0));
+}
+
+#[test]
+fn links_passes_env_vars() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+ authors = []
+ build = "build.rs"
+
+ [dependencies.a]
+ path = "a"
+ "#)
+ .file("src/lib.rs", "")
+ .file("build.rs", r#"
+ use std::env;
+ fn main() {
+ assert_eq!(env::var("DEP_FOO_FOO").unwrap(), "bar");
+ assert_eq!(env::var("DEP_FOO_BAR").unwrap(), "baz");
+ }
+ "#)
+ .file("a/Cargo.toml", r#"
+ [project]
+ name = "a"
+ version = "0.5.0"
+ authors = []
+ links = "foo"
+ build = "build.rs"
+ "#)
+ .file("a/src/lib.rs", "")
+ .file("a/build.rs", r#"
+ use std::env;
+ fn main() {
+ let lib = env::var("CARGO_MANIFEST_LINKS").unwrap();
+ assert_eq!(lib, "foo");
+
+ println!("cargo:foo=bar");
+ println!("cargo:bar=baz");
+ }
+ "#)
+ .build();
+
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(0));
+}
+
+#[test]
+fn only_rerun_build_script() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+ authors = []
+ build = "build.rs"
+ "#)
+ .file("src/lib.rs", "")
+ .file("build.rs", r#"
+ fn main() {}
+ "#)
+ .build();
+
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(0));
+ p.root().move_into_the_past();
+
+ File::create(&p.root().join("some-new-file")).unwrap();
+ p.root().move_into_the_past();
+
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(0)
+ .with_stderr("\
+[COMPILING] foo v0.5.0 (file://[..])
+[RUNNING] `[..][/]build-script-build`
+[RUNNING] `rustc --crate-name foo [..]`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+}
+
+#[test]
+fn rebuild_continues_to_pass_env_vars() {
+ let a = project("a")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "a"
+ version = "0.5.0"
+ authors = []
+ links = "foo"
+ build = "build.rs"
+ "#)
+ .file("src/lib.rs", "")
+ .file("build.rs", r#"
+ use std::time::Duration;
+ fn main() {
+ println!("cargo:foo=bar");
+ println!("cargo:bar=baz");
+ std::thread::sleep(Duration::from_millis(500));
+ }
+ "#)
+ .build();
+ a.root().move_into_the_past();
+
+ let p = project("foo")
+ .file("Cargo.toml", &format!(r#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+ authors = []
+ build = "build.rs"
+
+ [dependencies.a]
+ path = '{}'
+ "#, a.root().display()))
+ .file("src/lib.rs", "")
+ .file("build.rs", r#"
+ use std::env;
+ fn main() {
+ assert_eq!(env::var("DEP_FOO_FOO").unwrap(), "bar");
+ assert_eq!(env::var("DEP_FOO_BAR").unwrap(), "baz");
+ }
+ "#)
+ .build();
+
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(0));
+ p.root().move_into_the_past();
+
+ File::create(&p.root().join("some-new-file")).unwrap();
+ p.root().move_into_the_past();
+
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(0));
+}
+
+#[test]
+fn testing_and_such() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+ authors = []
+ build = "build.rs"
+ "#)
+ .file("src/lib.rs", "")
+ .file("build.rs", r#"
+ fn main() {}
+ "#)
+ .build();
+
+ println!("build");
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(0));
+ p.root().move_into_the_past();
+
+ File::create(&p.root().join("src/lib.rs")).unwrap();
+ p.root().move_into_the_past();
+
+ println!("test");
+ assert_that(p.cargo("test").arg("-vj1"),
+ execs().with_status(0)
+ .with_stderr("\
+[COMPILING] foo v0.5.0 (file://[..])
+[RUNNING] `[..][/]build-script-build`
+[RUNNING] `rustc --crate-name foo [..]`
+[RUNNING] `rustc --crate-name foo [..]`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] `[..][/]foo-[..][EXE]`
+[DOCTEST] foo
+[RUNNING] `rustdoc --test [..]`")
+ .with_stdout_contains_n("running 0 tests", 2));
+
+ println!("doc");
+ assert_that(p.cargo("doc").arg("-v"),
+ execs().with_status(0)
+ .with_stderr("\
+[DOCUMENTING] foo v0.5.0 (file://[..])
+[RUNNING] `rustdoc [..]`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+
+ File::create(&p.root().join("src/main.rs")).unwrap()
+ .write_all(b"fn main() {}").unwrap();
+ println!("run");
+ assert_that(p.cargo("run"),
+ execs().with_status(0)
+ .with_stderr("\
+[COMPILING] foo v0.5.0 (file://[..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] `target[/]debug[/]foo[EXE]`
+"));
+}
+
+#[test]
+fn propagation_of_l_flags() {
+ let target = rustc_host();
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+ authors = []
+ [dependencies.a]
+ path = "a"
+ "#)
+ .file("src/lib.rs", "")
+ .file("a/Cargo.toml", r#"
+ [project]
+ name = "a"
+ version = "0.5.0"
+ authors = []
+ links = "bar"
+ build = "build.rs"
+
+ [dependencies.b]
+ path = "../b"
+ "#)
+ .file("a/src/lib.rs", "")
+ .file("a/build.rs", r#"
+ fn main() {
+ println!("cargo:rustc-flags=-L bar");
+ }
+ "#)
+ .file("b/Cargo.toml", r#"
+ [project]
+ name = "b"
+ version = "0.5.0"
+ authors = []
+ links = "foo"
+ build = "build.rs"
+ "#)
+ .file("b/src/lib.rs", "")
+ .file("b/build.rs", "bad file")
+ .file(".cargo/config", &format!(r#"
+ [target.{}.foo]
+ rustc-flags = "-L foo"
+ "#, target))
+ .build();
+
+ assert_that(p.cargo("build").arg("-v").arg("-j1"),
+ execs().with_status(0)
+ .with_stderr_contains("\
+[RUNNING] `rustc --crate-name a [..] -L bar[..]-L foo[..]`
+[COMPILING] foo v0.5.0 (file://[..])
+[RUNNING] `rustc --crate-name foo [..] -L bar -L foo`
+"));
+}
+
+#[test]
+fn propagation_of_l_flags_new() {
+ let target = rustc_host();
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+ authors = []
+ [dependencies.a]
+ path = "a"
+ "#)
+ .file("src/lib.rs", "")
+ .file("a/Cargo.toml", r#"
+ [project]
+ name = "a"
+ version = "0.5.0"
+ authors = []
+ links = "bar"
+ build = "build.rs"
+
+ [dependencies.b]
+ path = "../b"
+ "#)
+ .file("a/src/lib.rs", "")
+ .file("a/build.rs", r#"
+ fn main() {
+ println!("cargo:rustc-link-search=bar");
+ }
+ "#)
+ .file("b/Cargo.toml", r#"
+ [project]
+ name = "b"
+ version = "0.5.0"
+ authors = []
+ links = "foo"
+ build = "build.rs"
+ "#)
+ .file("b/src/lib.rs", "")
+ .file("b/build.rs", "bad file")
+ .file(".cargo/config", &format!(r#"
+ [target.{}.foo]
+ rustc-link-search = ["foo"]
+ "#, target))
+ .build();
+
+ assert_that(p.cargo("build").arg("-v").arg("-j1"),
+ execs().with_status(0)
+ .with_stderr_contains("\
+[RUNNING] `rustc --crate-name a [..] -L bar[..]-L foo[..]`
+[COMPILING] foo v0.5.0 (file://[..])
+[RUNNING] `rustc --crate-name foo [..] -L bar -L foo`
+"));
+}
+
+#[test]
+fn build_deps_simple() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+ authors = []
+ build = "build.rs"
+ [build-dependencies.a]
+ path = "a"
+ "#)
+ .file("src/lib.rs", "")
+ .file("build.rs", "
+ #[allow(unused_extern_crates)]
+ extern crate a;
+ fn main() {}
+ ")
+ .file("a/Cargo.toml", r#"
+ [project]
+ name = "a"
+ version = "0.5.0"
+ authors = []
+ "#)
+ .file("a/src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(0)
+ .with_stderr("\
+[COMPILING] a v0.5.0 (file://[..])
+[RUNNING] `rustc --crate-name a [..]`
+[COMPILING] foo v0.5.0 (file://[..])
+[RUNNING] `rustc [..] build.rs [..] --extern a=[..]`
+[RUNNING] `[..][/]foo-[..][/]build-script-build`
+[RUNNING] `rustc --crate-name foo [..]`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+}
+
+#[test]
+fn build_deps_not_for_normal() {
+ let target = rustc_host();
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+ authors = []
+ build = "build.rs"
+ [build-dependencies.aaaaa]
+ path = "a"
+ "#)
+ .file("src/lib.rs", "#[allow(unused_extern_crates)] extern crate aaaaa;")
+ .file("build.rs", "
+ #[allow(unused_extern_crates)]
+ extern crate aaaaa;
+ fn main() {}
+ ")
+ .file("a/Cargo.toml", r#"
+ [project]
+ name = "aaaaa"
+ version = "0.5.0"
+ authors = []
+ "#)
+ .file("a/src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build").arg("-v").arg("--target").arg(&target),
+ execs().with_status(101)
+ .with_stderr_contains("\
+[..]can't find crate for `aaaaa`[..]
+")
+ .with_stderr_contains("\
+[ERROR] Could not compile `foo`.
+
+Caused by:
+ process didn't exit successfully: [..]
+"));
+}
+
+#[test]
+fn build_cmd_with_a_build_cmd() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+ authors = []
+ build = "build.rs"
+
+ [build-dependencies.a]
+ path = "a"
+ "#)
+ .file("src/lib.rs", "")
+ .file("build.rs", "
+ #[allow(unused_extern_crates)]
+ extern crate a;
+ fn main() {}
+ ")
+ .file("a/Cargo.toml", r#"
+ [project]
+ name = "a"
+ version = "0.5.0"
+ authors = []
+ build = "build.rs"
+
+ [build-dependencies.b]
+ path = "../b"
+ "#)
+ .file("a/src/lib.rs", "")
+ .file("a/build.rs", "#[allow(unused_extern_crates)] extern crate b; fn main() {}")
+ .file("b/Cargo.toml", r#"
+ [project]
+ name = "b"
+ version = "0.5.0"
+ authors = []
+ "#)
+ .file("b/src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(0)
+ .with_stderr("\
+[COMPILING] b v0.5.0 (file://[..])
+[RUNNING] `rustc --crate-name b [..]`
+[COMPILING] a v0.5.0 (file://[..])
+[RUNNING] `rustc [..] a[/]build.rs [..] --extern b=[..]`
+[RUNNING] `[..][/]a-[..][/]build-script-build`
+[RUNNING] `rustc --crate-name a [..]lib.rs --crate-type lib \
+ --emit=dep-info,link -C debuginfo=2 \
+ -C metadata=[..] \
+ --out-dir [..]target[/]debug[/]deps \
+ -L [..]target[/]debug[/]deps`
+[COMPILING] foo v0.5.0 (file://[..])
+[RUNNING] `rustc --crate-name build_script_build build.rs --crate-type bin \
+ --emit=dep-info,link \
+ -C debuginfo=2 -C metadata=[..] --out-dir [..] \
+ -L [..]target[/]debug[/]deps \
+ --extern a=[..]liba[..].rlib`
+[RUNNING] `[..][/]foo-[..][/]build-script-build`
+[RUNNING] `rustc --crate-name foo [..]lib.rs --crate-type lib \
+ --emit=dep-info,link -C debuginfo=2 \
+ -C metadata=[..] \
+ --out-dir [..] \
+ -L [..]target[/]debug[/]deps`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+}
+
+#[test]
+fn out_dir_is_preserved() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+ authors = []
+ build = "build.rs"
+ "#)
+ .file("src/lib.rs", "")
+ .file("build.rs", r#"
+ use std::env;
+ use std::fs::File;
+ use std::path::Path;
+ fn main() {
+ let out = env::var("OUT_DIR").unwrap();
+ File::create(Path::new(&out).join("foo")).unwrap();
+ }
+ "#)
+ .build();
+
+ // Make the file
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(0));
+ p.root().move_into_the_past();
+
+ // Change to asserting that it's there
+ File::create(&p.root().join("build.rs")).unwrap().write_all(br#"
+ use std::env;
+ use std::old_io::File;
+ fn main() {
+ let out = env::var("OUT_DIR").unwrap();
+ File::open(&Path::new(&out).join("foo")).unwrap();
+ }
+ "#).unwrap();
+ p.root().move_into_the_past();
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(0));
+
+ // Run a fresh build where file should be preserved
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(0));
+
+ // One last time to make sure it's still there.
+ File::create(&p.root().join("foo")).unwrap();
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(0));
+}
+
+#[test]
+fn output_separate_lines() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+ authors = []
+ build = "build.rs"
+ "#)
+ .file("src/lib.rs", "")
+ .file("build.rs", r#"
+ fn main() {
+ println!("cargo:rustc-flags=-L foo");
+ println!("cargo:rustc-flags=-l static=foo");
+ }
+ "#)
+ .build();
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(101)
+ .with_stderr_contains("\
+[COMPILING] foo v0.5.0 (file://[..])
+[RUNNING] `rustc [..] build.rs [..]`
+[RUNNING] `[..][/]foo-[..][/]build-script-build`
+[RUNNING] `rustc --crate-name foo [..] -L foo -l static=foo`
+[ERROR] could not find native static library [..]
+"));
+}
+
+#[test]
+fn output_separate_lines_new() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+ authors = []
+ build = "build.rs"
+ "#)
+ .file("src/lib.rs", "")
+ .file("build.rs", r#"
+ fn main() {
+ println!("cargo:rustc-link-search=foo");
+ println!("cargo:rustc-link-lib=static=foo");
+ }
+ "#)
+ .build();
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(101)
+ .with_stderr_contains("\
+[COMPILING] foo v0.5.0 (file://[..])
+[RUNNING] `rustc [..] build.rs [..]`
+[RUNNING] `[..][/]foo-[..][/]build-script-build`
+[RUNNING] `rustc --crate-name foo [..] -L foo -l static=foo`
+[ERROR] could not find native static library [..]
+"));
+}
+
+#[cfg(not(windows))] // FIXME(#867)
+#[test]
+fn code_generation() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+ authors = []
+ build = "build.rs"
+ "#)
+ .file("src/main.rs", r#"
+ include!(concat!(env!("OUT_DIR"), "/hello.rs"));
+
+ fn main() {
+ println!("{}", message());
+ }
+ "#)
+ .file("build.rs", r#"
+ use std::env;
+ use std::fs::File;
+ use std::io::prelude::*;
+ use std::path::PathBuf;
+
+ fn main() {
+ let dst = PathBuf::from(env::var("OUT_DIR").unwrap());
+ let mut f = File::create(&dst.join("hello.rs")).unwrap();
+ f.write_all(b"
+ pub fn message() -> &'static str {
+ \"Hello, World!\"
+ }
+ ").unwrap();
+ }
+ "#)
+ .build();
+
+ assert_that(p.cargo("run"),
+ execs().with_status(0)
+ .with_stderr("\
+[COMPILING] foo v0.5.0 (file://[..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] `target[/]debug[/]foo`")
+ .with_stdout("\
+Hello, World!
+"));
+
+ assert_that(p.cargo("test"),
+ execs().with_status(0));
+}
+
+#[test]
+fn release_with_build_script() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+ authors = []
+ build = "build.rs"
+ "#)
+ .file("src/lib.rs", "")
+ .file("build.rs", r#"
+ fn main() {}
+ "#)
+ .build();
+
+ assert_that(p.cargo("build").arg("-v").arg("--release"),
+ execs().with_status(0));
+}
+
+#[test]
+fn build_script_only() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.0"
+ authors = []
+ build = "build.rs"
+ "#)
+ .file("build.rs", r#"fn main() {}"#)
+ .build();
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(101)
+ .with_stderr("\
+[ERROR] failed to parse manifest at `[..]`
+
+Caused by:
+ no targets specified in the manifest
+ either src/lib.rs, src/main.rs, a [lib] section, or [[bin]] section must be present"));
+}
+
+#[test]
+fn shared_dep_with_a_build_script() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+ authors = []
+ build = "build.rs"
+
+ [dependencies.a]
+ path = "a"
+
+ [build-dependencies.b]
+ path = "b"
+ "#)
+ .file("src/lib.rs", "")
+ .file("build.rs", "fn main() {}")
+ .file("a/Cargo.toml", r#"
+ [package]
+ name = "a"
+ version = "0.5.0"
+ authors = []
+ build = "build.rs"
+ "#)
+ .file("a/build.rs", "fn main() {}")
+ .file("a/src/lib.rs", "")
+ .file("b/Cargo.toml", r#"
+ [package]
+ name = "b"
+ version = "0.5.0"
+ authors = []
+
+ [dependencies.a]
+ path = "../a"
+ "#)
+ .file("b/src/lib.rs", "")
+ .build();
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(0));
+}
+
+#[test]
+fn transitive_dep_host() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+ authors = []
+ build = "build.rs"
+
+ [build-dependencies.b]
+ path = "b"
+ "#)
+ .file("src/lib.rs", "")
+ .file("build.rs", "fn main() {}")
+ .file("a/Cargo.toml", r#"
+ [package]
+ name = "a"
+ version = "0.5.0"
+ authors = []
+ links = "foo"
+ build = "build.rs"
+ "#)
+ .file("a/build.rs", "fn main() {}")
+ .file("a/src/lib.rs", "")
+ .file("b/Cargo.toml", r#"
+ [package]
+ name = "b"
+ version = "0.5.0"
+ authors = []
+
+ [lib]
+ name = "b"
+ plugin = true
+
+ [dependencies.a]
+ path = "../a"
+ "#)
+ .file("b/src/lib.rs", "")
+ .build();
+ assert_that(p.cargo("build"),
+ execs().with_status(0));
+}
+
+#[test]
+fn test_a_lib_with_a_build_command() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+ authors = []
+ build = "build.rs"
+ "#)
+ .file("src/lib.rs", r#"
+ include!(concat!(env!("OUT_DIR"), "/foo.rs"));
+
+ /// ```
+ /// foo::bar();
+ /// ```
+ pub fn bar() {
+ assert_eq!(foo(), 1);
+ }
+ "#)
+ .file("build.rs", r#"
+ use std::env;
+ use std::io::prelude::*;
+ use std::fs::File;
+ use std::path::PathBuf;
+
+ fn main() {
+ let out = PathBuf::from(env::var("OUT_DIR").unwrap());
+ File::create(out.join("foo.rs")).unwrap().write_all(b"
+ fn foo() -> i32 { 1 }
+ ").unwrap();
+ }
+ "#)
+ .build();
+ assert_that(p.cargo("test"),
+ execs().with_status(0));
+}
+
+#[test]
+fn test_dev_dep_build_script() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+ authors = []
+
+ [dev-dependencies.a]
+ path = "a"
+ "#)
+ .file("src/lib.rs", "")
+ .file("a/Cargo.toml", r#"
+ [project]
+ name = "a"
+ version = "0.5.0"
+ authors = []
+ build = "build.rs"
+ "#)
+ .file("a/build.rs", "fn main() {}")
+ .file("a/src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("test"), execs().with_status(0));
+}
+
+#[test]
+fn build_script_with_dynamic_native_dependency() {
+
+ let _workspace = project("ws")
+ .file("Cargo.toml", r#"
+ [workspace]
+ members = ["builder", "foo"]
+ "#)
+ .build();
+
+ let build = project("ws/builder")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "builder"
+ version = "0.0.1"
+ authors = []
+
+ [lib]
+ name = "builder"
+ crate-type = ["dylib"]
+ plugin = true
+ "#)
+ .file("src/lib.rs", r#"
+ #[no_mangle]
+ pub extern fn foo() {}
+ "#)
+ .build();
+
+ let foo = project("ws/foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ build = "build.rs"
+
+ [build-dependencies.bar]
+ path = "bar"
+ "#)
+ .file("build.rs", r#"
+ extern crate bar;
+ fn main() { bar::bar() }
+ "#)
+ .file("src/lib.rs", "")
+ .file("bar/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+ build = "build.rs"
+ "#)
+ .file("bar/build.rs", r#"
+ use std::env;
+ use std::path::PathBuf;
+
+ fn main() {
+ let src = PathBuf::from(env::var("SRC").unwrap());
+ println!("cargo:rustc-link-search=native={}/target/debug/deps",
+ src.display());
+ }
+ "#)
+ .file("bar/src/lib.rs", r#"
+ pub fn bar() {
+ #[cfg_attr(not(target_env = "msvc"), link(name = "builder"))]
+ #[cfg_attr(target_env = "msvc", link(name = "builder.dll"))]
+ extern { fn foo(); }
+ unsafe { foo() }
+ }
+ "#)
+ .build();
+
+ assert_that(build.cargo("build").arg("-v")
+ .env("RUST_LOG", "cargo::ops::cargo_rustc"),
+ execs().with_status(0));
+
+ assert_that(foo.cargo("build").arg("-v").env("SRC", build.root())
+ .env("RUST_LOG", "cargo::ops::cargo_rustc"),
+ execs().with_status(0));
+}
+
+#[test]
+fn profile_and_opt_level_set_correctly() {
+ let build = project("builder")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "builder"
+ version = "0.0.1"
+ authors = []
+ build = "build.rs"
+ "#)
+ .file("src/lib.rs", "")
+ .file("build.rs", r#"
+ use std::env;
+
+ fn main() {
+ assert_eq!(env::var("OPT_LEVEL").unwrap(), "3");
+ assert_eq!(env::var("PROFILE").unwrap(), "release");
+ assert_eq!(env::var("DEBUG").unwrap(), "false");
+ }
+ "#)
+ .build();
+ assert_that(build.cargo("bench"),
+ execs().with_status(0));
+}
+
+#[test]
+fn build_script_with_lto() {
+ let build = project("builder")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "builder"
+ version = "0.0.1"
+ authors = []
+ build = "build.rs"
+
+ [profile.dev]
+ lto = true
+ "#)
+ .file("src/lib.rs", "")
+ .file("build.rs", r#"
+ fn main() {
+ }
+ "#)
+ .build();
+ assert_that(build.cargo("build"),
+ execs().with_status(0));
+}
+
+#[test]
+fn test_duplicate_deps() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ build = "build.rs"
+
+ [dependencies.bar]
+ path = "bar"
+
+ [build-dependencies.bar]
+ path = "bar"
+ "#)
+ .file("src/main.rs", r#"
+ extern crate bar;
+ fn main() { bar::do_nothing() }
+ "#)
+ .file("build.rs", r#"
+ extern crate bar;
+ fn main() { bar::do_nothing() }
+ "#)
+ .file("bar/Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("bar/src/lib.rs", "pub fn do_nothing() {}")
+ .build();
+
+ assert_that(p.cargo("build"), execs().with_status(0));
+}
+
+#[test]
+fn cfg_feedback() {
+ let build = project("builder")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "builder"
+ version = "0.0.1"
+ authors = []
+ build = "build.rs"
+ "#)
+ .file("src/main.rs", "
+ #[cfg(foo)]
+ fn main() {}
+ ")
+ .file("build.rs", r#"
+ fn main() {
+ println!("cargo:rustc-cfg=foo");
+ }
+ "#)
+ .build();
+ assert_that(build.cargo("build").arg("-v"),
+ execs().with_status(0));
+}
+
+#[test]
+fn cfg_override() {
+ let target = rustc_host();
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+ authors = []
+ links = "a"
+ build = "build.rs"
+ "#)
+ .file("src/main.rs", "
+ #[cfg(foo)]
+ fn main() {}
+ ")
+ .file("build.rs", "")
+ .file(".cargo/config", &format!(r#"
+ [target.{}.a]
+ rustc-cfg = ["foo"]
+ "#, target))
+ .build();
+
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(0));
+}
+
+#[test]
+fn cfg_test() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ build = "build.rs"
+ "#)
+ .file("build.rs", r#"
+ fn main() {
+ println!("cargo:rustc-cfg=foo");
+ }
+ "#)
+ .file("src/lib.rs", r#"
+ ///
+ /// ```
+ /// extern crate foo;
+ ///
+ /// fn main() {
+ /// foo::foo()
+ /// }
+ /// ```
+ ///
+ #[cfg(foo)]
+ pub fn foo() {}
+
+ #[cfg(foo)]
+ #[test]
+ fn test_foo() {
+ foo()
+ }
+ "#)
+ .file("tests/test.rs", r#"
+ #[cfg(foo)]
+ #[test]
+ fn test_bar() {}
+ "#)
+ .build();
+ assert_that(p.cargo("test").arg("-v"),
+ execs().with_stderr(format!("\
+[COMPILING] foo v0.0.1 ({dir})
+[RUNNING] [..] build.rs [..]
+[RUNNING] `[..][/]build-script-build`
+[RUNNING] [..] --cfg foo[..]
+[RUNNING] [..] --cfg foo[..]
+[RUNNING] [..] --cfg foo[..]
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] `[..][/]foo-[..][EXE]`
+[RUNNING] `[..][/]test-[..][EXE]`
+[DOCTEST] foo
+[RUNNING] [..] --cfg foo[..]", dir = p.url()))
+ .with_stdout_contains("test test_foo ... ok")
+ .with_stdout_contains("test test_bar ... ok")
+ .with_stdout_contains_n("test [..] ... ok", 3));
+}
+
+#[test]
+fn cfg_doc() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ build = "build.rs"
+
+ [dependencies.bar]
+ path = "bar"
+ "#)
+ .file("build.rs", r#"
+ fn main() {
+ println!("cargo:rustc-cfg=foo");
+ }
+ "#)
+ .file("src/lib.rs", r#"
+ #[cfg(foo)]
+ pub fn foo() {}
+ "#)
+ .file("bar/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+ build = "build.rs"
+ "#)
+ .file("bar/build.rs", r#"
+ fn main() {
+ println!("cargo:rustc-cfg=bar");
+ }
+ "#)
+ .file("bar/src/lib.rs", r#"
+ #[cfg(bar)]
+ pub fn bar() {}
+ "#)
+ .build();
+ assert_that(p.cargo("doc"),
+ execs().with_status(0));
+ assert_that(&p.root().join("target/doc"), existing_dir());
+ assert_that(&p.root().join("target/doc/foo/fn.foo.html"), existing_file());
+ assert_that(&p.root().join("target/doc/bar/fn.bar.html"), existing_file());
+}
+
+#[test]
+fn cfg_override_test() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ build = "build.rs"
+ links = "a"
+ "#)
+ .file("build.rs", "")
+ .file(".cargo/config", &format!(r#"
+ [target.{}.a]
+ rustc-cfg = ["foo"]
+ "#, rustc_host()))
+ .file("src/lib.rs", r#"
+ ///
+ /// ```
+ /// extern crate foo;
+ ///
+ /// fn main() {
+ /// foo::foo()
+ /// }
+ /// ```
+ ///
+ #[cfg(foo)]
+ pub fn foo() {}
+
+ #[cfg(foo)]
+ #[test]
+ fn test_foo() {
+ foo()
+ }
+ "#)
+ .file("tests/test.rs", r#"
+ #[cfg(foo)]
+ #[test]
+ fn test_bar() {}
+ "#)
+ .build();
+ assert_that(p.cargo("test").arg("-v"),
+ execs().with_stderr(format!("\
+[COMPILING] foo v0.0.1 ({dir})
+[RUNNING] `[..]`
+[RUNNING] `[..]`
+[RUNNING] `[..]`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] `[..][/]foo-[..][EXE]`
+[RUNNING] `[..][/]test-[..][EXE]`
+[DOCTEST] foo
+[RUNNING] [..] --cfg foo[..]", dir = p.url()))
+ .with_stdout_contains("test test_foo ... ok")
+ .with_stdout_contains("test test_bar ... ok")
+ .with_stdout_contains_n("test [..] ... ok", 3));
+}
+
+#[test]
+fn cfg_override_doc() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ build = "build.rs"
+ links = "a"
+
+ [dependencies.bar]
+ path = "bar"
+ "#)
+ .file(".cargo/config", &format!(r#"
+ [target.{target}.a]
+ rustc-cfg = ["foo"]
+ [target.{target}.b]
+ rustc-cfg = ["bar"]
+ "#, target = rustc_host()))
+ .file("build.rs", "")
+ .file("src/lib.rs", r#"
+ #[cfg(foo)]
+ pub fn foo() {}
+ "#)
+ .file("bar/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+ build = "build.rs"
+ links = "b"
+ "#)
+ .file("bar/build.rs", "")
+ .file("bar/src/lib.rs", r#"
+ #[cfg(bar)]
+ pub fn bar() {}
+ "#)
+ .build();
+ assert_that(p.cargo("doc"),
+ execs().with_status(0));
+ assert_that(&p.root().join("target/doc"), existing_dir());
+ assert_that(&p.root().join("target/doc/foo/fn.foo.html"), existing_file());
+ assert_that(&p.root().join("target/doc/bar/fn.bar.html"), existing_file());
+}
+
+#[test]
+fn env_build() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ build = "build.rs"
+ "#)
+ .file("src/main.rs", r#"
+ const FOO: &'static str = env!("FOO");
+ fn main() {
+ println!("{}", FOO);
+ }
+ "#)
+ .file("build.rs", r#"
+ fn main() {
+ println!("cargo:rustc-env=FOO=foo");
+ }
+ "#)
+ .build();
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(0));
+ assert_that(p.cargo("run").arg("-v"),
+ execs().with_status(0).with_stdout("foo\n"));
+}
+
+#[test]
+fn env_test() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ build = "build.rs"
+ "#)
+ .file("build.rs", r#"
+ fn main() {
+ println!("cargo:rustc-env=FOO=foo");
+ }
+ "#)
+ .file("src/lib.rs", r#"
+ pub const FOO: &'static str = env!("FOO");
+ "#)
+ .file("tests/test.rs", r#"
+ extern crate foo;
+
+ #[test]
+ fn test_foo() {
+ assert_eq!("foo", foo::FOO);
+ }
+ "#)
+ .build();
+ assert_that(p.cargo("test").arg("-v"),
+ execs().with_stderr(format!("\
+[COMPILING] foo v0.0.1 ({dir})
+[RUNNING] [..] build.rs [..]
+[RUNNING] `[..][/]build-script-build`
+[RUNNING] [..] --crate-name foo[..]
+[RUNNING] [..] --crate-name foo[..]
+[RUNNING] [..] --crate-name test[..]
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] `[..][/]foo-[..][EXE]`
+[RUNNING] `[..][/]test-[..][EXE]`
+[DOCTEST] foo
+[RUNNING] [..] --crate-name foo[..]", dir = p.url()))
+ .with_stdout_contains_n("running 0 tests", 2)
+ .with_stdout_contains("test test_foo ... ok"));
+}
+
+#[test]
+fn env_doc() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ build = "build.rs"
+ "#)
+ .file("src/main.rs", r#"
+ const FOO: &'static str = env!("FOO");
+ fn main() {}
+ "#)
+ .file("build.rs", r#"
+ fn main() {
+ println!("cargo:rustc-env=FOO=foo");
+ }
+ "#)
+ .build();
+ assert_that(p.cargo("doc").arg("-v"),
+ execs().with_status(0));
+}
+
+#[test]
+fn flags_go_into_tests() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+ authors = []
+
+ [dependencies]
+ b = { path = "b" }
+ "#)
+ .file("src/lib.rs", "")
+ .file("tests/foo.rs", "")
+ .file("b/Cargo.toml", r#"
+ [project]
+ name = "b"
+ version = "0.5.0"
+ authors = []
+ [dependencies]
+ a = { path = "../a" }
+ "#)
+ .file("b/src/lib.rs", "")
+ .file("a/Cargo.toml", r#"
+ [project]
+ name = "a"
+ version = "0.5.0"
+ authors = []
+ build = "build.rs"
+ "#)
+ .file("a/src/lib.rs", "")
+ .file("a/build.rs", r#"
+ fn main() {
+ println!("cargo:rustc-link-search=test");
+ }
+ "#)
+ .build();
+
+ assert_that(p.cargo("test").arg("-v").arg("--test=foo"),
+ execs().with_status(0)
+ .with_stderr("\
+[COMPILING] a v0.5.0 ([..]
+[RUNNING] `rustc [..] a[/]build.rs [..]`
+[RUNNING] `[..][/]build-script-build`
+[RUNNING] `rustc [..] a[/]src[/]lib.rs [..] -L test[..]`
+[COMPILING] b v0.5.0 ([..]
+[RUNNING] `rustc [..] b[/]src[/]lib.rs [..] -L test[..]`
+[COMPILING] foo v0.5.0 ([..]
+[RUNNING] `rustc [..] src[/]lib.rs [..] -L test[..]`
+[RUNNING] `rustc [..] tests[/]foo.rs [..] -L test[..]`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] `[..][/]foo-[..][EXE]`")
+ .with_stdout_contains("running 0 tests"));
+
+ assert_that(p.cargo("test").arg("-v").arg("-pb").arg("--lib"),
+ execs().with_status(0)
+ .with_stderr("\
+[FRESH] a v0.5.0 ([..]
+[COMPILING] b v0.5.0 ([..]
+[RUNNING] `rustc [..] b[/]src[/]lib.rs [..] -L test[..]`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] `[..][/]b-[..][EXE]`")
+ .with_stdout_contains("running 0 tests"));
+}
+
+#[test]
+fn diamond_passes_args_only_once() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+ authors = []
+
+ [dependencies]
+ a = { path = "a" }
+ b = { path = "b" }
+ "#)
+ .file("src/lib.rs", "")
+ .file("tests/foo.rs", "")
+ .file("a/Cargo.toml", r#"
+ [project]
+ name = "a"
+ version = "0.5.0"
+ authors = []
+ [dependencies]
+ b = { path = "../b" }
+ c = { path = "../c" }
+ "#)
+ .file("a/src/lib.rs", "")
+ .file("b/Cargo.toml", r#"
+ [project]
+ name = "b"
+ version = "0.5.0"
+ authors = []
+ [dependencies]
+ c = { path = "../c" }
+ "#)
+ .file("b/src/lib.rs", "")
+ .file("c/Cargo.toml", r#"
+ [project]
+ name = "c"
+ version = "0.5.0"
+ authors = []
+ build = "build.rs"
+ "#)
+ .file("c/build.rs", r#"
+ fn main() {
+ println!("cargo:rustc-link-search=native=test");
+ }
+ "#)
+ .file("c/src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(0).with_stderr("\
+[COMPILING] c v0.5.0 ([..]
+[RUNNING] `rustc [..]`
+[RUNNING] `[..]`
+[RUNNING] `rustc [..]`
+[COMPILING] b v0.5.0 ([..]
+[RUNNING] `rustc [..]`
+[COMPILING] a v0.5.0 ([..]
+[RUNNING] `rustc [..]`
+[COMPILING] foo v0.5.0 ([..]
+[RUNNING] `[..]rlib -L native=test`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+}
+
+#[test]
+fn adding_an_override_invalidates() {
+ let target = rustc_host();
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+ authors = []
+ links = "foo"
+ build = "build.rs"
+ "#)
+ .file("src/lib.rs", "")
+ .file(".cargo/config", "")
+ .file("build.rs", r#"
+ fn main() {
+ println!("cargo:rustc-link-search=native=foo");
+ }
+ "#)
+ .build();
+
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(0).with_stderr("\
+[COMPILING] foo v0.5.0 ([..]
+[RUNNING] `rustc [..]`
+[RUNNING] `[..]`
+[RUNNING] `rustc [..] -L native=foo`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+
+ File::create(p.root().join(".cargo/config")).unwrap().write_all(format!("
+ [target.{}.foo]
+ rustc-link-search = [\"native=bar\"]
+ ", target).as_bytes()).unwrap();
+
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(0).with_stderr("\
+[COMPILING] foo v0.5.0 ([..]
+[RUNNING] `rustc [..] -L native=bar`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+}
+
+#[test]
+fn changing_an_override_invalidates() {
+ let target = rustc_host();
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+ authors = []
+ links = "foo"
+ build = "build.rs"
+ "#)
+ .file("src/lib.rs", "")
+ .file(".cargo/config", &format!("
+ [target.{}.foo]
+ rustc-link-search = [\"native=foo\"]
+ ", target))
+ .file("build.rs", "")
+ .build();
+
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(0).with_stderr("\
+[COMPILING] foo v0.5.0 ([..]
+[RUNNING] `rustc [..] -L native=foo`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+
+ File::create(p.root().join(".cargo/config")).unwrap().write_all(format!("
+ [target.{}.foo]
+ rustc-link-search = [\"native=bar\"]
+ ", target).as_bytes()).unwrap();
+
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(0).with_stderr("\
+[COMPILING] foo v0.5.0 ([..]
+[RUNNING] `rustc [..] -L native=bar`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+}
+
+
+#[test]
+fn fresh_builds_possible_with_link_libs() {
+ // The bug is non-deterministic. Sometimes you can get a fresh build
+ let target = rustc_host();
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+ authors = []
+ links = "nativefoo"
+ build = "build.rs"
+ "#)
+ .file("src/lib.rs", "")
+ .file(".cargo/config", &format!("
+ [target.{}.nativefoo]
+ rustc-link-lib = [\"a\"]
+ rustc-link-search = [\"./b\"]
+ rustc-flags = \"-l z -L ./\"
+ ", target))
+ .file("build.rs", "")
+ .build();
+
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(0).with_stderr("\
+[COMPILING] foo v0.5.0 ([..]
+[RUNNING] `rustc [..]`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+
+ assert_that(p.cargo("build")
+ .arg("-v")
+ .env("RUST_LOG", "cargo::ops::cargo_rustc::fingerprint=info"),
+ execs().with_status(0).with_stderr("\
+[FRESH] foo v0.5.0 ([..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+}
+
+
+#[test]
+fn fresh_builds_possible_with_multiple_metadata_overrides() {
+ // The bug is non-deterministic. Sometimes you can get a fresh build
+ let target = rustc_host();
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+ authors = []
+ links = "foo"
+ build = "build.rs"
+ "#)
+ .file("src/lib.rs", "")
+ .file(".cargo/config", &format!("
+ [target.{}.foo]
+ a = \"\"
+ b = \"\"
+ c = \"\"
+ d = \"\"
+ e = \"\"
+ ", target))
+ .file("build.rs", "")
+ .build();
+
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(0).with_stderr("\
+[COMPILING] foo v0.5.0 ([..]
+[RUNNING] `rustc [..]`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+
+ assert_that(p.cargo("build")
+ .arg("-v")
+ .env("RUST_LOG", "cargo::ops::cargo_rustc::fingerprint=info"),
+ execs().with_status(0).with_stderr("\
+[FRESH] foo v0.5.0 ([..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+}
+
+
+#[test]
+fn rebuild_only_on_explicit_paths() {
+ let p = project("a")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "a"
+ version = "0.5.0"
+ authors = []
+ build = "build.rs"
+ "#)
+ .file("src/lib.rs", "")
+ .file("build.rs", r#"
+ fn main() {
+ println!("cargo:rerun-if-changed=foo");
+ println!("cargo:rerun-if-changed=bar");
+ }
+ "#)
+ .build();
+
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(0));
+
+ // files don't exist, so should always rerun if they don't exist
+ println!("run without");
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(0).with_stderr("\
+[COMPILING] a v0.5.0 ([..])
+[RUNNING] `[..][/]build-script-build`
+[RUNNING] `rustc [..] src[/]lib.rs [..]`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+
+ sleep_ms(1000);
+ File::create(p.root().join("foo")).unwrap();
+ File::create(p.root().join("bar")).unwrap();
+
+ // now the exist, so run once, catch the mtime, then shouldn't run again
+ println!("run with");
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(0).with_stderr("\
+[COMPILING] a v0.5.0 ([..])
+[RUNNING] `[..][/]build-script-build`
+[RUNNING] `rustc [..] src[/]lib.rs [..]`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+
+ println!("run with2");
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(0).with_stderr("\
+[FRESH] a v0.5.0 ([..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+
+ sleep_ms(1000);
+
+ // random other files do not affect freshness
+ println!("run baz");
+ File::create(p.root().join("baz")).unwrap();
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(0).with_stderr("\
+[FRESH] a v0.5.0 ([..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+
+ // but changing dependent files does
+ println!("run foo change");
+ File::create(p.root().join("foo")).unwrap();
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(0).with_stderr("\
+[COMPILING] a v0.5.0 ([..])
+[RUNNING] `[..][/]build-script-build`
+[RUNNING] `rustc [..] src[/]lib.rs [..]`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+
+ // .. as does deleting a file
+ println!("run foo delete");
+ fs::remove_file(p.root().join("bar")).unwrap();
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(0).with_stderr("\
+[COMPILING] a v0.5.0 ([..])
+[RUNNING] `[..][/]build-script-build`
+[RUNNING] `rustc [..] src[/]lib.rs [..]`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+}
+
+
+#[test]
+fn doctest_recieves_build_link_args() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+ authors = []
+ [dependencies.a]
+ path = "a"
+ "#)
+ .file("src/lib.rs", "")
+ .file("a/Cargo.toml", r#"
+ [project]
+ name = "a"
+ version = "0.5.0"
+ authors = []
+ links = "bar"
+ build = "build.rs"
+ "#)
+ .file("a/src/lib.rs", "")
+ .file("a/build.rs", r#"
+ fn main() {
+ println!("cargo:rustc-link-search=native=bar");
+ }
+ "#)
+ .build();
+
+ assert_that(p.cargo("test").arg("-v"),
+ execs().with_status(0)
+ .with_stderr_contains("\
+[RUNNING] `rustdoc --test [..] --crate-name foo [..]-L native=bar[..]`
+"));
+}
+
+#[test]
+fn please_respect_the_dag() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+ authors = []
+ build = "build.rs"
+
+ [dependencies]
+ a = { path = 'a' }
+ "#)
+ .file("src/lib.rs", "")
+ .file("build.rs", r#"
+ fn main() {
+ println!("cargo:rustc-link-search=native=foo");
+ }
+ "#)
+ .file("a/Cargo.toml", r#"
+ [project]
+ name = "a"
+ version = "0.5.0"
+ authors = []
+ links = "bar"
+ build = "build.rs"
+ "#)
+ .file("a/src/lib.rs", "")
+ .file("a/build.rs", r#"
+ fn main() {
+ println!("cargo:rustc-link-search=native=bar");
+ }
+ "#)
+ .build();
+
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(0)
+ .with_stderr_contains("\
+[RUNNING] `rustc [..] -L native=foo -L native=bar[..]`
+"));
+}
+
+#[test]
+fn non_utf8_output() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+ authors = []
+ build = "build.rs"
+ "#)
+ .file("build.rs", r#"
+ use std::io::prelude::*;
+
+ fn main() {
+ let mut out = std::io::stdout();
+ // print something that's not utf8
+ out.write_all(b"\xff\xff\n").unwrap();
+
+ // now print some cargo metadata that's utf8
+ println!("cargo:rustc-cfg=foo");
+
+ // now print more non-utf8
+ out.write_all(b"\xff\xff\n").unwrap();
+ }
+ "#)
+ .file("src/main.rs", r#"
+ #[cfg(foo)]
+ fn main() {}
+ "#)
+ .build();
+
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(0));
+}
+
+#[test]
+fn custom_target_dir() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+ authors = []
+
+ [dependencies]
+ a = { path = "a" }
+ "#)
+ .file("src/lib.rs", "")
+ .file(".cargo/config", r#"
+ [build]
+ target-dir = 'test'
+ "#)
+ .file("a/Cargo.toml", r#"
+ [project]
+ name = "a"
+ version = "0.5.0"
+ authors = []
+ build = "build.rs"
+ "#)
+ .file("a/build.rs", "fn main() {}")
+ .file("a/src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(0));
+}
+
+#[test]
+fn panic_abort_with_build_scripts() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+ authors = []
+
+ [profile.release]
+ panic = 'abort'
+
+ [dependencies]
+ a = { path = "a" }
+ "#)
+ .file("src/lib.rs", "#[allow(unused_extern_crates)] extern crate a;")
+ .file("a/Cargo.toml", r#"
+ [project]
+ name = "a"
+ version = "0.5.0"
+ authors = []
+ build = "build.rs"
+
+ [build-dependencies]
+ b = { path = "../b" }
+ "#)
+ .file("a/src/lib.rs", "")
+ .file("a/build.rs", "#[allow(unused_extern_crates)] extern crate b; fn main() {}")
+ .file("b/Cargo.toml", r#"
+ [project]
+ name = "b"
+ version = "0.5.0"
+ authors = []
+ "#)
+ .file("b/src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build").arg("-v").arg("--release"),
+ execs().with_status(0));
+}
+
+#[test]
+fn warnings_emitted() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+ authors = []
+ build = "build.rs"
+ "#)
+ .file("src/lib.rs", "")
+ .file("build.rs", r#"
+ fn main() {
+ println!("cargo:warning=foo");
+ println!("cargo:warning=bar");
+ }
+ "#)
+ .build();
+
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(0)
+ .with_stderr("\
+[COMPILING] foo v0.5.0 ([..])
+[RUNNING] `rustc [..]`
+[RUNNING] `[..]`
+warning: foo
+warning: bar
+[RUNNING] `rustc [..]`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+}
+
+#[test]
+fn warnings_hidden_for_upstream() {
+ Package::new("bar", "0.1.0")
+ .file("build.rs", r#"
+ fn main() {
+ println!("cargo:warning=foo");
+ println!("cargo:warning=bar");
+ }
+ "#)
+ .file("Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+ build = "build.rs"
+ "#)
+ .file("src/lib.rs", "")
+ .publish();
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+ authors = []
+
+ [dependencies]
+ bar = "*"
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(0)
+ .with_stderr("\
+[UPDATING] registry `[..]`
+[DOWNLOADING] bar v0.1.0 ([..])
+[COMPILING] bar v0.1.0
+[RUNNING] `rustc [..]`
+[RUNNING] `[..]`
+[RUNNING] `rustc [..]`
+[COMPILING] foo v0.5.0 ([..])
+[RUNNING] `rustc [..]`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+}
+
+#[test]
+fn warnings_printed_on_vv() {
+ Package::new("bar", "0.1.0")
+ .file("build.rs", r#"
+ fn main() {
+ println!("cargo:warning=foo");
+ println!("cargo:warning=bar");
+ }
+ "#)
+ .file("Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+ build = "build.rs"
+ "#)
+ .file("src/lib.rs", "")
+ .publish();
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+ authors = []
+
+ [dependencies]
+ bar = "*"
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build").arg("-vv"),
+ execs().with_status(0)
+ .with_stderr("\
+[UPDATING] registry `[..]`
+[DOWNLOADING] bar v0.1.0 ([..])
+[COMPILING] bar v0.1.0
+[RUNNING] `rustc [..]`
+[RUNNING] `[..]`
+warning: foo
+warning: bar
+[RUNNING] `rustc [..]`
+[COMPILING] foo v0.5.0 ([..])
+[RUNNING] `rustc [..]`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+}
+
+#[test]
+fn output_shows_on_vv() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+ authors = []
+ build = "build.rs"
+ "#)
+ .file("src/lib.rs", "")
+ .file("build.rs", r#"
+ use std::io::prelude::*;
+
+ fn main() {
+ std::io::stderr().write_all(b"stderr\n").unwrap();
+ std::io::stdout().write_all(b"stdout\n").unwrap();
+ }
+ "#)
+ .build();
+
+ assert_that(p.cargo("build").arg("-vv"),
+ execs().with_status(0)
+ .with_stdout("\
+stdout
+")
+ .with_stderr("\
+[COMPILING] foo v0.5.0 ([..])
+[RUNNING] `rustc [..]`
+[RUNNING] `[..]`
+stderr
+[RUNNING] `rustc [..]`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+}
+
+#[test]
+fn links_with_dots() {
+ let target = rustc_host();
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+ authors = []
+ build = "build.rs"
+ links = "a.b"
+ "#)
+ .file("src/lib.rs", "")
+ .file("build.rs", r#"
+ fn main() {
+ println!("cargo:rustc-link-search=bar")
+ }
+ "#)
+ .file(".cargo/config", &format!(r#"
+ [target.{}.'a.b']
+ rustc-link-search = ["foo"]
+ "#, target))
+ .build();
+
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(0)
+ .with_stderr_contains("\
+[RUNNING] `rustc --crate-name foo [..] [..] -L foo[..]`
+"));
+}
+
+#[test]
+fn rustc_and_rustdoc_set_correctly() {
+ let p = project("builder")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "builder"
+ version = "0.0.1"
+ authors = []
+ build = "build.rs"
+ "#)
+ .file("src/lib.rs", "")
+ .file("build.rs", r#"
+ use std::env;
+
+ fn main() {
+ assert_eq!(env::var("RUSTC").unwrap(), "rustc");
+ assert_eq!(env::var("RUSTDOC").unwrap(), "rustdoc");
+ }
+ "#)
+ .build();
+ assert_that(p.cargo("bench"),
+ execs().with_status(0));
+}
+
+#[test]
+fn cfg_env_vars_available() {
+ let p = project("builder")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "builder"
+ version = "0.0.1"
+ authors = []
+ build = "build.rs"
+ "#)
+ .file("src/lib.rs", "")
+ .file("build.rs", r#"
+ use std::env;
+
+ fn main() {
+ let fam = env::var("CARGO_CFG_TARGET_FAMILY").unwrap();
+ if cfg!(unix) {
+ assert_eq!(fam, "unix");
+ } else {
+ assert_eq!(fam, "windows");
+ }
+ }
+ "#)
+ .build();
+ assert_that(p.cargo("bench"),
+ execs().with_status(0));
+}
+
+#[test]
+fn switch_features_rerun() {
+ let p = project("builder")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "builder"
+ version = "0.0.1"
+ authors = []
+ build = "build.rs"
+
+ [features]
+ foo = []
+ "#)
+ .file("src/main.rs", r#"
+ fn main() {
+ println!(include_str!(concat!(env!("OUT_DIR"), "/output")));
+ }
+ "#)
+ .file("build.rs", r#"
+ use std::env;
+ use std::fs::File;
+ use std::io::Write;
+ use std::path::Path;
+
+ fn main() {
+ let out_dir = env::var_os("OUT_DIR").unwrap();
+ let out_dir = Path::new(&out_dir).join("output");
+ let mut f = File::create(&out_dir).unwrap();
+
+ if env::var_os("CARGO_FEATURE_FOO").is_some() {
+ f.write_all(b"foo").unwrap();
+ } else {
+ f.write_all(b"bar").unwrap();
+ }
+ }
+ "#)
+ .build();
+
+ assert_that(p.cargo("run").arg("-v").arg("--features=foo"),
+ execs().with_status(0).with_stdout("foo\n"));
+ assert_that(p.cargo("run").arg("-v"),
+ execs().with_status(0).with_stdout("bar\n"));
+ assert_that(p.cargo("run").arg("-v").arg("--features=foo"),
+ execs().with_status(0).with_stdout("foo\n"));
+}
+
+#[test]
+fn assume_build_script_when_build_rs_present() {
+ let p = project("builder")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "builder"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/main.rs", r#"
+ fn main() {
+ if ! cfg!(foo) {
+ panic!("the build script was not run");
+ }
+ }
+ "#)
+ .file("build.rs", r#"
+ fn main() {
+ println!("cargo:rustc-cfg=foo");
+ }
+ "#)
+ .build();
+
+ assert_that(p.cargo("run").arg("-v"),
+ execs().with_status(0));
+}
+
+#[test]
+fn if_build_set_to_false_dont_treat_build_rs_as_build_script() {
+ let p = project("builder")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "builder"
+ version = "0.0.1"
+ authors = []
+ build = false
+ "#)
+ .file("src/main.rs", r#"
+ fn main() {
+ if cfg!(foo) {
+ panic!("the build script was run");
+ }
+ }
+ "#)
+ .file("build.rs", r#"
+ fn main() {
+ println!("cargo:rustc-cfg=foo");
+ }
+ "#)
+ .build();
+
+ assert_that(p.cargo("run").arg("-v"),
+ execs().with_status(0));
+}
+
+#[test]
+fn deterministic_rustc_dependency_flags() {
+ // This bug is non-deterministic hence the large number of dependencies
+ // in the hopes it will have a much higher chance of triggering it.
+
+ Package::new("dep1", "0.1.0")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "dep1"
+ version = "0.1.0"
+ authors = []
+ build = "build.rs"
+ "#)
+ .file("build.rs", r#"
+ fn main() {
+ println!("cargo:rustc-flags=-L native=test1");
+ }
+ "#)
+ .file("src/lib.rs", "")
+ .publish();
+ Package::new("dep2", "0.1.0")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "dep2"
+ version = "0.1.0"
+ authors = []
+ build = "build.rs"
+ "#)
+ .file("build.rs", r#"
+ fn main() {
+ println!("cargo:rustc-flags=-L native=test2");
+ }
+ "#)
+ .file("src/lib.rs", "")
+ .publish();
+ Package::new("dep3", "0.1.0")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "dep3"
+ version = "0.1.0"
+ authors = []
+ build = "build.rs"
+ "#)
+ .file("build.rs", r#"
+ fn main() {
+ println!("cargo:rustc-flags=-L native=test3");
+ }
+ "#)
+ .file("src/lib.rs", "")
+ .publish();
+ Package::new("dep4", "0.1.0")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "dep4"
+ version = "0.1.0"
+ authors = []
+ build = "build.rs"
+ "#)
+ .file("build.rs", r#"
+ fn main() {
+ println!("cargo:rustc-flags=-L native=test4");
+ }
+ "#)
+ .file("src/lib.rs", "")
+ .publish();
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+
+ [dependencies]
+ dep1 = "*"
+ dep2 = "*"
+ dep3 = "*"
+ dep4 = "*"
+ "#)
+ .file("src/main.rs", r#"
+ fn main() {}
+ "#)
+ .build();
+
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(0)
+ .with_stderr_contains("\
+[RUNNING] `rustc --crate-name foo [..] -L native=test1 -L native=test2 \
+-L native=test3 -L native=test4`
+"));
+}
+
+#[test]
+fn links_duplicates_with_cycle() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+ authors = []
+ links = "a"
+ build = "build.rs"
+
+ [dependencies.a]
+ path = "a"
+
+ [dev-dependencies]
+ b = { path = "b" }
+ "#)
+ .file("src/lib.rs", "")
+ .file("build.rs", "")
+ .file("a/Cargo.toml", r#"
+ [project]
+ name = "a"
+ version = "0.5.0"
+ authors = []
+ links = "a"
+ build = "build.rs"
+ "#)
+ .file("a/src/lib.rs", "")
+ .file("a/build.rs", "")
+ .file("b/Cargo.toml", r#"
+ [project]
+ name = "b"
+ version = "0.5.0"
+ authors = []
+
+ [dependencies]
+ foo = { path = ".." }
+ "#)
+ .file("b/src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101)
+ .with_stderr("\
+[ERROR] multiple packages link to native library `a`, but a native library can \
+be linked only once
+
+package `foo v0.5.0 ([..])`
+ ... which is depended on by `b v0.5.0 ([..])`
+links to native library `a`
+
+package `a v0.5.0 (file://[..])`
+ ... which is depended on by `foo v0.5.0 ([..])`
+ ... which is depended on by `b v0.5.0 ([..])`
+also links to native library `a`
+"));
+}
+
+#[test]
+fn rename_with_link_search_path() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+ authors = []
+
+ [lib]
+ crate-type = ["cdylib"]
+ "#)
+ .file("src/lib.rs", "
+ #[no_mangle]
+ pub extern fn cargo_test_foo() {}
+ ");
+ let p = p.build();
+
+ assert_that(p.cargo("build"), execs().with_status(0));
+
+ let p2 = project("bar")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.5.0"
+ authors = []
+ "#)
+ .file("build.rs", r#"
+ use std::env;
+ use std::fs;
+ use std::path::PathBuf;
+
+ fn main() {
+ // Move the `libfoo.so` from the root of our project into the
+ // build directory. This way Cargo should automatically manage
+ // `LD_LIBRARY_PATH` and such.
+ let root = PathBuf::from(env::var_os("CARGO_MANIFEST_DIR").unwrap());
+ let file = format!("{}foo{}", env::consts::DLL_PREFIX, env::consts::DLL_SUFFIX);
+ let src = root.join(&file);
+
+ let dst_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
+ let dst = dst_dir.join(&file);
+
+ fs::copy(&src, &dst).unwrap();
+ // handle windows, like below
+ drop(fs::copy(root.join("foo.dll.lib"), dst_dir.join("foo.dll.lib")));
+
+ println!("cargo:rerun-if-changed=build.rs");
+ if cfg!(target_env = "msvc") {
+ println!("cargo:rustc-link-lib=foo.dll");
+ } else {
+ println!("cargo:rustc-link-lib=foo");
+ }
+ println!("cargo:rustc-link-search={}",
+ dst.parent().unwrap().display());
+ }
+ "#)
+ .file("src/main.rs", r#"
+ extern {
+ #[link_name = "cargo_test_foo"]
+ fn foo();
+ }
+
+ fn main() {
+ unsafe { foo(); }
+ }
+ "#);
+ let p2 = p2.build();
+
+ // Move the output `libfoo.so` into the directory of `p2`, and then delete
+ // the `p` project. On OSX the `libfoo.dylib` artifact references the
+ // original path in `p` so we want to make sure that it can't find it (hence
+ // the deletion).
+ let root = PathBuf::from(p.root());
+ let root = root.join("target").join("debug").join("deps");
+ let file = format!("{}foo{}", env::consts::DLL_PREFIX, env::consts::DLL_SUFFIX);
+ let src = root.join(&file);
+
+ let dst = p2.root().join(&file);
+
+ fs::copy(&src, &dst).unwrap();
+ // copy the import library for windows, if it exists
+ drop(fs::copy(&root.join("foo.dll.lib"), p2.root().join("foo.dll.lib")));
+ fs::remove_dir_all(p.root()).unwrap();
+
+ // Everything should work the first time
+ assert_that(p2.cargo("run"),
+ execs().with_status(0));
+
+ // Now rename the root directory and rerun `cargo run`. Not only should we
+ // not build anything but we also shouldn't crash.
+ let mut new = p2.root();
+ new.pop();
+ new.push("bar2");
+ fs::rename(p2.root(), &new).unwrap();
+ assert_that(p2.cargo("run").cwd(&new),
+ execs().with_status(0)
+ .with_stderr("\
+[FINISHED] [..]
+[RUNNING] [..]
+"));
+}
--- /dev/null
+use std::fs::File;
+
+use cargotest::sleep_ms;
+use cargotest::support::{project, execs};
+use hamcrest::assert_that;
+
+#[test]
+fn rerun_if_env_changes() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.5.0"
+ authors = []
+ "#)
+ .file("src/main.rs", r#"
+ fn main() {}
+ "#)
+ .file("build.rs", r#"
+ fn main() {
+ println!("cargo:rerun-if-env-changed=FOO");
+ }
+ "#)
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0)
+ .with_stderr("\
+[COMPILING] foo v0.5.0 ([..])
+[FINISHED] [..]
+"));
+ assert_that(p.cargo("build").env("FOO", "bar"),
+ execs().with_status(0)
+ .with_stderr("\
+[COMPILING] foo v0.5.0 ([..])
+[FINISHED] [..]
+"));
+ assert_that(p.cargo("build").env("FOO", "baz"),
+ execs().with_status(0)
+ .with_stderr("\
+[COMPILING] foo v0.5.0 ([..])
+[FINISHED] [..]
+"));
+ assert_that(p.cargo("build").env("FOO", "baz"),
+ execs().with_status(0)
+ .with_stderr("\
+[FINISHED] [..]
+"));
+ assert_that(p.cargo("build"),
+ execs().with_status(0)
+ .with_stderr("\
+[COMPILING] foo v0.5.0 ([..])
+[FINISHED] [..]
+"));
+}
+
+#[test]
+fn rerun_if_env_or_file_changes() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.5.0"
+ authors = []
+ "#)
+ .file("src/main.rs", r#"
+ fn main() {}
+ "#)
+ .file("build.rs", r#"
+ fn main() {
+ println!("cargo:rerun-if-env-changed=FOO");
+ println!("cargo:rerun-if-changed=foo");
+ }
+ "#)
+ .file("foo", "")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0)
+ .with_stderr("\
+[COMPILING] foo v0.5.0 ([..])
+[FINISHED] [..]
+"));
+ assert_that(p.cargo("build").env("FOO", "bar"),
+ execs().with_status(0)
+ .with_stderr("\
+[COMPILING] foo v0.5.0 ([..])
+[FINISHED] [..]
+"));
+ assert_that(p.cargo("build").env("FOO", "bar"),
+ execs().with_status(0)
+ .with_stderr("\
+[FINISHED] [..]
+"));
+ sleep_ms(1000);
+ File::create(p.root().join("foo")).unwrap();
+ assert_that(p.cargo("build").env("FOO", "bar"),
+ execs().with_status(0)
+ .with_stderr("\
+[COMPILING] foo v0.5.0 ([..])
+[FINISHED] [..]
+"));
+}
--- /dev/null
+use std::env;
+use std::fs::{self, File};
+use std::io::prelude::*;
+use std::path::{Path, PathBuf};
+use std::str;
+
+use cargotest::cargo_process;
+use cargotest::support::paths::{self, CargoPathExt};
+use cargotest::support::{execs, project, Project, basic_bin_manifest};
+use hamcrest::{assert_that, existing_file};
+
+#[cfg_attr(windows,allow(dead_code))]
+enum FakeKind<'a> {
+ Executable,
+ Symlink{target:&'a Path},
+}
+
+/// Add an empty file with executable flags (and platform-dependent suffix).
+/// TODO: move this to `Project` if other cases using this emerge.
+fn fake_file(proj: Project, dir: &Path, name: &str, kind: &FakeKind) -> Project {
+ let path = proj.root().join(dir).join(&format!("{}{}", name,
+ env::consts::EXE_SUFFIX));
+ path.parent().unwrap().mkdir_p();
+ match *kind {
+ FakeKind::Executable => {
+ File::create(&path).unwrap();
+ make_executable(&path);
+ },
+ FakeKind::Symlink{target} => {
+ make_symlink(&path,target);
+ }
+ }
+ return proj;
+
+ #[cfg(unix)]
+ fn make_executable(p: &Path) {
+ use std::os::unix::prelude::*;
+
+ let mut perms = fs::metadata(p).unwrap().permissions();
+ let mode = perms.mode();
+ perms.set_mode(mode | 0o111);
+ fs::set_permissions(p, perms).unwrap();
+ }
+ #[cfg(windows)]
+ fn make_executable(_: &Path) {}
+ #[cfg(unix)]
+ fn make_symlink(p: &Path, t: &Path) {
+ ::std::os::unix::fs::symlink(t,p).expect("Failed to create symlink");
+ }
+ #[cfg(windows)]
+ fn make_symlink(_: &Path, _: &Path) {
+ panic!("Not supported")
+ }
+}
+
+fn path() -> Vec<PathBuf> {
+ env::split_paths(&env::var_os("PATH").unwrap_or_default()).collect()
+}
+
+#[test]
+fn list_command_looks_at_path() {
+ let proj = project("list-non-overlapping").build();
+ let proj = fake_file(proj, Path::new("path-test"), "cargo-1", &FakeKind::Executable);
+ let mut pr = cargo_process();
+
+ let mut path = path();
+ path.push(proj.root().join("path-test"));
+ let path = env::join_paths(path.iter()).unwrap();
+ let output = pr.arg("-v").arg("--list")
+ .env("PATH", &path);
+ let output = output.exec_with_output().unwrap();
+ let output = str::from_utf8(&output.stdout).unwrap();
+ assert!(output.contains("\n 1 "), "missing 1: {}", output);
+}
+
+// windows and symlinks don't currently agree that well
+#[cfg(unix)]
+#[test]
+fn list_command_resolves_symlinks() {
+ use cargotest::support::cargo_exe;
+
+ let proj = project("list-non-overlapping").build();
+ let proj = fake_file(proj, Path::new("path-test"), "cargo-2",
+ &FakeKind::Symlink{target:&cargo_exe()});
+ let mut pr = cargo_process();
+
+ let mut path = path();
+ path.push(proj.root().join("path-test"));
+ let path = env::join_paths(path.iter()).unwrap();
+ let output = pr.arg("-v").arg("--list")
+ .env("PATH", &path);
+ let output = output.exec_with_output().unwrap();
+ let output = str::from_utf8(&output.stdout).unwrap();
+ assert!(output.contains("\n 2 "), "missing 2: {}", output);
+}
+
+#[test]
+fn find_closest_biuld_to_build() {
+ let mut pr = cargo_process();
+ pr.arg("biuld");
+
+ assert_that(pr,
+ execs().with_status(101)
+ .with_stderr("[ERROR] no such subcommand: `biuld`
+
+<tab>Did you mean `build`?
+
+"));
+}
+
+// if a subcommand is more than 3 edit distance away, we don't make a suggestion
+#[test]
+fn find_closest_dont_correct_nonsense() {
+ let mut pr = cargo_process();
+ pr.arg("there-is-no-way-that-there-is-a-command-close-to-this")
+ .cwd(&paths::root());
+
+ assert_that(pr,
+ execs().with_status(101)
+ .with_stderr("[ERROR] no such subcommand: \
+ `there-is-no-way-that-there-is-a-command-close-to-this`
+"));
+}
+
+#[test]
+fn displays_subcommand_on_error() {
+ let mut pr = cargo_process();
+ pr.arg("invalid-command");
+
+ assert_that(pr,
+ execs().with_status(101)
+ .with_stderr("[ERROR] no such subcommand: `invalid-command`
+"));
+}
+
+#[test]
+fn override_cargo_home() {
+ let root = paths::root();
+ let my_home = root.join("my_home");
+ fs::create_dir(&my_home).unwrap();
+ File::create(&my_home.join("config")).unwrap().write_all(br#"
+ [cargo-new]
+ name = "foo"
+ email = "bar"
+ git = false
+ "#).unwrap();
+
+ assert_that(cargo_process()
+ .arg("new").arg("foo")
+ .env("USER", "foo")
+ .env("CARGO_HOME", &my_home),
+ execs().with_status(0));
+
+ let toml = paths::root().join("foo/Cargo.toml");
+ let mut contents = String::new();
+ File::open(&toml).unwrap().read_to_string(&mut contents).unwrap();
+ assert!(contents.contains(r#"authors = ["foo <bar>"]"#));
+}
+
+#[test]
+fn cargo_subcommand_env() {
+ use cargotest::support::cargo_exe;
+
+ let src = format!(r#"
+ use std::env;
+
+ fn main() {{
+ println!("{{}}", env::var("{}").unwrap());
+ }}
+ "#, cargo::CARGO_ENV);
+
+ let p = project("cargo-envtest")
+ .file("Cargo.toml", &basic_bin_manifest("cargo-envtest"))
+ .file("src/main.rs", &src)
+ .build();
+
+ let target_dir = p.target_debug_dir();
+
+ assert_that(p.cargo("build"), execs().with_status(0));
+ assert_that(&p.bin("cargo-envtest"), existing_file());
+
+ let mut pr = cargo_process();
+ let cargo = cargo_exe().canonicalize().unwrap();
+ let mut path = path();
+ path.push(target_dir);
+ let path = env::join_paths(path.iter()).unwrap();
+
+ assert_that(pr.arg("envtest").env("PATH", &path),
+ execs().with_status(0).with_stdout(cargo.to_str().unwrap()));
+}
+
+#[test]
+fn cargo_help() {
+ assert_that(cargo_process(),
+ execs().with_status(0));
+ assert_that(cargo_process().arg("help"),
+ execs().with_status(0));
+ assert_that(cargo_process().arg("-h"),
+ execs().with_status(0));
+ assert_that(cargo_process().arg("help").arg("build"),
+ execs().with_status(0));
+ assert_that(cargo_process().arg("build").arg("-h"),
+ execs().with_status(0));
+ assert_that(cargo_process().arg("help").arg("-h"),
+ execs().with_status(0));
+ assert_that(cargo_process().arg("help").arg("help"),
+ execs().with_status(0));
+}
+
+#[test]
+fn explain() {
+ assert_that(cargo_process().arg("--explain").arg("E0001"),
+ execs().with_status(0));
+}
--- /dev/null
+use cargotest::support::{project, execs, basic_bin_manifest};
+use hamcrest::{assert_that};
+
+#[test]
+fn alias_incorrect_config_type() {
+ let p = project("foo")
+ .file("Cargo.toml", &basic_bin_manifest("foo"))
+ .file("src/main.rs", r#"
+ fn main() {
+ }"#)
+ .file(".cargo/config",r#"
+ [alias]
+ b-cargo-test = 5
+ "#)
+ .build();
+
+ assert_that(p.cargo("b-cargo-test").arg("-v"),
+ execs().with_status(101).
+ with_stderr_contains("[ERROR] invalid configuration \
+for key `alias.b-cargo-test`
+expected a list, but found a integer for [..]"));
+}
+
+
+#[test]
+fn alias_default_config_overrides_config() {
+ let p = project("foo")
+ .file("Cargo.toml", &basic_bin_manifest("foo"))
+ .file("src/main.rs", r#"
+ fn main() {
+ }"#)
+ .file(".cargo/config",r#"
+ [alias]
+ b = "not_build"
+ "#)
+ .build();
+
+ assert_that(p.cargo("b").arg("-v"),
+ execs().with_status(0).
+ with_stderr_contains("[COMPILING] foo v0.5.0 [..]"));
+}
+
+#[test]
+fn alias_config() {
+ let p = project("foo")
+ .file("Cargo.toml", &basic_bin_manifest("foo"))
+ .file("src/main.rs", r#"
+ fn main() {
+ }"#)
+ .file(".cargo/config",r#"
+ [alias]
+ b-cargo-test = "build"
+ "#)
+ .build();
+
+ assert_that(p.cargo("b-cargo-test").arg("-v"),
+ execs().with_status(0).
+ with_stderr_contains("[COMPILING] foo v0.5.0 [..]
+[RUNNING] `rustc --crate-name foo [..]"));
+}
+
+#[test]
+fn alias_list_test() {
+ let p = project("foo")
+ .file("Cargo.toml", &basic_bin_manifest("foo"))
+ .file("src/main.rs", r#"
+ fn main() {
+ }"#)
+ .file(".cargo/config",r#"
+ [alias]
+ b-cargo-test = ["build", "--release"]
+ "#)
+ .build();
+
+ assert_that(p.cargo("b-cargo-test").arg("-v"),
+ execs().with_status(0).
+ with_stderr_contains("[COMPILING] foo v0.5.0 [..]").
+ with_stderr_contains("[RUNNING] `rustc --crate-name [..]")
+ );
+}
+
+#[test]
+fn alias_with_flags_config() {
+ let p = project("foo")
+ .file("Cargo.toml", &basic_bin_manifest("foo"))
+ .file("src/main.rs", r#"
+ fn main() {
+ }"#)
+ .file(".cargo/config",r#"
+ [alias]
+ b-cargo-test = "build --release"
+ "#)
+ .build();
+
+ assert_that(p.cargo("b-cargo-test").arg("-v"),
+ execs().with_status(0).
+ with_stderr_contains("[COMPILING] foo v0.5.0 [..]").
+ with_stderr_contains("[RUNNING] `rustc --crate-name foo [..]")
+ );
+}
+
+#[test]
+fn cant_shadow_builtin() {
+ let p = project("foo")
+ .file("Cargo.toml", &basic_bin_manifest("foo"))
+ .file("src/main.rs", r#"
+ fn main() {
+ }"#)
+ .file(".cargo/config",r#"
+ [alias]
+ build = "fetch"
+ "#)
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0)
+ .with_stderr("\
+[COMPILING] foo v0.5.0 ([..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+}
--- /dev/null
+use cargotest::ChannelChanger;
+use cargotest::support::{project, execs};
+use hamcrest::assert_that;
+
+#[test]
+fn feature_required() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "a"
+ version = "0.0.1"
+ authors = []
+ im-a-teapot = true
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+ assert_that(p.cargo("build")
+ .masquerade_as_nightly_cargo(),
+ execs().with_status(101)
+ .with_stderr("\
+error: failed to parse manifest at `[..]`
+
+Caused by:
+ the `im-a-teapot` manifest key is unstable and may not work properly in England
+
+Caused by:
+ feature `test-dummy-unstable` is required
+
+consider adding `cargo-features = [\"test-dummy-unstable\"]` to the manifest
+"));
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101)
+ .with_stderr("\
+error: failed to parse manifest at `[..]`
+
+Caused by:
+ the `im-a-teapot` manifest key is unstable and may not work properly in England
+
+Caused by:
+ feature `test-dummy-unstable` is required
+
+this Cargo does not support nightly features, but if you
+switch to nightly channel you can add
+`cargo-features = [\"test-dummy-unstable\"]` to enable this feature
+"));
+}
+
+#[test]
+fn unknown_feature() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ cargo-features = ["foo"]
+
+ [package]
+ name = "a"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+ assert_that(p.cargo("build"),
+ execs().with_status(101)
+ .with_stderr("\
+error: failed to parse manifest at `[..]`
+
+Caused by:
+ unknown cargo feature `foo`
+"));
+}
+
+#[test]
+fn stable_feature_warns() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ cargo-features = ["test-dummy-stable"]
+
+ [package]
+ name = "a"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+ assert_that(p.cargo("build"),
+ execs().with_status(0)
+ .with_stderr("\
+warning: the cargo feature `test-dummy-stable` is now stable and is no longer \
+necessary to be listed in the manifest
+[COMPILING] a [..]
+[FINISHED] [..]
+"));
+}
+
+#[test]
+fn nightly_feature_requires_nightly() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ cargo-features = ["test-dummy-unstable"]
+
+ [package]
+ name = "a"
+ version = "0.0.1"
+ authors = []
+ im-a-teapot = true
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+ assert_that(p.cargo("build")
+ .masquerade_as_nightly_cargo(),
+ execs().with_status(0)
+ .with_stderr("\
+[COMPILING] a [..]
+[FINISHED] [..]
+"));
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101)
+ .with_stderr("\
+error: failed to parse manifest at `[..]`
+
+Caused by:
+ the cargo feature `test-dummy-unstable` requires a nightly version of Cargo, \
+ but this is the `stable` channel
+"));
+}
+
+#[test]
+fn nightly_feature_requires_nightly_in_dep() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "b"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ a = { path = "a" }
+ "#)
+ .file("src/lib.rs", "")
+ .file("a/Cargo.toml", r#"
+ cargo-features = ["test-dummy-unstable"]
+
+ [package]
+ name = "a"
+ version = "0.0.1"
+ authors = []
+ im-a-teapot = true
+ "#)
+ .file("a/src/lib.rs", "")
+ .build();
+ assert_that(p.cargo("build")
+ .masquerade_as_nightly_cargo(),
+ execs().with_status(0)
+ .with_stderr("\
+[COMPILING] a [..]
+[COMPILING] b [..]
+[FINISHED] [..]
+"));
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101)
+ .with_stderr("\
+error: failed to load source for a dependency on `a`
+
+Caused by:
+ Unable to update [..]
+
+Caused by:
+ failed to parse manifest at `[..]`
+
+Caused by:
+ the cargo feature `test-dummy-unstable` requires a nightly version of Cargo, \
+ but this is the `stable` channel
+"));
+}
+
+#[test]
+fn cant_publish() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ cargo-features = ["test-dummy-unstable"]
+
+ [package]
+ name = "a"
+ version = "0.0.1"
+ authors = []
+ im-a-teapot = true
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+ assert_that(p.cargo("build")
+ .masquerade_as_nightly_cargo(),
+ execs().with_status(0)
+ .with_stderr("\
+[COMPILING] a [..]
+[FINISHED] [..]
+"));
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101)
+ .with_stderr("\
+error: failed to parse manifest at `[..]`
+
+Caused by:
+ the cargo feature `test-dummy-unstable` requires a nightly version of Cargo, \
+ but this is the `stable` channel
+"));
+}
+
+#[test]
+fn z_flags_rejected() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ cargo-features = ["test-dummy-unstable"]
+
+ [package]
+ name = "a"
+ version = "0.0.1"
+ authors = []
+ im-a-teapot = true
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+ assert_that(p.cargo("build")
+ .arg("-Zprint-im-a-teapot"),
+ execs().with_status(101)
+ .with_stderr("\
+error: the `-Z` flag is only accepted on the nightly channel of Cargo
+"));
+
+ assert_that(p.cargo("build")
+ .masquerade_as_nightly_cargo()
+ .arg("-Zarg"),
+ execs().with_status(101)
+ .with_stderr("\
+error: unknown `-Z` flag specified: arg
+"));
+
+ assert_that(p.cargo("build")
+ .masquerade_as_nightly_cargo()
+ .arg("-Zprint-im-a-teapot"),
+ execs().with_status(0)
+ .with_stdout("im-a-teapot = true\n")
+ .with_stderr("\
+[COMPILING] a [..]
+[FINISHED] [..]
+"));
+}
+
+#[test]
+fn publish_rejected() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ cargo-features = ["test-dummy-unstable"]
+
+ [package]
+ name = "a"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+ assert_that(p.cargo("publish")
+ .masquerade_as_nightly_cargo(),
+ execs().with_status(101)
+ .with_stderr("\
+error: cannot publish crates which activate nightly-only cargo features to crates.io
+"));
+}
--- /dev/null
+[package]
+name = "cargotest"
+version = "0.1.0"
+authors = ["Alex Crichton <alex@alexcrichton.com>"]
+
+[lib]
+path = "lib.rs"
+
+[dependencies]
+cargo = { path = "../../.." }
+filetime = "0.1"
+flate2 = "1.0"
+git2 = { version = "0.6", default-features = false }
+hamcrest = "=0.1.1"
+hex = "0.3"
+log = "0.4"
+serde_json = "1.0"
+tar = { version = "0.4", default-features = false }
+url = "1.1"
--- /dev/null
+use std::fmt;
+use std::path::{PathBuf, Path};
+
+use hamcrest::{Matcher, MatchResult, existing_file};
+use support::paths;
+
+pub use self::InstalledExe as has_installed_exe;
+
+pub fn cargo_home() -> PathBuf {
+ paths::home().join(".cargo")
+}
+
+pub struct InstalledExe(pub &'static str);
+
+pub fn exe(name: &str) -> String {
+ if cfg!(windows) {format!("{}.exe", name)} else {name.to_string()}
+}
+
+impl<P: AsRef<Path>> Matcher<P> for InstalledExe {
+ fn matches(&self, path: P) -> MatchResult {
+ let path = path.as_ref().join("bin").join(exe(self.0));
+ existing_file().matches(&path)
+ }
+}
+
+impl fmt::Display for InstalledExe {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "installed exe `{}`", self.0)
+ }
+}
--- /dev/null
+#![deny(warnings)]
+
+extern crate cargo;
+extern crate filetime;
+extern crate flate2;
+extern crate git2;
+extern crate hamcrest;
+extern crate hex;
+#[macro_use]
+extern crate serde_json;
+extern crate tar;
+extern crate url;
+
+use std::ffi::OsStr;
+use std::time::Duration;
+
+use cargo::util::Rustc;
+use std::path::PathBuf;
+
+pub mod support;
+pub mod install;
+
+thread_local!(pub static RUSTC: Rustc = Rustc::new(PathBuf::from("rustc"), None).unwrap());
+
+pub fn rustc_host() -> String {
+ RUSTC.with(|r| r.host.clone())
+}
+
+pub fn is_nightly() -> bool {
+ RUSTC.with(|r| {
+ r.verbose_version.contains("-nightly") ||
+ r.verbose_version.contains("-dev")
+ })
+}
+
+pub fn process<T: AsRef<OsStr>>(t: T) -> cargo::util::ProcessBuilder {
+ _process(t.as_ref())
+}
+
+fn _process(t: &OsStr) -> cargo::util::ProcessBuilder {
+ let mut p = cargo::util::process(t);
+ p.cwd(&support::paths::root())
+ .env_remove("CARGO_HOME")
+ .env("HOME", support::paths::home())
+ .env("CARGO_HOME", support::paths::home().join(".cargo"))
+ .env("__CARGO_TEST_ROOT", support::paths::root())
+
+ // Force cargo to think it's on the stable channel for all tests, this
+ // should hopefully not surprise us as we add cargo features over time and
+ // cargo rides the trains.
+ .env("__CARGO_TEST_CHANNEL_OVERRIDE_DO_NOT_USE_THIS", "stable")
+
+ // For now disable incremental by default as support hasn't ridden to the
+ // stable channel yet. Once incremental support hits the stable compiler we
+ // can switch this to one and then fix the tests.
+ .env("CARGO_INCREMENTAL", "0")
+
+ // This env var can switch the git backend from libgit2 to git2-curl, which
+ // can tweak error messages and cause some tests to fail, so let's forcibly
+ // remove it.
+ .env_remove("CARGO_HTTP_CHECK_REVOKE")
+
+ .env_remove("__CARGO_DEFAULT_LIB_METADATA")
+ .env_remove("RUSTC")
+ .env_remove("RUSTDOC")
+ .env_remove("RUSTC_WRAPPER")
+ .env_remove("RUSTFLAGS")
+ .env_remove("XDG_CONFIG_HOME") // see #2345
+ .env("GIT_CONFIG_NOSYSTEM", "1") // keep trying to sandbox ourselves
+ .env_remove("EMAIL")
+ .env_remove("MFLAGS")
+ .env_remove("MAKEFLAGS")
+ .env_remove("CARGO_MAKEFLAGS")
+ .env_remove("GIT_AUTHOR_NAME")
+ .env_remove("GIT_AUTHOR_EMAIL")
+ .env_remove("GIT_COMMITTER_NAME")
+ .env_remove("GIT_COMMITTER_EMAIL")
+ .env_remove("CARGO_TARGET_DIR") // we assume 'target'
+ .env_remove("MSYSTEM"); // assume cmd.exe everywhere on windows
+ return p
+}
+
+pub trait ChannelChanger: Sized {
+ fn masquerade_as_nightly_cargo(&mut self) -> &mut Self;
+}
+
+impl ChannelChanger for cargo::util::ProcessBuilder {
+ fn masquerade_as_nightly_cargo(&mut self) -> &mut Self {
+ self.env("__CARGO_TEST_CHANNEL_OVERRIDE_DO_NOT_USE_THIS", "nightly")
+ }
+}
+
+pub fn cargo_process() -> cargo::util::ProcessBuilder {
+ process(&support::cargo_exe())
+}
+
+pub fn sleep_ms(ms: u64) {
+ std::thread::sleep(Duration::from_millis(ms));
+}
--- /dev/null
+use std::env;
+use std::process::Command;
+use std::sync::{Once, ONCE_INIT};
+use std::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering};
+
+use support::{project, main_file, basic_bin_manifest};
+
+pub fn disabled() -> bool {
+ // First, disable if ./configure requested so
+ match env::var("CFG_DISABLE_CROSS_TESTS") {
+ Ok(ref s) if *s == "1" => return true,
+ _ => {}
+ }
+
+ // Right now the windows bots cannot cross compile due to the mingw setup,
+ // so we disable ourselves on all but macos/linux setups where the rustc
+ // install script ensures we have both architectures
+ if !(cfg!(target_os = "macos") ||
+ cfg!(target_os = "linux") ||
+ cfg!(target_env = "msvc")) {
+ return true;
+ }
+
+ // It's not particularly common to have a cross-compilation setup, so
+ // try to detect that before we fail a bunch of tests through no fault
+ // of the user.
+ static CAN_RUN_CROSS_TESTS: AtomicBool = ATOMIC_BOOL_INIT;
+ static CHECK: Once = ONCE_INIT;
+
+ let cross_target = alternate();
+
+ CHECK.call_once(|| {
+ let p = project("cross_test")
+ .file("Cargo.toml", &basic_bin_manifest("cross_test"))
+ .file("src/cross_test.rs", &main_file(r#""testing!""#, &[]))
+ .build();
+
+ let result = p.cargo("build")
+ .arg("--target").arg(&cross_target)
+ .exec_with_output();
+
+ if result.is_ok() {
+ CAN_RUN_CROSS_TESTS.store(true, Ordering::SeqCst);
+ }
+ });
+
+ if CAN_RUN_CROSS_TESTS.load(Ordering::SeqCst) {
+ // We were able to compile a simple project, so the user has the
+ // necessary std:: bits installed. Therefore, tests should not
+ // be disabled.
+ return false;
+ }
+
+ // We can't compile a simple cross project. We want to warn the user
+ // by failing a single test and having the remainder of the cross tests
+ // pass. We don't use std::sync::Once here because panicing inside its
+ // call_once method would poison the Once instance, which is not what
+ // we want.
+ static HAVE_WARNED: AtomicBool = ATOMIC_BOOL_INIT;
+
+ if HAVE_WARNED.swap(true, Ordering::SeqCst) {
+ // We are some other test and somebody else is handling the warning.
+ // Just disable the current test.
+ return true;
+ }
+
+ // We are responsible for warning the user, which we do by panicing.
+ let rustup_available = Command::new("rustup").output().is_ok();
+
+ let linux_help = if cfg!(target_os = "linux") {
+ "
+
+You may need to install runtime libraries for your Linux distribution as well.".to_string()
+ } else {
+ "".to_string()
+ };
+
+ let rustup_help = if rustup_available {
+ format!("
+
+Alternatively, you can install the necessary libraries for cross-compilation with
+
+ rustup target add {}{}", cross_target, linux_help)
+ } else {
+ "".to_string()
+ };
+
+ panic!("Cannot cross compile to {}.
+
+This failure can be safely ignored. If you would prefer to not see this
+failure, you can set the environment variable CFG_DISABLE_CROSS_TESTS to \"1\".{}
+", cross_target, rustup_help);
+}
+
+pub fn alternate() -> String {
+ let platform = match env::consts::OS {
+ "linux" => "unknown-linux-gnu",
+ "macos" => "apple-darwin",
+ "windows" => "pc-windows-msvc",
+ _ => unreachable!(),
+ };
+ let arch = match env::consts::ARCH {
+ "x86" => "x86_64",
+ "x86_64" => "i686",
+ _ => unreachable!(),
+ };
+ format!("{}-{}", arch, platform)
+}
+
+pub fn alternate_arch() -> &'static str {
+ match env::consts::ARCH {
+ "x86" => "x86_64",
+ "x86_64" => "x86",
+ _ => unreachable!(),
+ }
+}
+
+pub fn host() -> String {
+ let platform = match env::consts::OS {
+ "linux" => "unknown-linux-gnu",
+ "macos" => "apple-darwin",
+ "windows" => "pc-windows-msvc",
+ _ => unreachable!(),
+ };
+ let arch = match env::consts::ARCH {
+ "x86" => "i686",
+ "x86_64" => "x86_64",
+ _ => unreachable!(),
+ };
+ format!("{}-{}", arch, platform)
+}
--- /dev/null
+use std::fs::{self, File};
+use std::io::prelude::*;
+use std::path::{Path, PathBuf};
+
+use url::Url;
+use git2;
+
+use cargo::util::ProcessError;
+use support::{ProjectBuilder, Project, project, path2url};
+
+#[must_use]
+pub struct RepoBuilder {
+ repo: git2::Repository,
+ files: Vec<PathBuf>,
+}
+
+pub struct Repository(git2::Repository);
+
+pub fn repo(p: &Path) -> RepoBuilder { RepoBuilder::init(p) }
+
+impl RepoBuilder {
+ pub fn init(p: &Path) -> RepoBuilder {
+ t!(fs::create_dir_all(p.parent().unwrap()));
+ let repo = t!(git2::Repository::init(p));
+ {
+ let mut config = t!(repo.config());
+ t!(config.set_str("user.name", "name"));
+ t!(config.set_str("user.email", "email"));
+ }
+ RepoBuilder { repo: repo, files: Vec::new() }
+ }
+
+ pub fn file(self, path: &str, contents: &str) -> RepoBuilder {
+ let mut me = self.nocommit_file(path, contents);
+ me.files.push(PathBuf::from(path));
+ me
+ }
+
+ pub fn nocommit_file(self, path: &str, contents: &str) -> RepoBuilder {
+ let dst = self.repo.workdir().unwrap().join(path);
+ t!(fs::create_dir_all(dst.parent().unwrap()));
+ t!(t!(File::create(&dst)).write_all(contents.as_bytes()));
+ self
+ }
+
+ pub fn build(self) -> Repository {
+ {
+ let mut index = t!(self.repo.index());
+ for file in self.files.iter() {
+ t!(index.add_path(file));
+ }
+ t!(index.write());
+ let id = t!(index.write_tree());
+ let tree = t!(self.repo.find_tree(id));
+ let sig = t!(self.repo.signature());
+ t!(self.repo.commit(Some("HEAD"), &sig, &sig,
+ "Initial commit", &tree, &[]));
+ }
+ let RepoBuilder{ repo, .. } = self;
+ Repository(repo)
+ }
+}
+
+impl Repository {
+ pub fn root(&self) -> &Path {
+ self.0.workdir().unwrap()
+ }
+
+ pub fn url(&self) -> Url {
+ path2url(self.0.workdir().unwrap().to_path_buf())
+ }
+}
+
+pub fn new<F>(name: &str, callback: F) -> Result<Project, ProcessError>
+ where F: FnOnce(ProjectBuilder) -> ProjectBuilder
+{
+ let mut git_project = project(name);
+ git_project = callback(git_project);
+ let git_project = git_project.build();
+
+ let repo = t!(git2::Repository::init(&git_project.root()));
+ let mut cfg = t!(repo.config());
+ t!(cfg.set_str("user.email", "foo@bar.com"));
+ t!(cfg.set_str("user.name", "Foo Bar"));
+ drop(cfg);
+ add(&repo);
+ commit(&repo);
+ Ok(git_project)
+}
+
+pub fn add(repo: &git2::Repository) {
+ // FIXME(libgit2/libgit2#2514): apparently add_all will add all submodules
+ // as well, and then fail b/c they're a directory. As a stopgap, we just
+ // ignore all submodules.
+ let mut s = t!(repo.submodules());
+ for submodule in s.iter_mut() {
+ t!(submodule.add_to_index(false));
+ }
+ let mut index = t!(repo.index());
+ t!(index.add_all(["*"].iter(), git2::ADD_DEFAULT,
+ Some(&mut (|a, _b| {
+ if s.iter().any(|s| a.starts_with(s.path())) {1} else {0}
+ }))));
+ t!(index.write());
+}
+
+pub fn add_submodule<'a>(repo: &'a git2::Repository, url: &str,
+ path: &Path) -> git2::Submodule<'a>
+{
+ let path = path.to_str().unwrap().replace(r"\", "/");
+ let mut s = t!(repo.submodule(url, Path::new(&path), false));
+ let subrepo = t!(s.open());
+ t!(subrepo.remote_add_fetch("origin", "refs/heads/*:refs/heads/*"));
+ let mut origin = t!(subrepo.find_remote("origin"));
+ t!(origin.fetch(&[], None, None));
+ t!(subrepo.checkout_head(None));
+ t!(s.add_finalize());
+ return s;
+}
+
+pub fn commit(repo: &git2::Repository) -> git2::Oid {
+ let tree_id = t!(t!(repo.index()).write_tree());
+ let sig = t!(repo.signature());
+ let mut parents = Vec::new();
+ match repo.head().ok().map(|h| h.target().unwrap()) {
+ Some(parent) => parents.push(t!(repo.find_commit(parent))),
+ None => {}
+ }
+ let parents = parents.iter().collect::<Vec<_>>();
+ t!(repo.commit(Some("HEAD"), &sig, &sig, "test",
+ &t!(repo.find_tree(tree_id)),
+ &parents))
+}
+
+pub fn tag(repo: &git2::Repository, name: &str) {
+ let head = repo.head().unwrap().target().unwrap();
+ t!(repo.tag(name,
+ &t!(repo.find_object(head, None)),
+ &t!(repo.signature()),
+ "make a new tag",
+ false));
+}
--- /dev/null
+use std::env;
+use std::ffi::OsStr;
+use std::fmt;
+use std::fs;
+use std::io::prelude::*;
+use std::os;
+use std::path::{Path, PathBuf};
+use std::process::Output;
+use std::str;
+use std::usize;
+
+use serde_json::{self, Value};
+use url::Url;
+use hamcrest as ham;
+use cargo::util::ProcessBuilder;
+use cargo::util::{ProcessError};
+
+use support::paths::CargoPathExt;
+
+#[macro_export]
+macro_rules! t {
+ ($e:expr) => (match $e {
+ Ok(e) => e,
+ Err(e) => panic!("{} failed with {}", stringify!($e), e),
+ })
+}
+
+pub mod paths;
+pub mod git;
+pub mod registry;
+pub mod cross_compile;
+pub mod publish;
+
+/*
+ *
+ * ===== Builders =====
+ *
+ */
+
+#[derive(PartialEq,Clone)]
+struct FileBuilder {
+ path: PathBuf,
+ body: String
+}
+
+impl FileBuilder {
+ pub fn new(path: PathBuf, body: &str) -> FileBuilder {
+ FileBuilder { path: path, body: body.to_string() }
+ }
+
+ fn mk(&self) {
+ self.dirname().mkdir_p();
+
+ let mut file = fs::File::create(&self.path).unwrap_or_else(|e| {
+ panic!("could not create file {}: {}", self.path.display(), e)
+ });
+
+ t!(file.write_all(self.body.as_bytes()));
+ }
+
+ fn dirname(&self) -> &Path {
+ self.path.parent().unwrap()
+ }
+}
+
+#[derive(PartialEq,Clone)]
+struct SymlinkBuilder {
+ dst: PathBuf,
+ src: PathBuf,
+}
+
+impl SymlinkBuilder {
+ pub fn new(dst: PathBuf, src: PathBuf) -> SymlinkBuilder {
+ SymlinkBuilder { dst: dst, src: src }
+ }
+
+ #[cfg(unix)]
+ fn mk(&self) {
+ self.dirname().mkdir_p();
+ t!(os::unix::fs::symlink(&self.dst, &self.src));
+ }
+
+ #[cfg(windows)]
+ fn mk(&self) {
+ self.dirname().mkdir_p();
+ t!(os::windows::fs::symlink_file(&self.dst, &self.src));
+ }
+
+ fn dirname(&self) -> &Path {
+ self.src.parent().unwrap()
+ }
+}
+
+#[derive(PartialEq,Clone)]
+pub struct Project{
+ root: PathBuf,
+}
+
+#[must_use]
+#[derive(PartialEq,Clone)]
+pub struct ProjectBuilder {
+ name: String,
+ root: Project,
+ files: Vec<FileBuilder>,
+ symlinks: Vec<SymlinkBuilder>,
+}
+
+impl ProjectBuilder {
+ pub fn root(&self) -> PathBuf {
+ self.root.root()
+ }
+
+ pub fn build_dir(&self) -> PathBuf {
+ self.root.build_dir()
+ }
+
+ pub fn target_debug_dir(&self) -> PathBuf {
+ self.root.target_debug_dir()
+ }
+
+ pub fn new(name: &str, root: PathBuf) -> ProjectBuilder {
+ ProjectBuilder {
+ name: name.to_string(),
+ root: Project{ root },
+ files: vec![],
+ symlinks: vec![],
+ }
+ }
+
+ pub fn file<B: AsRef<Path>>(mut self, path: B,
+ body: &str) -> Self {
+ self._file(path.as_ref(), body);
+ self
+ }
+
+ fn _file(&mut self, path: &Path, body: &str) {
+ self.files.push(FileBuilder::new(self.root.root.join(path), body));
+ }
+
+ pub fn symlink<T: AsRef<Path>>(mut self, dst: T,
+ src: T) -> Self {
+ self.symlinks.push(SymlinkBuilder::new(self.root.root.join(dst),
+ self.root.root.join(src)));
+ self
+ }
+
+ pub fn build(self) -> Project {
+ // First, clean the directory if it already exists
+ self.rm_root();
+
+ // Create the empty directory
+ self.root.root.mkdir_p();
+
+ for file in self.files.iter() {
+ file.mk();
+ }
+
+ for symlink in self.symlinks.iter() {
+ symlink.mk();
+ }
+
+ let ProjectBuilder{ name: _, root, files: _, symlinks: _, .. } = self;
+ root
+ }
+
+ fn rm_root(&self) {
+ self.root.root.rm_rf()
+ }
+}
+
+impl Project {
+ pub fn root(&self) -> PathBuf {
+ self.root.clone()
+ }
+
+ pub fn build_dir(&self) -> PathBuf {
+ self.root.join("target")
+ }
+
+ pub fn target_debug_dir(&self) -> PathBuf {
+ self.build_dir().join("debug")
+ }
+
+ pub fn url(&self) -> Url { path2url(self.root()) }
+
+ pub fn example_lib(&self, name: &str, kind: &str) -> PathBuf {
+ let prefix = Project::get_lib_prefix(kind);
+
+ let extension = Project::get_lib_extension(kind);
+
+ let lib_file_name = format!("{}{}.{}",
+ prefix,
+ name,
+ extension);
+
+ self.target_debug_dir()
+ .join("examples")
+ .join(&lib_file_name)
+ }
+
+ pub fn bin(&self, b: &str) -> PathBuf {
+ self.build_dir().join("debug").join(&format!("{}{}", b,
+ env::consts::EXE_SUFFIX))
+ }
+
+ pub fn release_bin(&self, b: &str) -> PathBuf {
+ self.build_dir().join("release").join(&format!("{}{}", b,
+ env::consts::EXE_SUFFIX))
+ }
+
+ pub fn target_bin(&self, target: &str, b: &str) -> PathBuf {
+ self.build_dir().join(target).join("debug")
+ .join(&format!("{}{}", b, env::consts::EXE_SUFFIX))
+ }
+
+ pub fn change_file(&self, path: &str, body: &str) {
+ FileBuilder::new(self.root.join(path), body).mk()
+ }
+
+ pub fn process<T: AsRef<OsStr>>(&self, program: T) -> ProcessBuilder {
+ let mut p = ::process(program);
+ p.cwd(self.root());
+ return p
+ }
+
+ pub fn cargo(&self, cmd: &str) -> ProcessBuilder {
+ let mut p = self.process(&cargo_exe());
+ p.arg(cmd);
+ return p;
+ }
+
+ pub fn read_lockfile(&self) -> String {
+ let mut buffer = String::new();
+ fs::File::open(self.root().join("Cargo.lock")).unwrap()
+ .read_to_string(&mut buffer).unwrap();
+ buffer
+ }
+
+ fn get_lib_prefix(kind: &str) -> &str {
+ match kind {
+ "lib" | "rlib" => "lib",
+ "staticlib" | "dylib" | "proc-macro" => {
+ if cfg!(windows) {
+ ""
+ } else {
+ "lib"
+ }
+ }
+ _ => unreachable!()
+ }
+ }
+
+ fn get_lib_extension(kind: &str) -> &str {
+ match kind {
+ "lib" | "rlib" => "rlib",
+ "staticlib" => {
+ if cfg!(windows) {
+ "lib"
+ } else {
+ "a"
+ }
+ }
+ "dylib" | "proc-macro" => {
+ if cfg!(windows) {
+ "dll"
+ } else if cfg!(target_os="macos") {
+ "dylib"
+ } else {
+ "so"
+ }
+ }
+ _ => unreachable!()
+ }
+ }
+}
+
+// Generates a project layout
+pub fn project(name: &str) -> ProjectBuilder {
+ ProjectBuilder::new(name, paths::root().join(name))
+}
+
+// Generates a project layout inside our fake home dir
+pub fn project_in_home(name: &str) -> ProjectBuilder {
+ ProjectBuilder::new(name, paths::home().join(name))
+}
+
+// === Helpers ===
+
+pub fn main_file(println: &str, deps: &[&str]) -> String {
+ let mut buf = String::new();
+
+ for dep in deps.iter() {
+ buf.push_str(&format!("extern crate {};\n", dep));
+ }
+
+ buf.push_str("fn main() { println!(");
+ buf.push_str(&println);
+ buf.push_str("); }\n");
+
+ buf.to_string()
+}
+
+trait ErrMsg<T> {
+ fn with_err_msg(self, val: String) -> Result<T, String>;
+}
+
+impl<T, E: fmt::Display> ErrMsg<T> for Result<T, E> {
+ fn with_err_msg(self, val: String) -> Result<T, String> {
+ match self {
+ Ok(val) => Ok(val),
+ Err(err) => Err(format!("{}; original={}", val, err))
+ }
+ }
+}
+
+// Path to cargo executables
+pub fn cargo_dir() -> PathBuf {
+ env::var_os("CARGO_BIN_PATH").map(PathBuf::from).or_else(|| {
+ env::current_exe().ok().map(|mut path| {
+ path.pop();
+ if path.ends_with("deps") {
+ path.pop();
+ }
+ path
+ })
+ }).unwrap_or_else(|| {
+ panic!("CARGO_BIN_PATH wasn't set. Cannot continue running test")
+ })
+}
+
+pub fn cargo_exe() -> PathBuf {
+ cargo_dir().join(format!("cargo{}", env::consts::EXE_SUFFIX))
+}
+
+/// Returns an absolute path in the filesystem that `path` points to. The
+/// returned path does not contain any symlinks in its hierarchy.
+/*
+ *
+ * ===== Matchers =====
+ *
+ */
+
+#[derive(Clone)]
+pub struct Execs {
+ expect_stdout: Option<String>,
+ expect_stdin: Option<String>,
+ expect_stderr: Option<String>,
+ expect_exit_code: Option<i32>,
+ expect_stdout_contains: Vec<String>,
+ expect_stderr_contains: Vec<String>,
+ expect_either_contains: Vec<String>,
+ expect_stdout_contains_n: Vec<(String, usize)>,
+ expect_stdout_not_contains: Vec<String>,
+ expect_stderr_not_contains: Vec<String>,
+ expect_neither_contains: Vec<String>,
+ expect_json: Option<Vec<Value>>,
+}
+
+impl Execs {
+ pub fn with_stdout<S: ToString>(mut self, expected: S) -> Execs {
+ self.expect_stdout = Some(expected.to_string());
+ self
+ }
+
+ pub fn with_stderr<S: ToString>(mut self, expected: S) -> Execs {
+ self._with_stderr(&expected);
+ self
+ }
+
+ fn _with_stderr(&mut self, expected: &ToString) {
+ self.expect_stderr = Some(expected.to_string());
+ }
+
+ pub fn with_status(mut self, expected: i32) -> Execs {
+ self.expect_exit_code = Some(expected);
+ self
+ }
+
+ pub fn with_stdout_contains<S: ToString>(mut self, expected: S) -> Execs {
+ self.expect_stdout_contains.push(expected.to_string());
+ self
+ }
+
+ pub fn with_stderr_contains<S: ToString>(mut self, expected: S) -> Execs {
+ self.expect_stderr_contains.push(expected.to_string());
+ self
+ }
+
+ pub fn with_either_contains<S: ToString>(mut self, expected: S) -> Execs {
+ self.expect_either_contains.push(expected.to_string());
+ self
+ }
+
+ pub fn with_stdout_contains_n<S: ToString>(mut self, expected: S, number: usize) -> Execs {
+ self.expect_stdout_contains_n.push((expected.to_string(), number));
+ self
+ }
+
+ pub fn with_stdout_does_not_contain<S: ToString>(mut self, expected: S) -> Execs {
+ self.expect_stdout_not_contains.push(expected.to_string());
+ self
+ }
+
+ pub fn with_stderr_does_not_contain<S: ToString>(mut self, expected: S) -> Execs {
+ self.expect_stderr_not_contains.push(expected.to_string());
+ self
+ }
+
+ pub fn with_neither_contains<S: ToString>(mut self, expected: S) -> Execs {
+ self.expect_neither_contains.push(expected.to_string());
+ self
+ }
+
+ pub fn with_json(mut self, expected: &str) -> Execs {
+ self.expect_json = Some(expected.split("\n\n").map(|obj| {
+ obj.parse().unwrap()
+ }).collect());
+ self
+ }
+
+ fn match_output(&self, actual: &Output) -> ham::MatchResult {
+ self.match_status(actual)
+ .and(self.match_stdout(actual))
+ .and(self.match_stderr(actual))
+ }
+
+ fn match_status(&self, actual: &Output) -> ham::MatchResult {
+ match self.expect_exit_code {
+ None => ham::success(),
+ Some(code) => {
+ ham::expect(
+ actual.status.code() == Some(code),
+ format!("exited with {}\n--- stdout\n{}\n--- stderr\n{}",
+ actual.status,
+ String::from_utf8_lossy(&actual.stdout),
+ String::from_utf8_lossy(&actual.stderr)))
+ }
+ }
+ }
+
+ fn match_stdout(&self, actual: &Output) -> ham::MatchResult {
+ self.match_std(self.expect_stdout.as_ref(), &actual.stdout,
+ "stdout", &actual.stderr, MatchKind::Exact)?;
+ for expect in self.expect_stdout_contains.iter() {
+ self.match_std(Some(expect), &actual.stdout, "stdout",
+ &actual.stderr, MatchKind::Partial)?;
+ }
+ for expect in self.expect_stderr_contains.iter() {
+ self.match_std(Some(expect), &actual.stderr, "stderr",
+ &actual.stdout, MatchKind::Partial)?;
+ }
+ for &(ref expect, number) in self.expect_stdout_contains_n.iter() {
+ self.match_std(Some(&expect), &actual.stdout, "stdout",
+ &actual.stderr, MatchKind::PartialN(number))?;
+ }
+ for expect in self.expect_stdout_not_contains.iter() {
+ self.match_std(Some(expect), &actual.stdout, "stdout",
+ &actual.stderr, MatchKind::NotPresent)?;
+ }
+ for expect in self.expect_stderr_not_contains.iter() {
+ self.match_std(Some(expect), &actual.stderr, "stderr",
+ &actual.stdout, MatchKind::NotPresent)?;
+ }
+ for expect in self.expect_neither_contains.iter() {
+ self.match_std(Some(expect), &actual.stdout, "stdout",
+ &actual.stdout, MatchKind::NotPresent)?;
+
+ self.match_std(Some(expect), &actual.stderr, "stderr",
+ &actual.stderr, MatchKind::NotPresent)?;
+ }
+
+ for expect in self.expect_either_contains.iter() {
+ let match_std = self.match_std(Some(expect), &actual.stdout, "stdout",
+ &actual.stdout, MatchKind::Partial);
+ let match_err = self.match_std(Some(expect), &actual.stderr, "stderr",
+ &actual.stderr, MatchKind::Partial);
+
+ if let (Err(_), Err(_)) = (match_std, match_err) {
+ Err(format!("expected to find:\n\
+ {}\n\n\
+ did not find in either output.", expect))?;
+ }
+ }
+
+ if let Some(ref objects) = self.expect_json {
+ let stdout = str::from_utf8(&actual.stdout)
+ .map_err(|_| "stdout was not utf8 encoded".to_owned())?;
+ let lines = stdout.lines().collect::<Vec<_>>();
+ if lines.len() != objects.len() {
+ return Err(format!("expected {} json lines, got {}, stdout:\n{}",
+ objects.len(), lines.len(), stdout));
+ }
+ for (obj, line) in objects.iter().zip(lines) {
+ self.match_json(obj, line)?;
+ }
+ }
+ Ok(())
+ }
+
+ fn match_stderr(&self, actual: &Output) -> ham::MatchResult {
+ self.match_std(self.expect_stderr.as_ref(), &actual.stderr,
+ "stderr", &actual.stdout, MatchKind::Exact)
+ }
+
+ fn match_std(&self, expected: Option<&String>, actual: &[u8],
+ description: &str, extra: &[u8],
+ kind: MatchKind) -> ham::MatchResult {
+ let out = match expected {
+ Some(out) => out,
+ None => return ham::success(),
+ };
+ let actual = match str::from_utf8(actual) {
+ Err(..) => return Err(format!("{} was not utf8 encoded",
+ description)),
+ Ok(actual) => actual,
+ };
+ // Let's not deal with \r\n vs \n on windows...
+ let actual = actual.replace("\r", "");
+ let actual = actual.replace("\t", "<tab>");
+
+ match kind {
+ MatchKind::Exact => {
+ let a = actual.lines();
+ let e = out.lines();
+
+ let diffs = self.diff_lines(a, e, false);
+ ham::expect(diffs.is_empty(),
+ format!("differences:\n\
+ {}\n\n\
+ other output:\n\
+ `{}`", diffs.join("\n"),
+ String::from_utf8_lossy(extra)))
+ }
+ MatchKind::Partial => {
+ let mut a = actual.lines();
+ let e = out.lines();
+
+ let mut diffs = self.diff_lines(a.clone(), e.clone(), true);
+ while let Some(..) = a.next() {
+ let a = self.diff_lines(a.clone(), e.clone(), true);
+ if a.len() < diffs.len() {
+ diffs = a;
+ }
+ }
+ ham::expect(diffs.is_empty(),
+ format!("expected to find:\n\
+ {}\n\n\
+ did not find in output:\n\
+ {}", out,
+ actual))
+ }
+ MatchKind::PartialN(number) => {
+ let mut a = actual.lines();
+ let e = out.lines();
+
+ let mut matches = 0;
+
+ while let Some(..) = {
+ if self.diff_lines(a.clone(), e.clone(), true).is_empty() {
+ matches += 1;
+ }
+ a.next()
+ } {}
+
+ ham::expect(matches == number,
+ format!("expected to find {} occurrences:\n\
+ {}\n\n\
+ did not find in output:\n\
+ {}", number, out,
+ actual))
+ }
+ MatchKind::NotPresent => {
+ ham::expect(!actual.contains(out),
+ format!("expected not to find:\n\
+ {}\n\n\
+ but found in output:\n\
+ {}", out,
+ actual))
+ }
+ }
+ }
+
+ fn match_json(&self, expected: &Value, line: &str) -> ham::MatchResult {
+ let actual = match line.parse() {
+ Err(e) => return Err(format!("invalid json, {}:\n`{}`", e, line)),
+ Ok(actual) => actual,
+ };
+
+ match find_mismatch(expected, &actual) {
+ Some((expected_part, actual_part)) => Err(format!(
+ "JSON mismatch\nExpected:\n{}\nWas:\n{}\nExpected part:\n{}\nActual part:\n{}\n",
+ serde_json::to_string_pretty(expected).unwrap(),
+ serde_json::to_string_pretty(&actual).unwrap(),
+ serde_json::to_string_pretty(expected_part).unwrap(),
+ serde_json::to_string_pretty(actual_part).unwrap(),
+ )),
+ None => Ok(()),
+ }
+ }
+
+ fn diff_lines<'a>(&self, actual: str::Lines<'a>, expected: str::Lines<'a>,
+ partial: bool) -> Vec<String> {
+ let actual = actual.take(if partial {
+ expected.clone().count()
+ } else {
+ usize::MAX
+ });
+ zip_all(actual, expected).enumerate().filter_map(|(i, (a,e))| {
+ match (a, e) {
+ (Some(a), Some(e)) => {
+ if lines_match(&e, &a) {
+ None
+ } else {
+ Some(format!("{:3} - |{}|\n + |{}|\n", i, e, a))
+ }
+ },
+ (Some(a), None) => {
+ Some(format!("{:3} -\n + |{}|\n", i, a))
+ },
+ (None, Some(e)) => {
+ Some(format!("{:3} - |{}|\n +\n", i, e))
+ },
+ (None, None) => panic!("Cannot get here")
+ }
+ }).collect()
+ }
+}
+
+#[derive(Debug, PartialEq, Eq, Clone, Copy)]
+enum MatchKind {
+ Exact,
+ Partial,
+ PartialN(usize),
+ NotPresent,
+}
+
+pub fn lines_match(expected: &str, mut actual: &str) -> bool {
+ let expected = substitute_macros(expected);
+ for (i, part) in expected.split("[..]").enumerate() {
+ match actual.find(part) {
+ Some(j) => {
+ if i == 0 && j != 0 {
+ return false
+ }
+ actual = &actual[j + part.len()..];
+ }
+ None => {
+ return false
+ }
+ }
+ }
+ actual.is_empty() || expected.ends_with("[..]")
+}
+
+#[test]
+fn lines_match_works() {
+ assert!(lines_match("a b", "a b"));
+ assert!(lines_match("a[..]b", "a b"));
+ assert!(lines_match("a[..]", "a b"));
+ assert!(lines_match("[..]", "a b"));
+ assert!(lines_match("[..]b", "a b"));
+
+ assert!(!lines_match("[..]b", "c"));
+ assert!(!lines_match("b", "c"));
+ assert!(!lines_match("b", "cb"));
+}
+
+// Compares JSON object for approximate equality.
+// You can use `[..]` wildcard in strings (useful for OS dependent things such
+// as paths). You can use a `"{...}"` string literal as a wildcard for
+// arbitrary nested JSON (useful for parts of object emitted by other programs
+// (e.g. rustc) rather than Cargo itself). Arrays are sorted before comparison.
+fn find_mismatch<'a>(expected: &'a Value, actual: &'a Value)
+ -> Option<(&'a Value, &'a Value)> {
+ use serde_json::Value::*;
+ match (expected, actual) {
+ (&Number(ref l), &Number(ref r)) if l == r => None,
+ (&Bool(l), &Bool(r)) if l == r => None,
+ (&String(ref l), &String(ref r)) if lines_match(l, r) => None,
+ (&Array(ref l), &Array(ref r)) => {
+ if l.len() != r.len() {
+ return Some((expected, actual));
+ }
+
+ let mut l = l.iter().collect::<Vec<_>>();
+ let mut r = r.iter().collect::<Vec<_>>();
+
+ l.retain(|l| {
+ match r.iter().position(|r| find_mismatch(l, r).is_none()) {
+ Some(i) => {
+ r.remove(i);
+ false
+ }
+ None => true
+ }
+ });
+
+ if l.len() > 0 {
+ assert!(r.len() > 0);
+ Some((&l[0], &r[0]))
+ } else {
+ assert!(r.len() == 0);
+ None
+ }
+ }
+ (&Object(ref l), &Object(ref r)) => {
+ let same_keys = l.len() == r.len() && l.keys().all(|k| r.contains_key(k));
+ if !same_keys {
+ return Some((expected, actual));
+ }
+
+ l.values().zip(r.values())
+ .filter_map(|(l, r)| find_mismatch(l, r))
+ .nth(0)
+ }
+ (&Null, &Null) => None,
+ // magic string literal "{...}" acts as wildcard for any sub-JSON
+ (&String(ref l), _) if l == "{...}" => None,
+ _ => Some((expected, actual)),
+ }
+
+}
+
+struct ZipAll<I1: Iterator, I2: Iterator> {
+ first: I1,
+ second: I2,
+}
+
+impl<T, I1: Iterator<Item=T>, I2: Iterator<Item=T>> Iterator for ZipAll<I1, I2> {
+ type Item = (Option<T>, Option<T>);
+ fn next(&mut self) -> Option<(Option<T>, Option<T>)> {
+ let first = self.first.next();
+ let second = self.second.next();
+
+ match (first, second) {
+ (None, None) => None,
+ (a, b) => Some((a, b))
+ }
+ }
+}
+
+fn zip_all<T, I1: Iterator<Item=T>, I2: Iterator<Item=T>>(a: I1, b: I2) -> ZipAll<I1, I2> {
+ ZipAll {
+ first: a,
+ second: b,
+ }
+}
+
+impl fmt::Display for Execs {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "execs")
+ }
+}
+
+impl ham::Matcher<ProcessBuilder> for Execs {
+ fn matches(&self, mut process: ProcessBuilder) -> ham::MatchResult {
+ self.matches(&mut process)
+ }
+}
+
+impl<'a> ham::Matcher<&'a mut ProcessBuilder> for Execs {
+ fn matches(&self, process: &'a mut ProcessBuilder) -> ham::MatchResult {
+ println!("running {}", process);
+ let res = process.exec_with_output();
+
+ match res {
+ Ok(out) => self.match_output(&out),
+ Err(e) => {
+ let err = e.downcast_ref::<ProcessError>();
+ if let Some(&ProcessError { output: Some(ref out), .. }) = err {
+ return self.match_output(out)
+ }
+ let mut s = format!("could not exec process {}: {}", process, e);
+ for cause in e.causes() {
+ s.push_str(&format!("\ncaused by: {}", cause));
+ }
+ Err(s)
+ }
+ }
+ }
+}
+
+impl ham::Matcher<Output> for Execs {
+ fn matches(&self, output: Output) -> ham::MatchResult {
+ self.match_output(&output)
+ }
+}
+
+pub fn execs() -> Execs {
+ Execs {
+ expect_stdout: None,
+ expect_stderr: None,
+ expect_stdin: None,
+ expect_exit_code: None,
+ expect_stdout_contains: Vec::new(),
+ expect_stderr_contains: Vec::new(),
+ expect_either_contains: Vec::new(),
+ expect_stdout_contains_n: Vec::new(),
+ expect_stdout_not_contains: Vec::new(),
+ expect_stderr_not_contains: Vec::new(),
+ expect_neither_contains: Vec::new(),
+ expect_json: None,
+ }
+}
+
+#[derive(Clone)]
+pub struct ShellWrites {
+ expected: String
+}
+
+impl fmt::Display for ShellWrites {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "`{}` written to the shell", self.expected)
+ }
+}
+
+impl<'a> ham::Matcher<&'a [u8]> for ShellWrites {
+ fn matches(&self, actual: &[u8])
+ -> ham::MatchResult
+ {
+ let actual = String::from_utf8_lossy(actual);
+ let actual = actual.to_string();
+ ham::expect(actual == self.expected, actual)
+ }
+}
+
+pub fn shell_writes<T: fmt::Display>(string: T) -> ShellWrites {
+ ShellWrites { expected: string.to_string() }
+}
+
+pub trait Tap {
+ fn tap<F: FnOnce(&mut Self)>(self, callback: F) -> Self;
+}
+
+impl<T> Tap for T {
+ fn tap<F: FnOnce(&mut Self)>(mut self, callback: F) -> T {
+ callback(&mut self);
+ self
+ }
+}
+
+pub fn basic_bin_manifest(name: &str) -> String {
+ format!(r#"
+ [package]
+
+ name = "{}"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+
+ [[bin]]
+
+ name = "{}"
+ "#, name, name)
+}
+
+pub fn basic_lib_manifest(name: &str) -> String {
+ format!(r#"
+ [package]
+
+ name = "{}"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+
+ [lib]
+
+ name = "{}"
+ "#, name, name)
+}
+
+pub fn path2url(p: PathBuf) -> Url {
+ Url::from_file_path(&*p).ok().unwrap()
+}
+
+fn substitute_macros(input: &str) -> String {
+ let macros = [
+ ("[RUNNING]", " Running"),
+ ("[COMPILING]", " Compiling"),
+ ("[CREATED]", " Created"),
+ ("[FINISHED]", " Finished"),
+ ("[ERROR]", "error:"),
+ ("[WARNING]", "warning:"),
+ ("[DOCUMENTING]", " Documenting"),
+ ("[FRESH]", " Fresh"),
+ ("[UPDATING]", " Updating"),
+ ("[ADDING]", " Adding"),
+ ("[REMOVING]", " Removing"),
+ ("[DOCTEST]", " Doc-tests"),
+ ("[PACKAGING]", " Packaging"),
+ ("[DOWNLOADING]", " Downloading"),
+ ("[UPLOADING]", " Uploading"),
+ ("[VERIFYING]", " Verifying"),
+ ("[ARCHIVING]", " Archiving"),
+ ("[INSTALLING]", " Installing"),
+ ("[REPLACING]", " Replacing"),
+ ("[UNPACKING]", " Unpacking"),
+ ("[SUMMARY]", " Summary"),
+ ("[EXE]", if cfg!(windows) {".exe"} else {""}),
+ ("[/]", if cfg!(windows) {"\\"} else {"/"}),
+ ];
+ let mut result = input.to_owned();
+ for &(pat, subst) in macros.iter() {
+ result = result.replace(pat, subst)
+ }
+ return result;
+}
--- /dev/null
+use std::env;
+use std::cell::Cell;
+use std::fs;
+use std::io::{self, ErrorKind};
+use std::path::{Path, PathBuf};
+use std::sync::{Once, ONCE_INIT};
+use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
+
+use filetime::{self, FileTime};
+
+static CARGO_INTEGRATION_TEST_DIR : &'static str = "cit";
+static NEXT_ID: AtomicUsize = ATOMIC_USIZE_INIT;
+
+thread_local!(static TASK_ID: usize = NEXT_ID.fetch_add(1, Ordering::SeqCst));
+
+fn init() {
+ static GLOBAL_INIT: Once = ONCE_INIT;
+ thread_local!(static LOCAL_INIT: Cell<bool> = Cell::new(false));
+ GLOBAL_INIT.call_once(|| {
+ global_root().mkdir_p();
+ });
+ LOCAL_INIT.with(|i| {
+ if i.get() {
+ return
+ }
+ i.set(true);
+ root().rm_rf();
+ home().mkdir_p();
+ })
+}
+
+fn global_root() -> PathBuf {
+ let mut path = t!(env::current_exe());
+ path.pop(); // chop off exe name
+ path.pop(); // chop off 'debug'
+
+ // If `cargo test` is run manually then our path looks like
+ // `target/debug/foo`, in which case our `path` is already pointing at
+ // `target`. If, however, `cargo test --target $target` is used then the
+ // output is `target/$target/debug/foo`, so our path is pointing at
+ // `target/$target`. Here we conditionally pop the `$target` name.
+ if path.file_name().and_then(|s| s.to_str()) != Some("target") {
+ path.pop();
+ }
+
+ path.join(CARGO_INTEGRATION_TEST_DIR)
+}
+
+pub fn root() -> PathBuf {
+ init();
+ global_root().join(&TASK_ID.with(|my_id| format!("t{}", my_id)))
+}
+
+pub fn home() -> PathBuf {
+ root().join("home")
+}
+
+pub trait CargoPathExt {
+ fn rm_rf(&self);
+ fn mkdir_p(&self);
+
+ fn move_into_the_past(&self) {
+ self.move_in_time(|sec, nsec| (sec - 3600, nsec))
+ }
+
+ fn move_into_the_future(&self) {
+ self.move_in_time(|sec, nsec| (sec + 3600, nsec))
+ }
+
+ fn move_in_time<F>(&self, F)
+ where F: Fn(u64, u32) -> (u64, u32);
+}
+
+impl CargoPathExt for Path {
+ /* Technically there is a potential race condition, but we don't
+ * care all that much for our tests
+ */
+ fn rm_rf(&self) {
+ if !self.exists() {
+ return
+ }
+
+ for file in t!(fs::read_dir(self)) {
+ let file = t!(file);
+ if file.file_type().map(|m| m.is_dir()).unwrap_or(false) {
+ file.path().rm_rf();
+ } else {
+ // On windows we can't remove a readonly file, and git will
+ // often clone files as readonly. As a result, we have some
+ // special logic to remove readonly files on windows.
+ do_op(&file.path(), "remove file", |p| fs::remove_file(p));
+ }
+ }
+ do_op(self, "remove dir", |p| fs::remove_dir(p));
+ }
+
+ fn mkdir_p(&self) {
+ fs::create_dir_all(self).unwrap_or_else(|e| {
+ panic!("failed to mkdir_p {}: {}", self.display(), e)
+ })
+ }
+
+ fn move_in_time<F>(&self, travel_amount: F)
+ where F: Fn(u64, u32) -> ((u64, u32)),
+ {
+ if self.is_file() {
+ time_travel(self, &travel_amount);
+ } else {
+ recurse(self, &self.join("target"), &travel_amount);
+ }
+
+ fn recurse<F>(p: &Path, bad: &Path, travel_amount: &F)
+ where F: Fn(u64, u32) -> ((u64, u32)),
+ {
+ if p.is_file() {
+ time_travel(p, travel_amount)
+ } else if !p.starts_with(bad) {
+ for f in t!(fs::read_dir(p)) {
+ let f = t!(f).path();
+ recurse(&f, bad, travel_amount);
+ }
+ }
+ }
+
+ fn time_travel<F>(path: &Path, travel_amount: &F)
+ where F: Fn(u64, u32) -> ((u64, u32)),
+ {
+ let stat = t!(path.metadata());
+
+ let mtime = FileTime::from_last_modification_time(&stat);
+
+ let (sec, nsec) = travel_amount(mtime.seconds_relative_to_1970(), mtime.nanoseconds());
+ let newtime = FileTime::from_seconds_since_1970(sec, nsec);
+
+ // Sadly change_file_times has a failure mode where a readonly file
+ // cannot have its times changed on windows.
+ do_op(path, "set file times",
+ |path| filetime::set_file_times(path, newtime, newtime));
+ }
+ }
+}
+
+fn do_op<F>(path: &Path, desc: &str, mut f: F)
+ where F: FnMut(&Path) -> io::Result<()>
+{
+ match f(path) {
+ Ok(()) => {}
+ Err(ref e) if cfg!(windows) &&
+ e.kind() == ErrorKind::PermissionDenied => {
+ let mut p = t!(path.metadata()).permissions();
+ p.set_readonly(false);
+ t!(fs::set_permissions(path, p));
+ f(path).unwrap_or_else(|e| {
+ panic!("failed to {} {}: {}", desc, path.display(), e);
+ })
+ }
+ Err(e) => {
+ panic!("failed to {} {}: {}", desc, path.display(), e);
+ }
+ }
+}
--- /dev/null
+use std::path::PathBuf;
+use std::io::prelude::*;
+use std::fs::{self, File};
+
+use support::paths;
+use support::git::{repo, Repository};
+
+use url::Url;
+
+pub fn setup() -> Repository {
+ let config = paths::root().join(".cargo/config");
+ t!(fs::create_dir_all(config.parent().unwrap()));
+ t!(t!(File::create(&config)).write_all(format!(r#"
+ [registry]
+ token = "api-token"
+
+ [registries.alternative]
+ index = "{registry}"
+ "#, registry = registry().to_string()).as_bytes()));
+
+ let credentials = paths::root().join("home/.cargo/credentials");
+ t!(fs::create_dir_all(credentials.parent().unwrap()));
+ t!(t!(File::create(&credentials)).write_all(br#"
+ [registries.alternative]
+ token = "api-token"
+ "#));
+
+ t!(fs::create_dir_all(&upload_path().join("api/v1/crates")));
+
+ repo(®istry_path())
+ .file("config.json", &format!(r#"{{
+ "dl": "{0}",
+ "api": "{0}"
+ }}"#, upload()))
+ .build()
+}
+
+fn registry_path() -> PathBuf { paths::root().join("registry") }
+pub fn registry() -> Url { Url::from_file_path(&*registry_path()).ok().unwrap() }
+pub fn upload_path() -> PathBuf { paths::root().join("upload") }
+fn upload() -> Url { Url::from_file_path(&*upload_path()).ok().unwrap() }
--- /dev/null
+use std::collections::HashMap;
+use std::fs::{self, File};
+use std::io::prelude::*;
+use std::path::{PathBuf, Path};
+
+use flate2::Compression;
+use flate2::write::GzEncoder;
+use git2;
+use hex;
+use tar::{Builder, Header};
+use url::Url;
+
+use support::paths;
+use support::git::repo;
+use cargo::util::Sha256;
+
+pub fn registry_path() -> PathBuf { paths::root().join("registry") }
+pub fn registry() -> Url { Url::from_file_path(&*registry_path()).ok().unwrap() }
+pub fn dl_path() -> PathBuf { paths::root().join("dl") }
+pub fn dl_url() -> Url { Url::from_file_path(&*dl_path()).ok().unwrap() }
+pub fn alt_registry_path() -> PathBuf { paths::root().join("alternative-registry") }
+pub fn alt_registry() -> Url { Url::from_file_path(&*alt_registry_path()).ok().unwrap() }
+pub fn alt_dl_path() -> PathBuf { paths::root().join("alt_dl") }
+pub fn alt_dl_url() -> String {
+ let base = Url::from_file_path(&*alt_dl_path()).ok().unwrap();
+ format!("{}/{{crate}}/{{version}}/{{crate}}-{{version}}.crate", base)
+}
+pub fn alt_api_path() -> PathBuf { paths::root().join("alt_api") }
+pub fn alt_api_url() -> Url { Url::from_file_path(&*alt_api_path()).ok().unwrap() }
+
+pub struct Package {
+ name: String,
+ vers: String,
+ deps: Vec<Dependency>,
+ files: Vec<(String, String)>,
+ extra_files: Vec<(String, String)>,
+ yanked: bool,
+ features: HashMap<String, Vec<String>>,
+ local: bool,
+ alternative: bool,
+}
+
+struct Dependency {
+ name: String,
+ vers: String,
+ kind: String,
+ target: Option<String>,
+ features: Vec<String>,
+ registry: Option<String>,
+}
+
+pub fn init() {
+ let config = paths::home().join(".cargo/config");
+ t!(fs::create_dir_all(config.parent().unwrap()));
+ if fs::metadata(&config).is_ok() {
+ return
+ }
+ t!(t!(File::create(&config)).write_all(format!(r#"
+ [registry]
+ token = "api-token"
+
+ [source.crates-io]
+ registry = 'https://wut'
+ replace-with = 'dummy-registry'
+
+ [source.dummy-registry]
+ registry = '{reg}'
+
+ [registries.alternative]
+ index = '{alt}'
+ "#, reg = registry(), alt = alt_registry()).as_bytes()));
+
+ // Init a new registry
+ let _ = repo(®istry_path())
+ .file("config.json", &format!(r#"
+ {{"dl":"{0}","api":"{0}"}}
+ "#, dl_url()))
+ .build();
+ fs::create_dir_all(dl_path().join("api/v1/crates")).unwrap();
+
+ // Init an alt registry
+ repo(&alt_registry_path())
+ .file("config.json", &format!(r#"
+ {{"dl":"{}","api":"{}"}}
+ "#, alt_dl_url(), alt_api_url()))
+ .build();
+ fs::create_dir_all(alt_api_path().join("api/v1/crates")).unwrap();
+}
+
+impl Package {
+ pub fn new(name: &str, vers: &str) -> Package {
+ init();
+ Package {
+ name: name.to_string(),
+ vers: vers.to_string(),
+ deps: Vec::new(),
+ files: Vec::new(),
+ extra_files: Vec::new(),
+ yanked: false,
+ features: HashMap::new(),
+ local: false,
+ alternative: false,
+ }
+ }
+
+ pub fn local(&mut self, local: bool) -> &mut Package {
+ self.local = local;
+ self
+ }
+
+ pub fn alternative(&mut self, alternative: bool) -> &mut Package {
+ self.alternative = alternative;
+ self
+ }
+
+ pub fn file(&mut self, name: &str, contents: &str) -> &mut Package {
+ self.files.push((name.to_string(), contents.to_string()));
+ self
+ }
+
+ pub fn extra_file(&mut self, name: &str, contents: &str) -> &mut Package {
+ self.extra_files.push((name.to_string(), contents.to_string()));
+ self
+ }
+
+ pub fn dep(&mut self, name: &str, vers: &str) -> &mut Package {
+ self.full_dep(name, vers, None, "normal", &[], None)
+ }
+
+ pub fn feature_dep(&mut self,
+ name: &str,
+ vers: &str,
+ features: &[&str]) -> &mut Package {
+ self.full_dep(name, vers, None, "normal", features, None)
+ }
+
+ pub fn target_dep(&mut self,
+ name: &str,
+ vers: &str,
+ target: &str) -> &mut Package {
+ self.full_dep(name, vers, Some(target), "normal", &[], None)
+ }
+
+ pub fn registry_dep(&mut self,
+ name: &str,
+ vers: &str,
+ registry: &str) -> &mut Package {
+ self.full_dep(name, vers, None, "normal", &[], Some(registry))
+ }
+
+ pub fn dev_dep(&mut self, name: &str, vers: &str) -> &mut Package {
+ self.full_dep(name, vers, None, "dev", &[], None)
+ }
+
+ fn full_dep(&mut self,
+ name: &str,
+ vers: &str,
+ target: Option<&str>,
+ kind: &str,
+ features: &[&str],
+ registry: Option<&str>) -> &mut Package {
+ self.deps.push(Dependency {
+ name: name.to_string(),
+ vers: vers.to_string(),
+ kind: kind.to_string(),
+ target: target.map(|s| s.to_string()),
+ features: features.iter().map(|s| s.to_string()).collect(),
+ registry: registry.map(|s| s.to_string()),
+ });
+ self
+ }
+
+ pub fn yanked(&mut self, yanked: bool) -> &mut Package {
+ self.yanked = yanked;
+ self
+ }
+
+ pub fn publish(&self) -> String {
+ self.make_archive();
+
+ // Figure out what we're going to write into the index
+ let deps = self.deps.iter().map(|dep| {
+ json!({
+ "name": dep.name,
+ "req": dep.vers,
+ "features": dep.features,
+ "default_features": true,
+ "target": dep.target,
+ "optional": false,
+ "kind": dep.kind,
+ "registry": dep.registry,
+ })
+ }).collect::<Vec<_>>();
+ let cksum = {
+ let mut c = Vec::new();
+ t!(t!(File::open(&self.archive_dst())).read_to_end(&mut c));
+ cksum(&c)
+ };
+ let line = json!({
+ "name": self.name,
+ "vers": self.vers,
+ "deps": deps,
+ "cksum": cksum,
+ "features": self.features,
+ "yanked": self.yanked,
+ }).to_string();
+
+ let file = match self.name.len() {
+ 1 => format!("1/{}", self.name),
+ 2 => format!("2/{}", self.name),
+ 3 => format!("3/{}/{}", &self.name[..1], self.name),
+ _ => format!("{}/{}/{}", &self.name[0..2], &self.name[2..4], self.name),
+ };
+
+ let registry_path = if self.alternative { alt_registry_path() } else { registry_path() };
+
+ // Write file/line in the index
+ let dst = if self.local {
+ registry_path.join("index").join(&file)
+ } else {
+ registry_path.join(&file)
+ };
+ let mut prev = String::new();
+ let _ = File::open(&dst).and_then(|mut f| f.read_to_string(&mut prev));
+ t!(fs::create_dir_all(dst.parent().unwrap()));
+ t!(t!(File::create(&dst))
+ .write_all((prev + &line[..] + "\n").as_bytes()));
+
+ // Add the new file to the index
+ if !self.local {
+ let repo = t!(git2::Repository::open(®istry_path));
+ let mut index = t!(repo.index());
+ t!(index.add_path(Path::new(&file)));
+ t!(index.write());
+ let id = t!(index.write_tree());
+
+ // Commit this change
+ let tree = t!(repo.find_tree(id));
+ let sig = t!(repo.signature());
+ let parent = t!(repo.refname_to_id("refs/heads/master"));
+ let parent = t!(repo.find_commit(parent));
+ t!(repo.commit(Some("HEAD"), &sig, &sig,
+ "Another commit", &tree,
+ &[&parent]));
+ }
+
+ return cksum
+ }
+
+ fn make_archive(&self) {
+ let mut manifest = format!(r#"
+ [package]
+ name = "{}"
+ version = "{}"
+ authors = []
+ "#, self.name, self.vers);
+ for dep in self.deps.iter() {
+ let target = match dep.target {
+ None => String::new(),
+ Some(ref s) => format!("target.'{}'.", s),
+ };
+ let kind = match &dep.kind[..] {
+ "build" => "build-",
+ "dev" => "dev-",
+ _ => ""
+ };
+ manifest.push_str(&format!(r#"
+ [{}{}dependencies.{}]
+ version = "{}"
+ "#, target, kind, dep.name, dep.vers));
+ }
+
+ let dst = self.archive_dst();
+ t!(fs::create_dir_all(dst.parent().unwrap()));
+ let f = t!(File::create(&dst));
+ let mut a =
+ Builder::new(GzEncoder::new(f, Compression::default()));
+ self.append(&mut a, "Cargo.toml", &manifest);
+ if self.files.is_empty() {
+ self.append(&mut a, "src/lib.rs", "");
+ } else {
+ for &(ref name, ref contents) in self.files.iter() {
+ self.append(&mut a, name, contents);
+ }
+ }
+ for &(ref name, ref contents) in self.extra_files.iter() {
+ self.append_extra(&mut a, name, contents);
+ }
+ }
+
+ fn append<W: Write>(&self, ar: &mut Builder<W>, file: &str, contents: &str) {
+ self.append_extra(ar,
+ &format!("{}-{}/{}", self.name, self.vers, file),
+ contents);
+ }
+
+ fn append_extra<W: Write>(&self, ar: &mut Builder<W>, path: &str, contents: &str) {
+ let mut header = Header::new_ustar();
+ header.set_size(contents.len() as u64);
+ t!(header.set_path(path));
+ header.set_cksum();
+ t!(ar.append(&header, contents.as_bytes()));
+ }
+
+ pub fn archive_dst(&self) -> PathBuf {
+ if self.local {
+ registry_path().join(format!("{}-{}.crate", self.name,
+ self.vers))
+ } else if self.alternative {
+ alt_dl_path()
+ .join(&self.name)
+ .join(&self.vers)
+ .join(&format!("{}-{}.crate", self.name, self.vers))
+ } else {
+ dl_path().join(&self.name).join(&self.vers).join("download")
+ }
+ }
+}
+
+pub fn cksum(s: &[u8]) -> String {
+ let mut sha = Sha256::new();
+ sha.update(s);
+ hex::encode(&sha.finish())
+}
--- /dev/null
+use std::str::FromStr;
+use std::fmt;
+
+use cargo::util::{Cfg, CfgExpr};
+use cargotest::rustc_host;
+use cargotest::support::registry::Package;
+use cargotest::support::{project, execs};
+use hamcrest::assert_that;
+
+macro_rules! c {
+ ($a:ident) => (
+ Cfg::Name(stringify!($a).to_string())
+ );
+ ($a:ident = $e:expr) => (
+ Cfg::KeyPair(stringify!($a).to_string(), $e.to_string())
+ );
+}
+
+macro_rules! e {
+ (any($($t:tt),*)) => (CfgExpr::Any(vec![$(e!($t)),*]));
+ (all($($t:tt),*)) => (CfgExpr::All(vec![$(e!($t)),*]));
+ (not($($t:tt)*)) => (CfgExpr::Not(Box::new(e!($($t)*))));
+ (($($t:tt)*)) => (e!($($t)*));
+ ($($t:tt)*) => (CfgExpr::Value(c!($($t)*)));
+}
+
+fn good<T>(s: &str, expected: T)
+ where T: FromStr + PartialEq + fmt::Debug,
+ T::Err: fmt::Display
+{
+ let c = match T::from_str(s) {
+ Ok(c) => c,
+ Err(e) => panic!("failed to parse `{}`: {}", s, e),
+ };
+ assert_eq!(c, expected);
+}
+
+fn bad<T>(s: &str, err: &str)
+ where T: FromStr + fmt::Display, T::Err: fmt::Display
+{
+ let e = match T::from_str(s) {
+ Ok(cfg) => panic!("expected `{}` to not parse but got {}", s, cfg),
+ Err(e) => e.to_string(),
+ };
+ assert!(e.contains(err), "when parsing `{}`,\n\"{}\" not contained \
+ inside: {}", s, err, e);
+}
+
+#[test]
+fn cfg_syntax() {
+ good("foo", c!(foo));
+ good("_bar", c!(_bar));
+ good(" foo", c!(foo));
+ good(" foo ", c!(foo));
+ good(" foo = \"bar\"", c!(foo = "bar"));
+ good("foo=\"\"", c!(foo = ""));
+ good(" foo=\"3\" ", c!(foo = "3"));
+ good("foo = \"3 e\"", c!(foo = "3 e"));
+}
+
+#[test]
+fn cfg_syntax_bad() {
+ bad::<Cfg>("", "found nothing");
+ bad::<Cfg>(" ", "found nothing");
+ bad::<Cfg>("\t", "unexpected character");
+ bad::<Cfg>("7", "unexpected character");
+ bad::<Cfg>("=", "expected identifier");
+ bad::<Cfg>(",", "expected identifier");
+ bad::<Cfg>("(", "expected identifier");
+ bad::<Cfg>("foo (", "malformed cfg value");
+ bad::<Cfg>("bar =", "expected a string");
+ bad::<Cfg>("bar = \"", "unterminated string");
+ bad::<Cfg>("foo, bar", "malformed cfg value");
+}
+
+#[test]
+fn cfg_expr() {
+ good("foo", e!(foo));
+ good("_bar", e!(_bar));
+ good(" foo", e!(foo));
+ good(" foo ", e!(foo));
+ good(" foo = \"bar\"", e!(foo = "bar"));
+ good("foo=\"\"", e!(foo = ""));
+ good(" foo=\"3\" ", e!(foo = "3"));
+ good("foo = \"3 e\"", e!(foo = "3 e"));
+
+ good("all()", e!(all()));
+ good("all(a)", e!(all(a)));
+ good("all(a, b)", e!(all(a, b)));
+ good("all(a, )", e!(all(a)));
+ good("not(a = \"b\")", e!(not(a = "b")));
+ good("not(all(a))", e!(not(all(a))));
+}
+
+#[test]
+fn cfg_expr_bad() {
+ bad::<CfgExpr>(" ", "found nothing");
+ bad::<CfgExpr>(" all", "expected `(`");
+ bad::<CfgExpr>("all(a", "expected `)`");
+ bad::<CfgExpr>("not", "expected `(`");
+ bad::<CfgExpr>("not(a", "expected `)`");
+ bad::<CfgExpr>("a = ", "expected a string");
+ bad::<CfgExpr>("all(not())", "expected identifier");
+ bad::<CfgExpr>("foo(a)", "consider using all() or any() explicitly");
+}
+
+#[test]
+fn cfg_matches() {
+ assert!(e!(foo).matches(&[c!(bar), c!(foo), c!(baz)]));
+ assert!(e!(any(foo)).matches(&[c!(bar), c!(foo), c!(baz)]));
+ assert!(e!(any(foo, bar)).matches(&[c!(bar)]));
+ assert!(e!(any(foo, bar)).matches(&[c!(foo)]));
+ assert!(e!(all(foo, bar)).matches(&[c!(foo), c!(bar)]));
+ assert!(e!(all(foo, bar)).matches(&[c!(foo), c!(bar)]));
+ assert!(e!(not(foo)).matches(&[c!(bar)]));
+ assert!(e!(not(foo)).matches(&[]));
+ assert!(e!(any((not(foo)), (all(foo, bar)))).matches(&[c!(bar)]));
+ assert!(e!(any((not(foo)), (all(foo, bar)))).matches(&[c!(foo), c!(bar)]));
+
+ assert!(!e!(foo).matches(&[]));
+ assert!(!e!(foo).matches(&[c!(bar)]));
+ assert!(!e!(foo).matches(&[c!(fo)]));
+ assert!(!e!(any(foo)).matches(&[]));
+ assert!(!e!(any(foo)).matches(&[c!(bar)]));
+ assert!(!e!(any(foo)).matches(&[c!(bar), c!(baz)]));
+ assert!(!e!(all(foo)).matches(&[c!(bar), c!(baz)]));
+ assert!(!e!(all(foo, bar)).matches(&[c!(bar)]));
+ assert!(!e!(all(foo, bar)).matches(&[c!(foo)]));
+ assert!(!e!(all(foo, bar)).matches(&[]));
+ assert!(!e!(not(bar)).matches(&[c!(bar)]));
+ assert!(!e!(not(bar)).matches(&[c!(baz), c!(bar)]));
+ assert!(!e!(any((not(foo)), (all(foo, bar)))).matches(&[c!(foo)]));
+}
+
+#[test]
+fn cfg_easy() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "a"
+ version = "0.0.1"
+ authors = []
+
+ [target.'cfg(unix)'.dependencies]
+ b = { path = 'b' }
+ [target."cfg(windows)".dependencies]
+ b = { path = 'b' }
+ "#)
+ .file("src/lib.rs", "extern crate b;")
+ .file("b/Cargo.toml", r#"
+ [package]
+ name = "b"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("b/src/lib.rs", "")
+ .build();
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(0));
+}
+
+#[test]
+fn dont_include() {
+ let other_family = if cfg!(unix) {"windows"} else {"unix"};
+ let p = project("foo")
+ .file("Cargo.toml", &format!(r#"
+ [package]
+ name = "a"
+ version = "0.0.1"
+ authors = []
+
+ [target.'cfg({})'.dependencies]
+ b = {{ path = 'b' }}
+ "#, other_family))
+ .file("src/lib.rs", "")
+ .file("b/Cargo.toml", r#"
+ [package]
+ name = "b"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("b/src/lib.rs", "")
+ .build();
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr("\
+[COMPILING] a v0.0.1 ([..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+}
+
+#[test]
+fn works_through_the_registry() {
+ Package::new("foo", "0.1.0").publish();
+ Package::new("bar", "0.1.0")
+ .target_dep("foo", "0.1.0", "cfg(unix)")
+ .target_dep("foo", "0.1.0", "cfg(windows)")
+ .publish();
+
+ let p = project("a")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "a"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ bar = "0.1.0"
+ "#)
+ .file("src/lib.rs", "#[allow(unused_extern_crates)] extern crate bar;")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr("\
+[UPDATING] registry [..]
+[DOWNLOADING] [..]
+[DOWNLOADING] [..]
+[COMPILING] foo v0.1.0
+[COMPILING] bar v0.1.0
+[COMPILING] a v0.0.1 ([..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+}
+
+#[test]
+fn ignore_version_from_other_platform() {
+ let this_family = if cfg!(unix) {"unix"} else {"windows"};
+ let other_family = if cfg!(unix) {"windows"} else {"unix"};
+ Package::new("foo", "0.1.0").publish();
+ Package::new("foo", "0.2.0").publish();
+
+ let p = project("a")
+ .file("Cargo.toml", &format!(r#"
+ [package]
+ name = "a"
+ version = "0.0.1"
+ authors = []
+
+ [target.'cfg({})'.dependencies]
+ foo = "0.1.0"
+
+ [target.'cfg({})'.dependencies]
+ foo = "0.2.0"
+ "#, this_family, other_family))
+ .file("src/lib.rs", "#[allow(unused_extern_crates)] extern crate foo;")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr("\
+[UPDATING] registry [..]
+[DOWNLOADING] [..]
+[COMPILING] foo v0.1.0
+[COMPILING] a v0.0.1 ([..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+}
+
+#[test]
+fn bad_target_spec() {
+ let p = project("a")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "a"
+ version = "0.0.1"
+ authors = []
+
+ [target.'cfg(4)'.dependencies]
+ bar = "0.1.0"
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101).with_stderr("\
+[ERROR] failed to parse manifest at `[..]`
+
+Caused by:
+ failed to parse `4` as a cfg expression
+
+Caused by:
+ unexpected character in cfg `4`, [..]
+"));
+}
+
+#[test]
+fn bad_target_spec2() {
+ let p = project("a")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "a"
+ version = "0.0.1"
+ authors = []
+
+ [target.'cfg(foo =)'.dependencies]
+ bar = "0.1.0"
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101).with_stderr("\
+[ERROR] failed to parse manifest at `[..]`
+
+Caused by:
+ failed to parse `foo =` as a cfg expression
+
+Caused by:
+ expected a string, found nothing
+"));
+}
+
+#[test]
+fn multiple_match_ok() {
+ let p = project("foo")
+ .file("Cargo.toml", &format!(r#"
+ [package]
+ name = "a"
+ version = "0.0.1"
+ authors = []
+
+ [target.'cfg(unix)'.dependencies]
+ b = {{ path = 'b' }}
+ [target.'cfg(target_family = "unix")'.dependencies]
+ b = {{ path = 'b' }}
+ [target."cfg(windows)".dependencies]
+ b = {{ path = 'b' }}
+ [target.'cfg(target_family = "windows")'.dependencies]
+ b = {{ path = 'b' }}
+ [target."cfg(any(windows, unix))".dependencies]
+ b = {{ path = 'b' }}
+
+ [target.{}.dependencies]
+ b = {{ path = 'b' }}
+ "#, rustc_host()))
+ .file("src/lib.rs", "extern crate b;")
+ .file("b/Cargo.toml", r#"
+ [package]
+ name = "b"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("b/src/lib.rs", "")
+ .build();
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(0));
+}
+
+#[test]
+fn any_ok() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "a"
+ version = "0.0.1"
+ authors = []
+
+ [target."cfg(any(windows, unix))".dependencies]
+ b = { path = 'b' }
+ "#)
+ .file("src/lib.rs", "extern crate b;")
+ .file("b/Cargo.toml", r#"
+ [package]
+ name = "b"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("b/src/lib.rs", "")
+ .build();
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(0));
+}
--- /dev/null
+echo "checking for lines over 100 characters..."
+find src tests -name '*.rs' | xargs grep '.\{101,\}' && exit 1
+echo "ok"
--- /dev/null
+use cargotest::is_nightly;
+use cargotest::support::{execs, project};
+use cargotest::support::registry::Package;
+use hamcrest::prelude::*;
+use cargotest::support::paths::CargoPathExt;
+use cargotest::install::exe;
+use glob::glob;
+
+const SIMPLE_MANIFEST: &str = r#"
+[package]
+name = "foo"
+version = "0.0.1"
+authors = []
+"#;
+
+#[test]
+fn check_success() {
+ let foo = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.bar]
+ path = "../bar"
+ "#)
+ .file("src/main.rs", r#"
+ extern crate bar;
+ fn main() {
+ ::bar::baz();
+ }
+ "#)
+ .build();
+ let _bar = project("bar")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("src/lib.rs", r#"
+ pub fn baz() {}
+ "#)
+ .build();
+
+ assert_that(foo.cargo("check"),
+ execs().with_status(0));
+}
+
+#[test]
+fn check_fail() {
+ let foo = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.bar]
+ path = "../bar"
+ "#)
+ .file("src/main.rs", r#"
+ extern crate bar;
+ fn main() {
+ ::bar::baz(42);
+ }
+ "#)
+ .build();
+ let _bar = project("bar")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("src/lib.rs", r#"
+ pub fn baz() {}
+ "#)
+ .build();
+
+ assert_that(foo.cargo("check"),
+ execs().with_status(101));
+}
+
+#[test]
+fn custom_derive() {
+ if !is_nightly() {
+ return
+ }
+ let foo = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.bar]
+ path = "../bar"
+ "#)
+ .file("src/main.rs", r#"
+#![feature(proc_macro)]
+
+#[macro_use]
+extern crate bar;
+
+trait B {
+ fn b(&self);
+}
+
+#[derive(B)]
+struct A;
+
+fn main() {
+ let a = A;
+ a.b();
+}
+"#)
+ .build();
+ let _bar = project("bar")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+ [lib]
+ proc-macro = true
+ "#)
+ .file("src/lib.rs", r#"
+#![feature(proc_macro, proc_macro_lib)]
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_derive(B)]
+pub fn derive(_input: TokenStream) -> TokenStream {
+ format!("impl B for A {{ fn b(&self) {{}} }}").parse().unwrap()
+}
+"#)
+ .build();
+
+ assert_that(foo.cargo("check"),
+ execs().with_status(0));
+}
+
+#[test]
+fn check_build() {
+ let foo = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.bar]
+ path = "../bar"
+ "#)
+ .file("src/main.rs", r#"
+ extern crate bar;
+ fn main() {
+ ::bar::baz();
+ }
+ "#)
+ .build();
+
+ let _bar = project("bar")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("src/lib.rs", r#"
+ pub fn baz() {}
+ "#)
+ .build();
+
+ assert_that(foo.cargo("check"),
+ execs().with_status(0));
+ assert_that(foo.cargo("build"),
+ execs().with_status(0));
+}
+
+#[test]
+fn build_check() {
+ let foo = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.bar]
+ path = "../bar"
+ "#)
+ .file("src/main.rs", r#"
+ extern crate bar;
+ fn main() {
+ ::bar::baz();
+ }
+ "#)
+ .build();
+
+ let _bar = project("bar")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("src/lib.rs", r#"
+ pub fn baz() {}
+ "#)
+ .build();
+
+ assert_that(foo.cargo("build"),
+ execs().with_status(0));
+ assert_that(foo.cargo("check"),
+ execs().with_status(0));
+}
+
+// Checks that where a project has both a lib and a bin, the lib is only checked
+// not built.
+#[test]
+fn issue_3418() {
+ let foo = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+
+ [dependencies]
+ "#)
+ .file("src/lib.rs", "")
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ assert_that(foo.cargo("check").arg("-v"),
+ execs().with_status(0)
+ .with_stderr_contains("[..] --emit=dep-info,metadata [..]"));
+}
+
+// Some weirdness that seems to be caused by a crate being built as well as
+// checked, but in this case with a proc macro too.
+#[test]
+fn issue_3419() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ rustc-serialize = "*"
+ "#)
+ .file("src/lib.rs", r#"
+ extern crate rustc_serialize;
+
+ use rustc_serialize::Decodable;
+
+ pub fn take<T: Decodable>() {}
+ "#)
+ .file("src/main.rs", r#"
+ extern crate rustc_serialize;
+
+ extern crate foo;
+
+ #[derive(RustcDecodable)]
+ pub struct Foo;
+
+ fn main() {
+ foo::take::<Foo>();
+ }
+ "#)
+ .build();
+
+ Package::new("rustc-serialize", "1.0.0")
+ .file("src/lib.rs",
+ r#"pub trait Decodable: Sized {
+ fn decode<D: Decoder>(d: &mut D) -> Result<Self, D::Error>;
+ }
+ pub trait Decoder {
+ type Error;
+ fn read_struct<T, F>(&mut self, s_name: &str, len: usize, f: F)
+ -> Result<T, Self::Error>
+ where F: FnOnce(&mut Self) -> Result<T, Self::Error>;
+ } "#).publish();
+
+ assert_that(p.cargo("check"),
+ execs().with_status(0));
+}
+
+// Check on a dylib should have a different metadata hash than build.
+#[test]
+fn dylib_check_preserves_build_cache() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+
+ [lib]
+ crate-type = ["dylib"]
+
+ [dependencies]
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0)
+ .with_stderr("\
+[..]Compiling foo v0.1.0 ([..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+
+ assert_that(p.cargo("check"),
+ execs().with_status(0));
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0)
+ .with_stderr("\
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+}
+
+// test `cargo rustc --profile check`
+#[test]
+fn rustc_check() {
+ let foo = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.bar]
+ path = "../bar"
+ "#)
+ .file("src/main.rs", r#"
+ extern crate bar;
+ fn main() {
+ ::bar::baz();
+ }
+ "#)
+ .build();
+ let _bar = project("bar")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("src/lib.rs", r#"
+ pub fn baz() {}
+ "#)
+ .build();
+
+ assert_that(foo.cargo("rustc")
+ .arg("--profile")
+ .arg("check")
+ .arg("--")
+ .arg("--emit=metadata"),
+ execs().with_status(0));
+}
+
+#[test]
+fn rustc_check_err() {
+ let foo = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.bar]
+ path = "../bar"
+ "#)
+ .file("src/main.rs", r#"
+ extern crate bar;
+ fn main() {
+ ::bar::qux();
+ }
+ "#)
+ .build();
+ let _bar = project("bar")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("src/lib.rs", r#"
+ pub fn baz() {}
+ "#)
+ .build();
+
+ assert_that(foo.cargo("rustc")
+ .arg("--profile")
+ .arg("check")
+ .arg("--")
+ .arg("--emit=metadata"),
+ execs().with_status(101));
+}
+
+#[test]
+fn check_all() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [workspace]
+ [dependencies]
+ b = { path = "b" }
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .file("examples/a.rs", "fn main() {}")
+ .file("tests/a.rs", "")
+ .file("src/lib.rs", "")
+ .file("b/Cargo.toml", r#"
+ [package]
+ name = "b"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("b/src/main.rs", "fn main() {}")
+ .file("b/src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("check").arg("--all").arg("-v"),
+ execs().with_status(0)
+ .with_stderr_contains("[..] --crate-name foo src[/]lib.rs [..]")
+ .with_stderr_contains("[..] --crate-name foo src[/]main.rs [..]")
+ .with_stderr_contains("[..] --crate-name b b[/]src[/]lib.rs [..]")
+ .with_stderr_contains("[..] --crate-name b b[/]src[/]main.rs [..]")
+ );
+}
+
+#[test]
+fn check_virtual_all_implied() {
+ let p = project("workspace")
+ .file("Cargo.toml", r#"
+ [workspace]
+ members = ["foo", "bar"]
+ "#)
+ .file("foo/Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+ "#)
+ .file("foo/src/lib.rs", r#"
+ pub fn foo() {}
+ "#)
+ .file("bar/Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.1.0"
+ "#)
+ .file("bar/src/lib.rs", r#"
+ pub fn bar() {}
+ "#)
+ .build();
+
+ assert_that(p.cargo("check").arg("-v"),
+ execs().with_status(0)
+ .with_stderr_contains("[..] --crate-name foo foo[/]src[/]lib.rs [..]")
+ .with_stderr_contains("[..] --crate-name bar bar[/]src[/]lib.rs [..]")
+ );
+}
+
+#[test]
+fn check_all_targets() {
+ let foo = project("foo")
+ .file("Cargo.toml", SIMPLE_MANIFEST)
+ .file("src/main.rs", "fn main() {}")
+ .file("src/lib.rs", "pub fn smth() {}")
+ .file("examples/example1.rs", "fn main() {}")
+ .file("tests/test2.rs", "#[test] fn t() {}")
+ .file("benches/bench3.rs", "")
+ .build();
+
+ assert_that(foo.cargo("check").arg("--all-targets").arg("-v"),
+ execs().with_status(0)
+ .with_stderr_contains("[..] --crate-name foo src[/]lib.rs [..]")
+ .with_stderr_contains("[..] --crate-name foo src[/]main.rs [..]")
+ .with_stderr_contains("[..] --crate-name example1 examples[/]example1.rs [..]")
+ .with_stderr_contains("[..] --crate-name test2 tests[/]test2.rs [..]")
+ .with_stderr_contains("[..] --crate-name bench3 benches[/]bench3.rs [..]")
+ );
+}
+
+#[test]
+fn check_unit_test_profile() {
+ let foo = project("foo")
+ .file("Cargo.toml", SIMPLE_MANIFEST)
+ .file("src/lib.rs", r#"
+ #[cfg(test)]
+ mod tests {
+ #[test]
+ fn it_works() {
+ badtext
+ }
+ }
+ "#)
+ .build();
+
+ assert_that(foo.cargo("check"),
+ execs().with_status(0));
+ assert_that(foo.cargo("check").arg("--profile").arg("test"),
+ execs().with_status(101)
+ .with_stderr_contains("[..]badtext[..]"));
+}
+
+// Verify what is checked with various command-line filters.
+#[test]
+fn check_filters() {
+ let p = project("foo")
+ .file("Cargo.toml", SIMPLE_MANIFEST)
+ .file("src/lib.rs", r#"
+ fn unused_normal_lib() {}
+ #[cfg(test)]
+ mod tests {
+ fn unused_unit_lib() {}
+ }
+ "#)
+ .file("src/main.rs", r#"
+ fn main() {}
+ fn unused_normal_bin() {}
+ #[cfg(test)]
+ mod tests {
+ fn unused_unit_bin() {}
+ }
+ "#)
+ .file("tests/t1.rs", r#"
+ fn unused_normal_t1() {}
+ #[cfg(test)]
+ mod tests {
+ fn unused_unit_t1() {}
+ }
+ "#)
+ .file("examples/ex1.rs", r#"
+ fn main() {}
+ fn unused_normal_ex1() {}
+ #[cfg(test)]
+ mod tests {
+ fn unused_unit_ex1() {}
+ }
+ "#)
+ .file("benches/b1.rs", r#"
+ fn unused_normal_b1() {}
+ #[cfg(test)]
+ mod tests {
+ fn unused_unit_b1() {}
+ }
+ "#)
+ .build();
+
+ assert_that(p.cargo("check"),
+ execs().with_status(0)
+ .with_stderr_contains("[..]unused_normal_lib[..]")
+ .with_stderr_contains("[..]unused_normal_bin[..]")
+ .with_stderr_does_not_contain("unused_normal_t1")
+ .with_stderr_does_not_contain("unused_normal_ex1")
+ .with_stderr_does_not_contain("unused_normal_b1")
+ .with_stderr_does_not_contain("unused_unit_"));
+ p.root().join("target").rm_rf();
+ assert_that(p.cargo("check").arg("--tests").arg("-v"),
+ execs().with_status(0)
+ .with_stderr_contains("[..] --crate-name foo src[/]lib.rs [..] --test [..]")
+ .with_stderr_contains("[..] --crate-name foo src[/]lib.rs --crate-type lib [..]")
+ .with_stderr_contains("[..] --crate-name foo src[/]main.rs [..] --test [..]")
+ .with_stderr_contains("[..] --crate-name foo src[/]main.rs --crate-type bin [..]")
+ .with_stderr_contains("[..]unused_unit_lib[..]")
+ .with_stderr_contains("[..]unused_unit_bin[..]")
+ .with_stderr_contains("[..]unused_normal_lib[..]")
+ .with_stderr_contains("[..]unused_normal_bin[..]")
+ .with_stderr_contains("[..]unused_unit_t1[..]")
+ .with_stderr_contains("[..]unused_normal_ex1[..]")
+ .with_stderr_contains("[..]unused_unit_ex1[..]")
+ .with_stderr_does_not_contain("unused_normal_b1")
+ .with_stderr_does_not_contain("unused_unit_b1"));
+ p.root().join("target").rm_rf();
+ assert_that(p.cargo("check").arg("--test").arg("t1").arg("-v"),
+ execs().with_status(0)
+ .with_stderr_contains("[..]unused_normal_lib[..]")
+ .with_stderr_contains("[..]unused_normal_bin[..]")
+ .with_stderr_contains("[..]unused_unit_t1[..]")
+ .with_stderr_does_not_contain("unused_unit_lib")
+ .with_stderr_does_not_contain("unused_unit_bin")
+ .with_stderr_does_not_contain("unused_normal_ex1")
+ .with_stderr_does_not_contain("unused_normal_b1")
+ .with_stderr_does_not_contain("unused_unit_ex1")
+ .with_stderr_does_not_contain("unused_unit_b1"));
+ p.root().join("target").rm_rf();
+ assert_that(p.cargo("check").arg("--all-targets").arg("-v"),
+ execs().with_status(0)
+ .with_stderr_contains("[..]unused_normal_lib[..]")
+ .with_stderr_contains("[..]unused_normal_bin[..]")
+ .with_stderr_contains("[..]unused_normal_t1[..]")
+ .with_stderr_contains("[..]unused_normal_ex1[..]")
+ .with_stderr_contains("[..]unused_normal_b1[..]")
+ .with_stderr_contains("[..]unused_unit_b1[..]")
+ .with_stderr_contains("[..]unused_unit_t1[..]")
+ .with_stderr_contains("[..]unused_unit_lib[..]")
+ .with_stderr_contains("[..]unused_unit_bin[..]")
+ .with_stderr_contains("[..]unused_unit_ex1[..]"));
+}
+
+#[test]
+fn check_artifacts()
+{
+ // Verify which artifacts are created when running check (#4059).
+ let p = project("foo")
+ .file("Cargo.toml", SIMPLE_MANIFEST)
+ .file("src/lib.rs", "")
+ .file("src/main.rs", "fn main() {}")
+ .file("tests/t1.rs", "")
+ .file("examples/ex1.rs", "fn main() {}")
+ .file("benches/b1.rs", "")
+ .build();
+ assert_that(p.cargo("check"), execs().with_status(0));
+ assert_that(&p.root().join("target/debug/libfoo.rmeta"),
+ existing_file());
+ assert_that(&p.root().join("target/debug/libfoo.rlib"),
+ is_not(existing_file()));
+ assert_that(&p.root().join("target/debug").join(exe("foo")),
+ is_not(existing_file()));
+
+ p.root().join("target").rm_rf();
+ assert_that(p.cargo("check").arg("--lib"), execs().with_status(0));
+ assert_that(&p.root().join("target/debug/libfoo.rmeta"),
+ existing_file());
+ assert_that(&p.root().join("target/debug/libfoo.rlib"),
+ is_not(existing_file()));
+ assert_that(&p.root().join("target/debug").join(exe("foo")),
+ is_not(existing_file()));
+
+ p.root().join("target").rm_rf();
+ assert_that(p.cargo("check").arg("--bin").arg("foo"),
+ execs().with_status(0));
+ assert_that(&p.root().join("target/debug/libfoo.rmeta"),
+ existing_file());
+ assert_that(&p.root().join("target/debug/libfoo.rlib"),
+ is_not(existing_file()));
+ assert_that(&p.root().join("target/debug").join(exe("foo")),
+ is_not(existing_file()));
+
+ p.root().join("target").rm_rf();
+ assert_that(p.cargo("check").arg("--test").arg("t1"),
+ execs().with_status(0));
+ assert_that(&p.root().join("target/debug/libfoo.rmeta"),
+ existing_file());
+ assert_that(&p.root().join("target/debug/libfoo.rlib"),
+ is_not(existing_file()));
+ assert_that(&p.root().join("target/debug").join(exe("foo")),
+ is_not(existing_file()));
+ assert_that(glob(&p.root().join("target/debug/t1-*").to_str().unwrap())
+ .unwrap().count(),
+ is(equal_to(0)));
+
+ p.root().join("target").rm_rf();
+ assert_that(p.cargo("check").arg("--example").arg("ex1"),
+ execs().with_status(0));
+ assert_that(&p.root().join("target/debug/libfoo.rmeta"),
+ existing_file());
+ assert_that(&p.root().join("target/debug/libfoo.rlib"),
+ is_not(existing_file()));
+ assert_that(&p.root().join("target/debug/examples").join(exe("ex1")),
+ is_not(existing_file()));
+
+ p.root().join("target").rm_rf();
+ assert_that(p.cargo("check").arg("--bench").arg("b1"),
+ execs().with_status(0));
+ assert_that(&p.root().join("target/debug/libfoo.rmeta"),
+ existing_file());
+ assert_that(&p.root().join("target/debug/libfoo.rlib"),
+ is_not(existing_file()));
+ assert_that(&p.root().join("target/debug").join(exe("foo")),
+ is_not(existing_file()));
+ assert_that(glob(&p.root().join("target/debug/b1-*").to_str().unwrap())
+ .unwrap().count(),
+ is(equal_to(0)));
+}
--- /dev/null
+use std::env;
+
+use cargotest::support::{git, project, execs, main_file, basic_bin_manifest};
+use cargotest::support::registry::Package;
+use hamcrest::{assert_that, existing_dir, existing_file, is_not};
+
+#[test]
+fn cargo_clean_simple() {
+ let p = project("foo")
+ .file("Cargo.toml", &basic_bin_manifest("foo"))
+ .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
+ .build();
+
+ assert_that(p.cargo("build"), execs().with_status(0));
+ assert_that(&p.build_dir(), existing_dir());
+
+ assert_that(p.cargo("clean"),
+ execs().with_status(0));
+ assert_that(&p.build_dir(), is_not(existing_dir()));
+}
+
+#[test]
+fn different_dir() {
+ let p = project("foo")
+ .file("Cargo.toml", &basic_bin_manifest("foo"))
+ .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
+ .file("src/bar/a.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"), execs().with_status(0));
+ assert_that(&p.build_dir(), existing_dir());
+
+ assert_that(p.cargo("clean").cwd(&p.root().join("src")),
+ execs().with_status(0).with_stdout(""));
+ assert_that(&p.build_dir(), is_not(existing_dir()));
+}
+
+#[test]
+fn clean_multiple_packages() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.d1]
+ path = "d1"
+ [dependencies.d2]
+ path = "d2"
+
+ [[bin]]
+ name = "foo"
+ "#)
+ .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
+ .file("d1/Cargo.toml", r#"
+ [package]
+ name = "d1"
+ version = "0.0.1"
+ authors = []
+
+ [[bin]]
+ name = "d1"
+ "#)
+ .file("d1/src/main.rs", "fn main() { println!(\"d1\"); }")
+ .file("d2/Cargo.toml", r#"
+ [package]
+ name = "d2"
+ version = "0.0.1"
+ authors = []
+
+ [[bin]]
+ name = "d2"
+ "#)
+ .file("d2/src/main.rs", "fn main() { println!(\"d2\"); }")
+ .build();
+
+ assert_that(p.cargo("build").arg("-p").arg("d1").arg("-p").arg("d2")
+ .arg("-p").arg("foo"),
+ execs().with_status(0));
+
+ let d1_path = &p.build_dir().join("debug")
+ .join(format!("d1{}", env::consts::EXE_SUFFIX));
+ let d2_path = &p.build_dir().join("debug")
+ .join(format!("d2{}", env::consts::EXE_SUFFIX));
+
+
+ assert_that(&p.bin("foo"), existing_file());
+ assert_that(d1_path, existing_file());
+ assert_that(d2_path, existing_file());
+
+ assert_that(p.cargo("clean").arg("-p").arg("d1").arg("-p").arg("d2")
+ .cwd(&p.root().join("src")),
+ execs().with_status(0).with_stdout(""));
+ assert_that(&p.bin("foo"), existing_file());
+ assert_that(d1_path, is_not(existing_file()));
+ assert_that(d2_path, is_not(existing_file()));
+}
+
+#[test]
+fn clean_release() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ a = { path = "a" }
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .file("a/Cargo.toml", r#"
+ [package]
+ name = "a"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("a/src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build").arg("--release"),
+ execs().with_status(0));
+
+ assert_that(p.cargo("clean").arg("-p").arg("foo"),
+ execs().with_status(0));
+ assert_that(p.cargo("build").arg("--release"),
+ execs().with_status(0).with_stdout(""));
+
+ assert_that(p.cargo("clean").arg("-p").arg("foo").arg("--release"),
+ execs().with_status(0));
+ assert_that(p.cargo("build").arg("--release"),
+ execs().with_status(0).with_stderr("\
+[COMPILING] foo v0.0.1 ([..])
+[FINISHED] release [optimized] target(s) in [..]
+"));
+}
+
+#[test]
+fn build_script() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ build = "build.rs"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .file("build.rs", r#"
+ use std::path::PathBuf;
+ use std::env;
+
+ fn main() {
+ let out = PathBuf::from(env::var_os("OUT_DIR").unwrap());
+ if env::var("FIRST").is_ok() {
+ std::fs::File::create(out.join("out")).unwrap();
+ } else {
+ assert!(!std::fs::metadata(out.join("out")).is_ok());
+ }
+ }
+ "#)
+ .file("a/src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build").env("FIRST", "1"),
+ execs().with_status(0));
+ assert_that(p.cargo("clean").arg("-p").arg("foo"),
+ execs().with_status(0));
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(0).with_stderr("\
+[COMPILING] foo v0.0.1 ([..])
+[RUNNING] `rustc [..] build.rs [..]`
+[RUNNING] `[..]build-script-build`
+[RUNNING] `rustc [..] src[/]main.rs [..]`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+}
+
+#[test]
+fn clean_git() {
+ let git = git::new("dep", |project| {
+ project.file("Cargo.toml", r#"
+ [project]
+ name = "dep"
+ version = "0.5.0"
+ authors = []
+ "#)
+ .file("src/lib.rs", "")
+ }).unwrap();
+
+ let p = project("foo")
+ .file("Cargo.toml", &format!(r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ dep = {{ git = '{}' }}
+ "#, git.url()))
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0));
+ assert_that(p.cargo("clean").arg("-p").arg("dep"),
+ execs().with_status(0).with_stdout(""));
+ assert_that(p.cargo("build"),
+ execs().with_status(0));
+}
+
+#[test]
+fn registry() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ bar = "0.1"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ Package::new("bar", "0.1.0").publish();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0));
+ assert_that(p.cargo("clean").arg("-p").arg("bar"),
+ execs().with_status(0).with_stdout(""));
+ assert_that(p.cargo("build"),
+ execs().with_status(0));
+}
--- /dev/null
+use std::{env, str};
+use std::fs::{self, File};
+use std::io::Write;
+use std::net::TcpListener;
+use std::process::Stdio;
+use std::thread;
+use std::sync::mpsc::channel;
+use std::time::Duration;
+
+use git2;
+use cargotest;
+use cargotest::install::{has_installed_exe, cargo_home};
+use cargotest::support::git;
+use cargotest::support::registry::Package;
+use cargotest::support::{execs, project};
+use hamcrest::{assert_that, existing_file};
+
+fn pkg(name: &str, vers: &str) {
+ Package::new(name, vers)
+ .file("src/main.rs", "fn main() {{}}")
+ .publish();
+}
+
+#[test]
+fn multiple_installs() {
+ let p = project("foo")
+ .file("a/Cargo.toml", r#"
+ [package]
+ name = "foo"
+ authors = []
+ version = "0.0.0"
+ "#)
+ .file("a/src/main.rs", "fn main() {}")
+ .file("b/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ authors = []
+ version = "0.0.0"
+ "#)
+ .file("b/src/main.rs", "fn main() {}");
+ let p = p.build();
+
+ let mut a = p.cargo("install").cwd(p.root().join("a")).build_command();
+ let mut b = p.cargo("install").cwd(p.root().join("b")).build_command();
+
+ a.stdout(Stdio::piped()).stderr(Stdio::piped());
+ b.stdout(Stdio::piped()).stderr(Stdio::piped());
+
+ let a = a.spawn().unwrap();
+ let b = b.spawn().unwrap();
+ let a = thread::spawn(move || a.wait_with_output().unwrap());
+ let b = b.wait_with_output().unwrap();
+ let a = a.join().unwrap();
+
+ assert_that(a, execs().with_status(0));
+ assert_that(b, execs().with_status(0));
+
+ assert_that(cargo_home(), has_installed_exe("foo"));
+ assert_that(cargo_home(), has_installed_exe("bar"));
+}
+
+#[test]
+fn concurrent_installs() {
+ const LOCKED_BUILD: &'static str = "waiting for file lock on build directory";
+
+ pkg("foo", "0.0.1");
+ pkg("bar", "0.0.1");
+
+ let mut a = cargotest::cargo_process().arg("install").arg("foo").build_command();
+ let mut b = cargotest::cargo_process().arg("install").arg("bar").build_command();
+
+ a.stdout(Stdio::piped()).stderr(Stdio::piped());
+ b.stdout(Stdio::piped()).stderr(Stdio::piped());
+
+ let a = a.spawn().unwrap();
+ let b = b.spawn().unwrap();
+ let a = thread::spawn(move || a.wait_with_output().unwrap());
+ let b = b.wait_with_output().unwrap();
+ let a = a.join().unwrap();
+
+ assert!(!str::from_utf8(&a.stderr).unwrap().contains(LOCKED_BUILD));
+ assert!(!str::from_utf8(&b.stderr).unwrap().contains(LOCKED_BUILD));
+
+ assert_that(a, execs().with_status(0));
+ assert_that(b, execs().with_status(0));
+
+ assert_that(cargo_home(), has_installed_exe("foo"));
+ assert_that(cargo_home(), has_installed_exe("bar"));
+}
+
+#[test]
+fn one_install_should_be_bad() {
+ let p = project("foo")
+ .file("a/Cargo.toml", r#"
+ [package]
+ name = "foo"
+ authors = []
+ version = "0.0.0"
+ "#)
+ .file("a/src/main.rs", "fn main() {}")
+ .file("b/Cargo.toml", r#"
+ [package]
+ name = "foo"
+ authors = []
+ version = "0.0.0"
+ "#)
+ .file("b/src/main.rs", "fn main() {}");
+ let p = p.build();
+
+ let mut a = p.cargo("install").cwd(p.root().join("a")).build_command();
+ let mut b = p.cargo("install").cwd(p.root().join("b")).build_command();
+
+ a.stdout(Stdio::piped()).stderr(Stdio::piped());
+ b.stdout(Stdio::piped()).stderr(Stdio::piped());
+
+ let a = a.spawn().unwrap();
+ let b = b.spawn().unwrap();
+ let a = thread::spawn(move || a.wait_with_output().unwrap());
+ let b = b.wait_with_output().unwrap();
+ let a = a.join().unwrap();
+
+ let (bad, good) = if a.status.code() == Some(101) {(a, b)} else {(b, a)};
+ assert_that(bad, execs().with_status(101).with_stderr_contains("\
+[ERROR] binary `foo[..]` already exists in destination as part of `[..]`
+"));
+ assert_that(good, execs().with_status(0).with_stderr_contains("\
+warning: be sure to add `[..]` to your PATH [..]
+"));
+
+ assert_that(cargo_home(), has_installed_exe("foo"));
+}
+
+#[test]
+fn multiple_registry_fetches() {
+ let mut pkg = Package::new("bar", "1.0.2");
+ for i in 0..10 {
+ let name = format!("foo{}", i);
+ Package::new(&name, "1.0.0").publish();
+ pkg.dep(&name, "*");
+ }
+ pkg.publish();
+
+ let p = project("foo")
+ .file("a/Cargo.toml", r#"
+ [package]
+ name = "foo"
+ authors = []
+ version = "0.0.0"
+
+ [dependencies]
+ bar = "*"
+ "#)
+ .file("a/src/main.rs", "fn main() {}")
+ .file("b/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ authors = []
+ version = "0.0.0"
+
+ [dependencies]
+ bar = "*"
+ "#)
+ .file("b/src/main.rs", "fn main() {}");
+ let p = p.build();
+
+ let mut a = p.cargo("build").cwd(p.root().join("a")).build_command();
+ let mut b = p.cargo("build").cwd(p.root().join("b")).build_command();
+
+ a.stdout(Stdio::piped()).stderr(Stdio::piped());
+ b.stdout(Stdio::piped()).stderr(Stdio::piped());
+
+ let a = a.spawn().unwrap();
+ let b = b.spawn().unwrap();
+ let a = thread::spawn(move || a.wait_with_output().unwrap());
+ let b = b.wait_with_output().unwrap();
+ let a = a.join().unwrap();
+
+ assert_that(a, execs().with_status(0));
+ assert_that(b, execs().with_status(0));
+
+ let suffix = env::consts::EXE_SUFFIX;
+ assert_that(&p.root().join("a/target/debug").join(format!("foo{}", suffix)),
+ existing_file());
+ assert_that(&p.root().join("b/target/debug").join(format!("bar{}", suffix)),
+ existing_file());
+}
+
+#[test]
+fn git_same_repo_different_tags() {
+ let a = git::new("dep", |project| {
+ project.file("Cargo.toml", r#"
+ [project]
+ name = "dep"
+ version = "0.5.0"
+ authors = []
+ "#).file("src/lib.rs", "pub fn tag1() {}")
+ }).unwrap();
+
+ let repo = git2::Repository::open(&a.root()).unwrap();
+ git::tag(&repo, "tag1");
+
+ File::create(a.root().join("src/lib.rs")).unwrap()
+ .write_all(b"pub fn tag2() {}").unwrap();
+ git::add(&repo);
+ git::commit(&repo);
+ git::tag(&repo, "tag2");
+
+ let p = project("foo")
+ .file("a/Cargo.toml", &format!(r#"
+ [package]
+ name = "foo"
+ authors = []
+ version = "0.0.0"
+
+ [dependencies]
+ dep = {{ git = '{}', tag = 'tag1' }}
+ "#, a.url()))
+ .file("a/src/main.rs", "extern crate dep; fn main() { dep::tag1(); }")
+ .file("b/Cargo.toml", &format!(r#"
+ [package]
+ name = "bar"
+ authors = []
+ version = "0.0.0"
+
+ [dependencies]
+ dep = {{ git = '{}', tag = 'tag2' }}
+ "#, a.url()))
+ .file("b/src/main.rs", "extern crate dep; fn main() { dep::tag2(); }");
+ let p = p.build();
+
+ let mut a = p.cargo("build").arg("-v").cwd(p.root().join("a")).build_command();
+ let mut b = p.cargo("build").arg("-v").cwd(p.root().join("b")).build_command();
+
+ a.stdout(Stdio::piped()).stderr(Stdio::piped());
+ b.stdout(Stdio::piped()).stderr(Stdio::piped());
+
+ let a = a.spawn().unwrap();
+ let b = b.spawn().unwrap();
+ let a = thread::spawn(move || a.wait_with_output().unwrap());
+ let b = b.wait_with_output().unwrap();
+ let a = a.join().unwrap();
+
+ assert_that(a, execs().with_status(0));
+ assert_that(b, execs().with_status(0));
+}
+
+#[test]
+fn git_same_branch_different_revs() {
+ let a = git::new("dep", |project| {
+ project.file("Cargo.toml", r#"
+ [project]
+ name = "dep"
+ version = "0.5.0"
+ authors = []
+ "#).file("src/lib.rs", "pub fn f1() {}")
+ }).unwrap();
+
+ let p = project("foo")
+ .file("a/Cargo.toml", &format!(r#"
+ [package]
+ name = "foo"
+ authors = []
+ version = "0.0.0"
+
+ [dependencies]
+ dep = {{ git = '{}' }}
+ "#, a.url()))
+ .file("a/src/main.rs", "extern crate dep; fn main() { dep::f1(); }")
+ .file("b/Cargo.toml", &format!(r#"
+ [package]
+ name = "bar"
+ authors = []
+ version = "0.0.0"
+
+ [dependencies]
+ dep = {{ git = '{}' }}
+ "#, a.url()))
+ .file("b/src/main.rs", "extern crate dep; fn main() { dep::f2(); }");
+ let p = p.build();
+
+ // Generate a Cargo.lock pointing at the current rev, then clear out the
+ // target directory
+ assert_that(p.cargo("build").cwd(p.root().join("a")),
+ execs().with_status(0));
+ fs::remove_dir_all(p.root().join("a/target")).unwrap();
+
+ // Make a new commit on the master branch
+ let repo = git2::Repository::open(&a.root()).unwrap();
+ File::create(a.root().join("src/lib.rs")).unwrap()
+ .write_all(b"pub fn f2() {}").unwrap();
+ git::add(&repo);
+ git::commit(&repo);
+
+ // Now run both builds in parallel. The build of `b` should pick up the
+ // newest commit while the build of `a` should use the locked old commit.
+ let mut a = p.cargo("build").cwd(p.root().join("a")).build_command();
+ let mut b = p.cargo("build").cwd(p.root().join("b")).build_command();
+
+ a.stdout(Stdio::piped()).stderr(Stdio::piped());
+ b.stdout(Stdio::piped()).stderr(Stdio::piped());
+
+ let a = a.spawn().unwrap();
+ let b = b.spawn().unwrap();
+ let a = thread::spawn(move || a.wait_with_output().unwrap());
+ let b = b.wait_with_output().unwrap();
+ let a = a.join().unwrap();
+
+ assert_that(a, execs().with_status(0));
+ assert_that(b, execs().with_status(0));
+}
+
+#[test]
+fn same_project() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ authors = []
+ version = "0.0.0"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .file("src/lib.rs", "");
+ let p = p.build();
+
+ let mut a = p.cargo("build").build_command();
+ let mut b = p.cargo("build").build_command();
+
+ a.stdout(Stdio::piped()).stderr(Stdio::piped());
+ b.stdout(Stdio::piped()).stderr(Stdio::piped());
+
+ let a = a.spawn().unwrap();
+ let b = b.spawn().unwrap();
+ let a = thread::spawn(move || a.wait_with_output().unwrap());
+ let b = b.wait_with_output().unwrap();
+ let a = a.join().unwrap();
+
+ assert_that(a, execs().with_status(0));
+ assert_that(b, execs().with_status(0));
+}
+
+// Make sure that if Cargo dies while holding a lock that it's released and the
+// next Cargo to come in will take over cleanly.
+// older win versions don't support job objects, so skip test there
+#[test]
+#[cfg_attr(target_os = "windows", ignore)]
+fn killing_cargo_releases_the_lock() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ authors = []
+ version = "0.0.0"
+ build = "build.rs"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .file("build.rs", r#"
+ use std::net::TcpStream;
+
+ fn main() {
+ if std::env::var("A").is_ok() {
+ TcpStream::connect(&std::env::var("ADDR").unwrap()[..])
+ .unwrap();
+ std::thread::sleep(std::time::Duration::new(10, 0));
+ }
+ }
+ "#);
+ let p = p.build();
+
+ // Our build script will connect to our local TCP socket to inform us that
+ // it's started and that's how we know that `a` will have the lock
+ // when we kill it.
+ let l = TcpListener::bind("127.0.0.1:0").unwrap();
+ let mut a = p.cargo("build").build_command();
+ let mut b = p.cargo("build").build_command();
+ a.stdout(Stdio::piped()).stderr(Stdio::piped());
+ b.stdout(Stdio::piped()).stderr(Stdio::piped());
+ a.env("ADDR", l.local_addr().unwrap().to_string()).env("A", "a");
+ b.env("ADDR", l.local_addr().unwrap().to_string()).env_remove("A");
+
+ // Spawn `a`, wait for it to get to the build script (at which point the
+ // lock is held), then kill it.
+ let mut a = a.spawn().unwrap();
+ l.accept().unwrap();
+ a.kill().unwrap();
+
+ // Spawn `b`, then just finish the output of a/b the same way the above
+ // tests does.
+ let b = b.spawn().unwrap();
+ let a = thread::spawn(move || a.wait_with_output().unwrap());
+ let b = b.wait_with_output().unwrap();
+ let a = a.join().unwrap();
+
+ // We killed `a`, so it shouldn't succeed, but `b` should have succeeded.
+ assert!(!a.status.success());
+ assert_that(b, execs().with_status(0));
+}
+
+#[test]
+fn debug_release_ok() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ authors = []
+ version = "0.0.0"
+ "#)
+ .file("src/main.rs", "fn main() {}");
+ let p = p.build();
+
+ assert_that(p.cargo("build"), execs().with_status(0));
+ fs::remove_dir_all(p.root().join("target")).unwrap();
+
+ let mut a = p.cargo("build").build_command();
+ let mut b = p.cargo("build").arg("--release").build_command();
+ a.stdout(Stdio::piped()).stderr(Stdio::piped());
+ b.stdout(Stdio::piped()).stderr(Stdio::piped());
+ let a = a.spawn().unwrap();
+ let b = b.spawn().unwrap();
+ let a = thread::spawn(move || a.wait_with_output().unwrap());
+ let b = b.wait_with_output().unwrap();
+ let a = a.join().unwrap();
+
+ assert_that(a, execs().with_status(0).with_stderr("\
+[COMPILING] foo v0.0.0 [..]
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+ assert_that(b, execs().with_status(0).with_stderr("\
+[COMPILING] foo v0.0.0 [..]
+[FINISHED] release [optimized] target(s) in [..]
+"));
+}
+
+#[test]
+fn no_deadlock_with_git_dependencies() {
+ let dep1 = git::new("dep1", |project| {
+ project.file("Cargo.toml", r#"
+ [project]
+ name = "dep1"
+ version = "0.5.0"
+ authors = []
+ "#).file("src/lib.rs", "")
+ }).unwrap();
+
+ let dep2 = git::new("dep2", |project| {
+ project.file("Cargo.toml", r#"
+ [project]
+ name = "dep2"
+ version = "0.5.0"
+ authors = []
+ "#).file("src/lib.rs", "")
+ }).unwrap();
+
+ let p = project("foo")
+ .file("Cargo.toml", &format!(r#"
+ [package]
+ name = "foo"
+ authors = []
+ version = "0.0.0"
+
+ [dependencies]
+ dep1 = {{ git = '{}' }}
+ dep2 = {{ git = '{}' }}
+ "#, dep1.url(), dep2.url()))
+ .file("src/main.rs", "fn main() { }");
+ let p = p.build();
+
+ let n_concurrent_builds = 5;
+
+ let (tx, rx) = channel();
+ for _ in 0..n_concurrent_builds {
+ let cmd = p.cargo("build").build_command()
+ .stdout(Stdio::piped())
+ .stderr(Stdio::piped())
+ .spawn();
+ let tx = tx.clone();
+ thread::spawn(move || {
+ let result = cmd.unwrap().wait_with_output().unwrap();
+ tx.send(result).unwrap()
+ });
+ }
+
+ //TODO: use `Receiver::recv_timeout` once it is stable.
+ let recv_timeout = |chan: &::std::sync::mpsc::Receiver<_>| {
+ for _ in 0..3000 {
+ if let Ok(x) = chan.try_recv() {
+ return x
+ }
+ thread::sleep(Duration::from_millis(10));
+ }
+ chan.try_recv().expect("Deadlock!")
+ };
+
+ for _ in 0..n_concurrent_builds {
+ let result = recv_timeout(&rx);
+ assert_that(result, execs().with_status(0))
+ }
+
+}
--- /dev/null
+use cargotest::support::{project, execs};
+use hamcrest::assert_that;
+
+#[test]
+fn read_env_vars_for_config() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ authors = []
+ version = "0.0.0"
+ build = "build.rs"
+ "#)
+ .file("src/lib.rs", "")
+ .file("build.rs", r#"
+ use std::env;
+ fn main() {
+ assert_eq!(env::var("NUM_JOBS").unwrap(), "100");
+ }
+ "#)
+ .build();
+
+ assert_that(p.cargo("build").env("CARGO_BUILD_JOBS", "100"),
+ execs().with_status(0));
+}
--- /dev/null
+use cargo::util::process;
+use cargotest::{is_nightly, rustc_host};
+use cargotest::support::{project, execs, basic_bin_manifest, cross_compile};
+use hamcrest::{assert_that, existing_file};
+
+#[test]
+fn simple_cross() {
+ if cross_compile::disabled() { return }
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.0"
+ authors = []
+ build = "build.rs"
+ "#)
+ .file("build.rs", &format!(r#"
+ fn main() {{
+ assert_eq!(std::env::var("TARGET").unwrap(), "{}");
+ }}
+ "#, cross_compile::alternate()))
+ .file("src/main.rs", &format!(r#"
+ use std::env;
+ fn main() {{
+ assert_eq!(env::consts::ARCH, "{}");
+ }}
+ "#, cross_compile::alternate_arch()))
+ .build();
+
+ let target = cross_compile::alternate();
+ assert_that(p.cargo("build").arg("--target").arg(&target).arg("-v"),
+ execs().with_status(0));
+ assert_that(&p.target_bin(&target, "foo"), existing_file());
+
+ assert_that(process(&p.target_bin(&target, "foo")),
+ execs().with_status(0));
+}
+
+#[test]
+fn simple_cross_config() {
+ if cross_compile::disabled() { return }
+
+ let p = project("foo")
+ .file(".cargo/config", &format!(r#"
+ [build]
+ target = "{}"
+ "#, cross_compile::alternate()))
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.0"
+ authors = []
+ build = "build.rs"
+ "#)
+ .file("build.rs", &format!(r#"
+ fn main() {{
+ assert_eq!(std::env::var("TARGET").unwrap(), "{}");
+ }}
+ "#, cross_compile::alternate()))
+ .file("src/main.rs", &format!(r#"
+ use std::env;
+ fn main() {{
+ assert_eq!(env::consts::ARCH, "{}");
+ }}
+ "#, cross_compile::alternate_arch()))
+ .build();
+
+ let target = cross_compile::alternate();
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(0));
+ assert_that(&p.target_bin(&target, "foo"), existing_file());
+
+ assert_that(process(&p.target_bin(&target, "foo")),
+ execs().with_status(0));
+}
+
+#[test]
+fn simple_deps() {
+ if cross_compile::disabled() { return }
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.bar]
+ path = "../bar"
+ "#)
+ .file("src/main.rs", r#"
+ extern crate bar;
+ fn main() { bar::bar(); }
+ "#)
+ .build();
+ let _p2 = project("bar")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/lib.rs", "pub fn bar() {}")
+ .build();
+
+ let target = cross_compile::alternate();
+ assert_that(p.cargo("build").arg("--target").arg(&target),
+ execs().with_status(0));
+ assert_that(&p.target_bin(&target, "foo"), existing_file());
+
+ assert_that(process(&p.target_bin(&target, "foo")),
+ execs().with_status(0));
+}
+
+#[test]
+fn plugin_deps() {
+ if cross_compile::disabled() { return }
+ if !is_nightly() { return }
+
+ let foo = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.bar]
+ path = "../bar"
+
+ [dependencies.baz]
+ path = "../baz"
+ "#)
+ .file("src/main.rs", r#"
+ #![feature(plugin)]
+ #![plugin(bar)]
+ extern crate baz;
+ fn main() {
+ assert_eq!(bar!(), baz::baz());
+ }
+ "#)
+ .build();
+ let _bar = project("bar")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+
+ [lib]
+ name = "bar"
+ plugin = true
+ "#)
+ .file("src/lib.rs", r#"
+ #![feature(plugin_registrar, quote, rustc_private)]
+
+ extern crate rustc_plugin;
+ extern crate syntax;
+
+ use rustc_plugin::Registry;
+ use syntax::tokenstream::TokenTree;
+ use syntax::codemap::Span;
+ use syntax::ast::*;
+ use syntax::ext::base::{ExtCtxt, MacEager, MacResult};
+ use syntax::ext::build::AstBuilder;
+
+ #[plugin_registrar]
+ pub fn foo(reg: &mut Registry) {
+ reg.register_macro("bar", expand_bar);
+ }
+
+ fn expand_bar(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree])
+ -> Box<MacResult + 'static> {
+ MacEager::expr(cx.expr_lit(sp, LitKind::Int(1, LitIntType::Unsuffixed)))
+ }
+ "#)
+ .build();
+ let _baz = project("baz")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "baz"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/lib.rs", "pub fn baz() -> i32 { 1 }")
+ .build();
+
+ let target = cross_compile::alternate();
+ assert_that(foo.cargo("build").arg("--target").arg(&target),
+ execs().with_status(0));
+ assert_that(&foo.target_bin(&target, "foo"), existing_file());
+
+ assert_that(process(&foo.target_bin(&target, "foo")),
+ execs().with_status(0));
+}
+
+#[test]
+fn plugin_to_the_max() {
+ if cross_compile::disabled() { return }
+ if !is_nightly() { return }
+
+ let foo = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.bar]
+ path = "../bar"
+
+ [dependencies.baz]
+ path = "../baz"
+ "#)
+ .file("src/main.rs", r#"
+ #![feature(plugin)]
+ #![plugin(bar)]
+ extern crate baz;
+ fn main() {
+ assert_eq!(bar!(), baz::baz());
+ }
+ "#)
+ .build();
+ let _bar = project("bar")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+
+ [lib]
+ name = "bar"
+ plugin = true
+
+ [dependencies.baz]
+ path = "../baz"
+ "#)
+ .file("src/lib.rs", r#"
+ #![feature(plugin_registrar, quote, rustc_private)]
+
+ extern crate rustc_plugin;
+ extern crate syntax;
+ extern crate baz;
+
+ use rustc_plugin::Registry;
+ use syntax::tokenstream::TokenTree;
+ use syntax::codemap::Span;
+ use syntax::ast::*;
+ use syntax::ext::base::{ExtCtxt, MacEager, MacResult};
+ use syntax::ext::build::AstBuilder;
+ use syntax::ptr::P;
+
+ #[plugin_registrar]
+ pub fn foo(reg: &mut Registry) {
+ reg.register_macro("bar", expand_bar);
+ }
+
+ fn expand_bar(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree])
+ -> Box<MacResult + 'static> {
+ let bar = Ident::from_str("baz");
+ let path = cx.path(sp, vec![bar.clone(), bar]);
+ MacEager::expr(cx.expr_call(sp, cx.expr_path(path), vec![]))
+ }
+ "#)
+ .build();
+ let _baz = project("baz")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "baz"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/lib.rs", "pub fn baz() -> i32 { 1 }")
+ .build();
+
+ let target = cross_compile::alternate();
+ assert_that(foo.cargo("build").arg("--target").arg(&target).arg("-v"),
+ execs().with_status(0));
+ println!("second");
+ assert_that(foo.cargo("build").arg("-v")
+ .arg("--target").arg(&target),
+ execs().with_status(0));
+ assert_that(&foo.target_bin(&target, "foo"), existing_file());
+
+ assert_that(process(&foo.target_bin(&target, "foo")),
+ execs().with_status(0));
+}
+
+#[test]
+fn linker_and_ar() {
+ if cross_compile::disabled() { return }
+
+ let target = cross_compile::alternate();
+ let p = project("foo")
+ .file(".cargo/config", &format!(r#"
+ [target.{}]
+ ar = "my-ar-tool"
+ linker = "my-linker-tool"
+ "#, target))
+ .file("Cargo.toml", &basic_bin_manifest("foo"))
+ .file("src/foo.rs", &format!(r#"
+ use std::env;
+ fn main() {{
+ assert_eq!(env::consts::ARCH, "{}");
+ }}
+ "#, cross_compile::alternate_arch()))
+ .build();
+
+ assert_that(p.cargo("build").arg("--target").arg(&target)
+ .arg("-v"),
+ execs().with_status(101)
+ .with_stderr_contains(&format!("\
+[COMPILING] foo v0.5.0 ({url})
+[RUNNING] `rustc --crate-name foo src[/]foo.rs --crate-type bin \
+ --emit=dep-info,link -C debuginfo=2 \
+ -C metadata=[..] \
+ --out-dir {dir}[/]target[/]{target}[/]debug[/]deps \
+ --target {target} \
+ -C ar=my-ar-tool -C linker=my-linker-tool \
+ -L dependency={dir}[/]target[/]{target}[/]debug[/]deps \
+ -L dependency={dir}[/]target[/]debug[/]deps`
+",
+ dir = p.root().display(),
+ url = p.url(),
+ target = target,
+ )));
+}
+
+#[test]
+fn plugin_with_extra_dylib_dep() {
+ if cross_compile::disabled() { return }
+ if !is_nightly() { return }
+
+ let foo = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.bar]
+ path = "../bar"
+ "#)
+ .file("src/main.rs", r#"
+ #![feature(plugin)]
+ #![plugin(bar)]
+
+ fn main() {}
+ "#)
+ .build();
+ let _bar = project("bar")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+
+ [lib]
+ name = "bar"
+ plugin = true
+
+ [dependencies.baz]
+ path = "../baz"
+ "#)
+ .file("src/lib.rs", r#"
+ #![feature(plugin_registrar, rustc_private)]
+
+ extern crate rustc_plugin;
+ extern crate baz;
+
+ use rustc_plugin::Registry;
+
+ #[plugin_registrar]
+ pub fn foo(reg: &mut Registry) {
+ println!("{}", baz::baz());
+ }
+ "#)
+ .build();
+ let _baz = project("baz")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "baz"
+ version = "0.0.1"
+ authors = []
+
+ [lib]
+ name = "baz"
+ crate_type = ["dylib"]
+ "#)
+ .file("src/lib.rs", "pub fn baz() -> i32 { 1 }")
+ .build();
+
+ let target = cross_compile::alternate();
+ assert_that(foo.cargo("build").arg("--target").arg(&target),
+ execs().with_status(0));
+}
+
+#[test]
+fn cross_tests() {
+ if cross_compile::disabled() { return }
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ authors = []
+ version = "0.0.0"
+
+ [[bin]]
+ name = "bar"
+ "#)
+ .file("src/bin/bar.rs", &format!(r#"
+ #[allow(unused_extern_crates)]
+ extern crate foo;
+ use std::env;
+ fn main() {{
+ assert_eq!(env::consts::ARCH, "{}");
+ }}
+ #[test] fn test() {{ main() }}
+ "#, cross_compile::alternate_arch()))
+ .file("src/lib.rs", &format!(r#"
+ use std::env;
+ pub fn foo() {{ assert_eq!(env::consts::ARCH, "{}"); }}
+ #[test] fn test_foo() {{ foo() }}
+ "#, cross_compile::alternate_arch()))
+ .build();
+
+ let target = cross_compile::alternate();
+ assert_that(p.cargo("test").arg("--target").arg(&target),
+ execs().with_status(0)
+ .with_stderr(&format!("\
+[COMPILING] foo v0.0.0 ({foo})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] target[/]{triple}[/]debug[/]deps[/]foo-[..][EXE]
+[RUNNING] target[/]{triple}[/]debug[/]deps[/]bar-[..][EXE]", foo = p.url(), triple = target))
+ .with_stdout_contains("test test_foo ... ok")
+ .with_stdout_contains("test test ... ok"));
+}
+
+#[test]
+fn no_cross_doctests() {
+ if cross_compile::disabled() { return }
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ authors = []
+ version = "0.0.0"
+ "#)
+ .file("src/lib.rs", r#"
+ //! ```
+ //! extern crate foo;
+ //! assert!(true);
+ //! ```
+ "#)
+ .build();
+
+ let host_output = format!("\
+[COMPILING] foo v0.0.0 ({foo})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] target[/]debug[/]deps[/]foo-[..][EXE]
+[DOCTEST] foo
+", foo = p.url());
+
+ println!("a");
+ assert_that(p.cargo("test"),
+ execs().with_status(0)
+ .with_stderr(&host_output));
+
+ println!("b");
+ let target = cross_compile::host();
+ assert_that(p.cargo("test").arg("--target").arg(&target),
+ execs().with_status(0)
+ .with_stderr(&format!("\
+[COMPILING] foo v0.0.0 ({foo})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] target[/]{triple}[/]debug[/]deps[/]foo-[..][EXE]
+[DOCTEST] foo
+", foo = p.url(), triple = target)));
+
+ println!("c");
+ let target = cross_compile::alternate();
+ assert_that(p.cargo("test").arg("--target").arg(&target),
+ execs().with_status(0)
+ .with_stderr(&format!("\
+[COMPILING] foo v0.0.0 ({foo})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] target[/]{triple}[/]debug[/]deps[/]foo-[..][EXE]
+", foo = p.url(), triple = target)));
+}
+
+#[test]
+fn simple_cargo_run() {
+ if cross_compile::disabled() { return }
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.0"
+ authors = []
+ "#)
+ .file("src/main.rs", &format!(r#"
+ use std::env;
+ fn main() {{
+ assert_eq!(env::consts::ARCH, "{}");
+ }}
+ "#, cross_compile::alternate_arch()))
+ .build();
+
+ let target = cross_compile::alternate();
+ assert_that(p.cargo("run").arg("--target").arg(&target),
+ execs().with_status(0));
+}
+
+#[test]
+fn cross_with_a_build_script() {
+ if cross_compile::disabled() { return }
+
+ let target = cross_compile::alternate();
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.0"
+ authors = []
+ build = 'build.rs'
+ "#)
+ .file("build.rs", &format!(r#"
+ use std::env;
+ use std::path::PathBuf;
+ fn main() {{
+ assert_eq!(env::var("TARGET").unwrap(), "{0}");
+ let mut path = PathBuf::from(env::var_os("OUT_DIR").unwrap());
+ assert_eq!(path.file_name().unwrap().to_str().unwrap(), "out");
+ path.pop();
+ assert!(path.file_name().unwrap().to_str().unwrap()
+ .starts_with("foo-"));
+ path.pop();
+ assert_eq!(path.file_name().unwrap().to_str().unwrap(), "build");
+ path.pop();
+ assert_eq!(path.file_name().unwrap().to_str().unwrap(), "debug");
+ path.pop();
+ assert_eq!(path.file_name().unwrap().to_str().unwrap(), "{0}");
+ path.pop();
+ assert_eq!(path.file_name().unwrap().to_str().unwrap(), "target");
+ }}
+ "#, target))
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("build").arg("--target").arg(&target).arg("-v"),
+ execs().with_status(0)
+ .with_stderr(&format!("\
+[COMPILING] foo v0.0.0 (file://[..])
+[RUNNING] `rustc [..] build.rs [..] --out-dir {dir}[/]target[/]debug[/]build[/]foo-[..]`
+[RUNNING] `{dir}[/]target[/]debug[/]build[/]foo-[..][/]build-script-build`
+[RUNNING] `rustc [..] src[/]main.rs [..] --target {target} [..]`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+", target = target,
+ dir = p.root().display())));
+}
+
+#[test]
+fn build_script_needed_for_host_and_target() {
+ if cross_compile::disabled() { return }
+
+ let target = cross_compile::alternate();
+ let host = rustc_host();
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.0"
+ authors = []
+ build = 'build.rs'
+
+ [dependencies.d1]
+ path = "d1"
+ [build-dependencies.d2]
+ path = "d2"
+ "#)
+
+ .file("build.rs", r#"
+ #[allow(unused_extern_crates)]
+ extern crate d2;
+ fn main() { d2::d2(); }
+ "#)
+ .file("src/main.rs", "
+ #[allow(unused_extern_crates)]
+ extern crate d1;
+ fn main() { d1::d1(); }
+ ")
+ .file("d1/Cargo.toml", r#"
+ [package]
+ name = "d1"
+ version = "0.0.0"
+ authors = []
+ build = 'build.rs'
+ "#)
+ .file("d1/src/lib.rs", "
+ pub fn d1() {}
+ ")
+ .file("d1/build.rs", r#"
+ use std::env;
+ fn main() {
+ let target = env::var("TARGET").unwrap();
+ println!("cargo:rustc-flags=-L /path/to/{}", target);
+ }
+ "#)
+ .file("d2/Cargo.toml", r#"
+ [package]
+ name = "d2"
+ version = "0.0.0"
+ authors = []
+
+ [dependencies.d1]
+ path = "../d1"
+ "#)
+ .file("d2/src/lib.rs", "
+ #[allow(unused_extern_crates)]
+ extern crate d1;
+ pub fn d2() { d1::d1(); }
+ ")
+ .build();
+
+ assert_that(p.cargo("build").arg("--target").arg(&target).arg("-v"),
+ execs().with_status(0)
+ .with_stderr_contains(&format!("\
+[COMPILING] d1 v0.0.0 ({url}/d1)", url = p.url()))
+ .with_stderr_contains(&format!("\
+[RUNNING] `rustc [..] d1[/]build.rs [..] --out-dir {dir}[/]target[/]debug[/]build[/]d1-[..]`",
+ dir = p.root().display()))
+ .with_stderr_contains(&format!("\
+[RUNNING] `{dir}[/]target[/]debug[/]build[/]d1-[..][/]build-script-build`",
+ dir = p.root().display()))
+ .with_stderr_contains("\
+[RUNNING] `rustc [..] d1[/]src[/]lib.rs [..]`")
+ .with_stderr_contains(&format!("\
+[COMPILING] d2 v0.0.0 ({url}/d2)", url = p.url()))
+ .with_stderr_contains(&format!("\
+[RUNNING] `rustc [..] d2[/]src[/]lib.rs [..] \
+ -L /path/to/{host}`", host = host))
+ .with_stderr_contains(&format!("\
+[COMPILING] foo v0.0.0 ({url})", url = p.url()))
+ .with_stderr_contains(&format!("\
+[RUNNING] `rustc [..] build.rs [..] --out-dir {dir}[/]target[/]debug[/]build[/]foo-[..] \
+ -L /path/to/{host}`", dir = p.root().display(), host = host))
+ .with_stderr_contains(&format!("\
+[RUNNING] `rustc [..] src[/]main.rs [..] --target {target} [..] \
+ -L /path/to/{target}`", target = target)));
+}
+
+#[test]
+fn build_deps_for_the_right_arch() {
+ if cross_compile::disabled() { return }
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.0"
+ authors = []
+
+ [dependencies.d2]
+ path = "d2"
+ "#)
+ .file("src/main.rs", "extern crate d2; fn main() {}")
+ .file("d1/Cargo.toml", r#"
+ [package]
+ name = "d1"
+ version = "0.0.0"
+ authors = []
+ "#)
+ .file("d1/src/lib.rs", "
+ pub fn d1() {}
+ ")
+ .file("d2/Cargo.toml", r#"
+ [package]
+ name = "d2"
+ version = "0.0.0"
+ authors = []
+ build = "build.rs"
+
+ [build-dependencies.d1]
+ path = "../d1"
+ "#)
+ .file("d2/build.rs", "extern crate d1; fn main() {}")
+ .file("d2/src/lib.rs", "")
+ .build();
+
+ let target = cross_compile::alternate();
+ assert_that(p.cargo("build").arg("--target").arg(&target).arg("-v"),
+ execs().with_status(0));
+}
+
+#[test]
+fn build_script_only_host() {
+ if cross_compile::disabled() { return }
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.0"
+ authors = []
+ build = "build.rs"
+
+ [build-dependencies.d1]
+ path = "d1"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .file("build.rs", "extern crate d1; fn main() {}")
+ .file("d1/Cargo.toml", r#"
+ [package]
+ name = "d1"
+ version = "0.0.0"
+ authors = []
+ build = "build.rs"
+ "#)
+ .file("d1/src/lib.rs", "
+ pub fn d1() {}
+ ")
+ .file("d1/build.rs", r#"
+ use std::env;
+
+ fn main() {
+ assert!(env::var("OUT_DIR").unwrap().replace("\\", "/")
+ .contains("target/debug/build/d1-"),
+ "bad: {:?}", env::var("OUT_DIR"));
+ }
+ "#)
+ .build();
+
+ let target = cross_compile::alternate();
+ assert_that(p.cargo("build").arg("--target").arg(&target).arg("-v"),
+ execs().with_status(0));
+}
+
+#[test]
+fn plugin_build_script_right_arch() {
+ if cross_compile::disabled() { return }
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ build = "build.rs"
+
+ [lib]
+ name = "foo"
+ plugin = true
+ "#)
+ .file("build.rs", "fn main() {}")
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build").arg("-v").arg("--target").arg(cross_compile::alternate()),
+ execs().with_status(0)
+ .with_stderr("\
+[COMPILING] foo v0.0.1 ([..])
+[RUNNING] `rustc [..] build.rs [..]`
+[RUNNING] `[..][/]build-script-build`
+[RUNNING] `rustc [..] src[/]lib.rs [..]`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+}
+
+#[test]
+fn build_script_with_platform_specific_dependencies() {
+ if cross_compile::disabled() { return }
+
+ let target = cross_compile::alternate();
+ let host = rustc_host();
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ build = "build.rs"
+
+ [build-dependencies.d1]
+ path = "d1"
+ "#)
+ .file("build.rs", "
+ #[allow(unused_extern_crates)]
+ extern crate d1;
+ fn main() {}
+ ")
+ .file("src/lib.rs", "")
+ .file("d1/Cargo.toml", &format!(r#"
+ [package]
+ name = "d1"
+ version = "0.0.0"
+ authors = []
+
+ [target.{}.dependencies]
+ d2 = {{ path = "../d2" }}
+ "#, host))
+ .file("d1/src/lib.rs", "
+ #[allow(unused_extern_crates)]
+ extern crate d2;
+ ")
+ .file("d2/Cargo.toml", r#"
+ [package]
+ name = "d2"
+ version = "0.0.0"
+ authors = []
+ "#)
+ .file("d2/src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build").arg("-v").arg("--target").arg(&target),
+ execs().with_status(0)
+ .with_stderr(&format!("\
+[COMPILING] d2 v0.0.0 ([..])
+[RUNNING] `rustc [..] d2[/]src[/]lib.rs [..]`
+[COMPILING] d1 v0.0.0 ([..])
+[RUNNING] `rustc [..] d1[/]src[/]lib.rs [..]`
+[COMPILING] foo v0.0.1 ([..])
+[RUNNING] `rustc [..] build.rs [..]`
+[RUNNING] `{dir}[/]target[/]debug[/]build[/]foo-[..][/]build-script-build`
+[RUNNING] `rustc [..] src[/]lib.rs [..] --target {target} [..]`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+", dir = p.root().display(), target = target)));
+}
+
+#[test]
+fn platform_specific_dependencies_do_not_leak() {
+ if cross_compile::disabled() { return }
+
+ let target = cross_compile::alternate();
+ let host = rustc_host();
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ build = "build.rs"
+
+ [dependencies.d1]
+ path = "d1"
+
+ [build-dependencies.d1]
+ path = "d1"
+ "#)
+ .file("build.rs", "extern crate d1; fn main() {}")
+ .file("src/lib.rs", "")
+ .file("d1/Cargo.toml", &format!(r#"
+ [package]
+ name = "d1"
+ version = "0.0.0"
+ authors = []
+
+ [target.{}.dependencies]
+ d2 = {{ path = "../d2" }}
+ "#, host))
+ .file("d1/src/lib.rs", "extern crate d2;")
+ .file("d2/Cargo.toml", r#"
+ [package]
+ name = "d2"
+ version = "0.0.0"
+ authors = []
+ "#)
+ .file("d2/src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build").arg("-v").arg("--target").arg(&target),
+ execs().with_status(101)
+ .with_stderr_contains("\
+[..] can't find crate for `d2`[..]"));
+}
+
+#[test]
+fn platform_specific_variables_reflected_in_build_scripts() {
+ if cross_compile::disabled() { return }
+
+ let target = cross_compile::alternate();
+ let host = rustc_host();
+ let p = project("foo")
+ .file("Cargo.toml", &format!(r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ build = "build.rs"
+
+ [target.{host}.dependencies]
+ d1 = {{ path = "d1" }}
+
+ [target.{target}.dependencies]
+ d2 = {{ path = "d2" }}
+ "#, host = host, target = target))
+ .file("build.rs", &format!(r#"
+ use std::env;
+
+ fn main() {{
+ let platform = env::var("TARGET").unwrap();
+ let (expected, not_expected) = match &platform[..] {{
+ "{host}" => ("DEP_D1_VAL", "DEP_D2_VAL"),
+ "{target}" => ("DEP_D2_VAL", "DEP_D1_VAL"),
+ _ => panic!("unknown platform")
+ }};
+
+ env::var(expected).ok()
+ .expect(&format!("missing {{}}", expected));
+ env::var(not_expected).err()
+ .expect(&format!("found {{}}", not_expected));
+ }}
+ "#, host = host, target = target))
+ .file("src/lib.rs", "")
+ .file("d1/Cargo.toml", r#"
+ [package]
+ name = "d1"
+ version = "0.0.0"
+ authors = []
+ links = "d1"
+ build = "build.rs"
+ "#)
+ .file("d1/build.rs", r#"
+ fn main() { println!("cargo:val=1") }
+ "#)
+ .file("d1/src/lib.rs", "")
+ .file("d2/Cargo.toml", r#"
+ [package]
+ name = "d2"
+ version = "0.0.0"
+ authors = []
+ links = "d2"
+ build = "build.rs"
+ "#)
+ .file("d2/build.rs", r#"
+ fn main() { println!("cargo:val=1") }
+ "#)
+ .file("d2/src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build").arg("-v"), execs().with_status(0));
+ assert_that(p.cargo("build").arg("-v").arg("--target").arg(&target),
+ execs().with_status(0));
+}
+
+#[test]
+fn cross_test_dylib() {
+ if cross_compile::disabled() { return }
+
+ let target = cross_compile::alternate();
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [lib]
+ name = "foo"
+ crate_type = ["dylib"]
+
+ [dependencies.bar]
+ path = "bar"
+ "#)
+ .file("src/lib.rs", r#"
+ extern crate bar as the_bar;
+
+ pub fn bar() { the_bar::baz(); }
+
+ #[test]
+ fn foo() { bar(); }
+ "#)
+ .file("tests/test.rs", r#"
+ extern crate foo as the_foo;
+
+ #[test]
+ fn foo() { the_foo::bar(); }
+ "#)
+ .file("bar/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+
+ [lib]
+ name = "bar"
+ crate_type = ["dylib"]
+ "#)
+ .file("bar/src/lib.rs", &format!(r#"
+ use std::env;
+ pub fn baz() {{
+ assert_eq!(env::consts::ARCH, "{}");
+ }}
+ "#, cross_compile::alternate_arch()))
+ .build();
+
+ assert_that(p.cargo("test").arg("--target").arg(&target),
+ execs().with_status(0)
+ .with_stderr(&format!("\
+[COMPILING] bar v0.0.1 ({dir}/bar)
+[COMPILING] foo v0.0.1 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] target[/]{arch}[/]debug[/]deps[/]foo-[..][EXE]
+[RUNNING] target[/]{arch}[/]debug[/]deps[/]test-[..][EXE]",
+ dir = p.url(), arch = cross_compile::alternate()))
+ .with_stdout_contains_n("test foo ... ok", 2));
+
+}
--- /dev/null
+use std::fs::File;
+use std::path::PathBuf;
+use std::io::prelude::*;
+
+use cargotest::support::{project, execs, cross_compile, publish};
+use hamcrest::{assert_that, contains};
+use flate2::read::GzDecoder;
+use tar::Archive;
+
+#[test]
+fn simple_cross_package() {
+ if cross_compile::disabled() { return }
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.0"
+ authors = []
+ license = "MIT"
+ description = "foo"
+ repository = "bar"
+ "#)
+ .file("src/main.rs", &format!(r#"
+ use std::env;
+ fn main() {{
+ assert_eq!(env::consts::ARCH, "{}");
+ }}
+ "#, cross_compile::alternate_arch()))
+ .build();
+
+ let target = cross_compile::alternate();
+
+ assert_that(p.cargo("package").arg("--target").arg(&target),
+ execs().with_status(0).with_status(0).with_stderr(&format!(
+" Packaging foo v0.0.0 ({dir})
+ Verifying foo v0.0.0 ({dir})
+ Compiling foo v0.0.0 ({dir}/target/package/foo-0.0.0)
+ Finished dev [unoptimized + debuginfo] target(s) in [..]
+", dir = p.url())));
+
+ // Check that the tarball contains the files
+ let f = File::open(&p.root().join("target/package/foo-0.0.0.crate")).unwrap();
+ let mut rdr = GzDecoder::new(f);
+ let mut contents = Vec::new();
+ rdr.read_to_end(&mut contents).unwrap();
+ let mut ar = Archive::new(&contents[..]);
+ let entries = ar.entries().unwrap();
+ let entry_paths = entries.map(|entry| {
+ entry.unwrap().path().unwrap().into_owned()
+ }).collect::<Vec<PathBuf>>();
+ assert_that(&entry_paths, contains(vec![PathBuf::from("foo-0.0.0/Cargo.toml")]));
+ assert_that(&entry_paths, contains(vec![PathBuf::from("foo-0.0.0/Cargo.toml.orig")]));
+ assert_that(&entry_paths, contains(vec![PathBuf::from("foo-0.0.0/src/main.rs")]));
+}
+
+#[test]
+fn publish_with_target() {
+ if cross_compile::disabled() { return }
+
+ publish::setup();
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.0"
+ authors = []
+ license = "MIT"
+ description = "foo"
+ repository = "bar"
+ "#)
+ .file("src/main.rs", &format!(r#"
+ use std::env;
+ fn main() {{
+ assert_eq!(env::consts::ARCH, "{}");
+ }}
+ "#, cross_compile::alternate_arch()))
+ .build();
+
+ let target = cross_compile::alternate();
+
+ assert_that(p.cargo("publish")
+ .arg("--index").arg(publish::registry().to_string())
+ .arg("--target").arg(&target),
+ execs().with_status(0).with_stderr(&format!(
+" Updating registry `{registry}`
+ Packaging foo v0.0.0 ({dir})
+ Verifying foo v0.0.0 ({dir})
+ Compiling foo v0.0.0 ({dir}/target/package/foo-0.0.0)
+ Finished dev [unoptimized + debuginfo] target(s) in [..]
+ Uploading foo v0.0.0 ({dir})
+", dir = p.url(), registry = publish::registry())));
+}
--- /dev/null
+use std::fs;
+use std::io::{self, Read};
+use std::net::TcpListener;
+use std::process::{Stdio, Child};
+use std::thread;
+use std::time::Duration;
+
+use cargotest::support::project;
+
+#[cfg(unix)]
+fn enabled() -> bool {
+ true
+}
+
+// On Windows support for these tests is only enabled through the usage of job
+// objects. Support for nested job objects, however, was added in recent-ish
+// versions of Windows, so this test may not always be able to succeed.
+//
+// As a result, we try to add ourselves to a job object here
+// can succeed or not.
+#[cfg(windows)]
+fn enabled() -> bool {
+ use winapi::um::{handleapi, jobapi, jobapi2, processthreadsapi};
+
+ unsafe {
+ // If we're not currently in a job, then we can definitely run these
+ // tests.
+ let me = processthreadsapi::GetCurrentProcess();
+ let mut ret = 0;
+ let r = jobapi::IsProcessInJob(me, 0 as *mut _, &mut ret);
+ assert!(r != 0);
+ if ret == winapi::shared::minwindef::FALSE {
+ return true
+ }
+
+ // If we are in a job, then we can run these tests if we can be added to
+ // a nested job (as we're going to create a nested job no matter what as
+ // part of these tests.
+ //
+ // If we can't be added to a nested job, then these tests will
+ // definitely fail, and there's not much we can do about that.
+ let job = jobapi2::CreateJobObjectW(0 as *mut _, 0 as *const _);
+ assert!(!job.is_null());
+ let r = jobapi2::AssignProcessToJobObject(job, me);
+ handleapi::CloseHandle(job);
+ r != 0
+ }
+}
+
+#[test]
+fn ctrl_c_kills_everyone() {
+ if !enabled() {
+ return
+ }
+
+ let listener = TcpListener::bind("127.0.0.1:0").unwrap();
+ let addr = listener.local_addr().unwrap();
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ build = "build.rs"
+ "#)
+ .file("src/lib.rs", "")
+ .file("build.rs", &format!(r#"
+ use std::net::TcpStream;
+ use std::io::Read;
+
+ fn main() {{
+ let mut socket = TcpStream::connect("{}").unwrap();
+ let _ = socket.read(&mut [0; 10]);
+ panic!("that read should never return");
+ }}
+ "#, addr))
+ .build();
+
+ let mut cargo = p.cargo("build").build_command();
+ cargo.stdin(Stdio::piped())
+ .stdout(Stdio::piped())
+ .stderr(Stdio::piped())
+ .env("__CARGO_TEST_SETSID_PLEASE_DONT_USE_ELSEWHERE", "1");
+ let mut child = cargo.spawn().unwrap();
+
+ let mut sock = listener.accept().unwrap().0;
+ ctrl_c(&mut child);
+
+ assert!(!child.wait().unwrap().success());
+ match sock.read(&mut [0; 10]) {
+ Ok(n) => assert_eq!(n, 0),
+ Err(e) => assert_eq!(e.kind(), io::ErrorKind::ConnectionReset),
+ }
+
+ // Ok so what we just did was spawn cargo that spawned a build script, then
+ // we killed cargo in hopes of it killing the build script as well. If all
+ // went well the build script is now dead. On Windows, however, this is
+ // enforced with job objects which means that it may actually be in the
+ // *process* of being torn down at this point.
+ //
+ // Now on Windows we can't completely remove a file until all handles to it
+ // have been closed. Including those that represent running processes. So if
+ // we were to return here then there may still be an open reference to some
+ // file in the build directory. What we want to actually do is wait for the
+ // build script to *complete* exit. Take care of that by blowing away the
+ // build directory here, and panicking if we eventually spin too long
+ // without being able to.
+ for i in 0..10 {
+ match fs::remove_dir_all(&p.root().join("target")) {
+ Ok(()) => return,
+ Err(e) => println!("attempt {}: {}", i, e),
+ }
+ thread::sleep(Duration::from_millis(100));
+ }
+
+ panic!("couldn't remove build directory after a few tries, seems like \
+ we won't be able to!");
+}
+
+#[cfg(unix)]
+fn ctrl_c(child: &mut Child) {
+ use libc;
+
+ let r = unsafe { libc::kill(-(child.id() as i32), libc::SIGINT) };
+ if r < 0 {
+ panic!("failed to kill: {}", io::Error::last_os_error());
+ }
+}
+
+#[cfg(windows)]
+fn ctrl_c(child: &mut Child) {
+ child.kill().unwrap();
+}
--- /dev/null
+use cargotest::support::{basic_bin_manifest, main_file, execs, project};
+use hamcrest::{assert_that, existing_file};
+
+#[test]
+fn build_dep_info() {
+ let p = project("foo")
+ .file("Cargo.toml", &basic_bin_manifest("foo"))
+ .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
+ .build();
+
+ assert_that(p.cargo("build"), execs().with_status(0));
+
+ let depinfo_bin_path = &p.bin("foo").with_extension("d");
+
+ assert_that(depinfo_bin_path, existing_file());
+}
+
+#[test]
+fn build_dep_info_lib() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [[example]]
+ name = "ex"
+ crate-type = ["lib"]
+ "#)
+ .file("build.rs", "fn main() {}")
+ .file("src/lib.rs", "")
+ .file("examples/ex.rs", "")
+ .build();
+
+ assert_that(p.cargo("build").arg("--example=ex"), execs().with_status(0));
+ assert_that(&p.example_lib("ex", "lib").with_extension("d"), existing_file());
+}
+
+
+#[test]
+fn build_dep_info_rlib() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [[example]]
+ name = "ex"
+ crate-type = ["rlib"]
+ "#)
+ .file("src/lib.rs", "")
+ .file("examples/ex.rs", "")
+ .build();
+
+ assert_that(p.cargo("build").arg("--example=ex"), execs().with_status(0));
+ assert_that(&p.example_lib("ex", "rlib").with_extension("d"), existing_file());
+}
+
+#[test]
+fn build_dep_info_dylib() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [[example]]
+ name = "ex"
+ crate-type = ["dylib"]
+ "#)
+ .file("src/lib.rs", "")
+ .file("examples/ex.rs", "")
+ .build();
+
+ assert_that(p.cargo("build").arg("--example=ex"), execs().with_status(0));
+ assert_that(&p.example_lib("ex", "dylib").with_extension("d"), existing_file());
+}
--- /dev/null
+use serde_json;
+use std::collections::HashMap;
+use std::fs::{self, File};
+use std::io::prelude::*;
+use std::str;
+
+use cargotest::cargo_process;
+use cargotest::support::git;
+use cargotest::support::paths;
+use cargotest::support::registry::{Package, cksum};
+use cargotest::support::{project, execs, ProjectBuilder};
+use hamcrest::assert_that;
+
+fn setup() {
+ let root = paths::root();
+ t!(fs::create_dir(&root.join(".cargo")));
+ t!(t!(File::create(root.join(".cargo/config"))).write_all(br#"
+ [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(&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 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();
+ }
+}
+
+#[test]
+fn simple() {
+ setup();
+
+ VendorPackage::new("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("src/lib.rs", "pub fn foo() {}")
+ .build();
+
+ let p = project("bar")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+
+ [dependencies]
+ foo = "0.1.0"
+ "#)
+ .file("src/lib.rs", r#"
+ extern crate foo;
+
+ pub fn bar() {
+ foo::foo();
+ }
+ "#)
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr("\
+[COMPILING] foo v0.1.0
+[COMPILING] bar v0.1.0 ([..]bar)
+[FINISHED] [..]
+"));
+}
+
+#[test]
+fn simple_install() {
+ setup();
+
+ VendorPackage::new("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .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"
+ "#)
+ .file("src/main.rs", r#"
+ extern crate foo;
+
+ pub fn main() {
+ foo::foo();
+ }
+ "#)
+ .build();
+
+ assert_that(cargo_process().arg("install").arg("bar"),
+ execs().with_status(0).with_stderr(
+" Installing bar v0.1.0
+ Compiling foo v0.1.0
+ Compiling bar v0.1.0
+ Finished release [optimized] target(s) in [..] secs
+ Installing [..]bar[..]
+warning: be sure to add `[..]` to your PATH to be able to run the installed binaries
+"));
+}
+
+#[test]
+fn simple_install_fail() {
+ setup();
+
+ VendorPackage::new("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .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", r#"
+ extern crate foo;
+
+ pub fn main() {
+ foo::foo();
+ }
+ "#)
+ .build();
+
+ assert_that(cargo_process().arg("install").arg("bar"),
+ execs().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 named `baz` found
+location searched: registry `https://github.com/rust-lang/crates.io-index`
+required by package `bar v0.1.0`
+"));
+}
+
+#[test]
+fn install_without_feature_dep() {
+ setup();
+
+ VendorPackage::new("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .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 = { version = "9.8.7", optional = true }
+
+ [features]
+ wantbaz = ["baz"]
+ "#)
+ .file("src/main.rs", r#"
+ extern crate foo;
+
+ pub fn main() {
+ foo::foo();
+ }
+ "#)
+ .build();
+
+ assert_that(cargo_process().arg("install").arg("bar"),
+ execs().with_status(0).with_stderr(
+" Installing bar v0.1.0
+ Compiling foo v0.1.0
+ Compiling bar v0.1.0
+ Finished release [optimized] target(s) in [..] secs
+ Installing [..]bar[..]
+warning: be sure to add `[..]` to your PATH to be able to run the installed binaries
+"));
+}
+
+#[test]
+fn not_there() {
+ setup();
+
+ let _ = project("index").build();
+
+ let p = project("bar")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+
+ [dependencies]
+ foo = "0.1.0"
+ "#)
+ .file("src/lib.rs", r#"
+ extern crate foo;
+
+ pub fn bar() {
+ foo::foo();
+ }
+ "#)
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101).with_stderr("\
+error: no matching package named `foo` found
+location searched: [..]
+required by package `bar v0.1.0 ([..])`
+"));
+}
+
+#[test]
+fn multiple() {
+ setup();
+
+ VendorPackage::new("foo-0.1.0")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("src/lib.rs", "pub fn foo() {}")
+ .file(".cargo-checksum", "")
+ .build();
+
+ VendorPackage::new("foo-0.2.0")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.2.0"
+ authors = []
+ "#)
+ .file("src/lib.rs", "pub fn foo() {}")
+ .file(".cargo-checksum", "")
+ .build();
+
+ let p = project("bar")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+
+ [dependencies]
+ foo = "0.1.0"
+ "#)
+ .file("src/lib.rs", r#"
+ extern crate foo;
+
+ pub fn bar() {
+ foo::foo();
+ }
+ "#)
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr("\
+[COMPILING] foo v0.1.0
+[COMPILING] bar v0.1.0 ([..]bar)
+[FINISHED] [..]
+"));
+}
+
+#[test]
+fn crates_io_then_directory() {
+ let p = project("bar")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+
+ [dependencies]
+ foo = "0.1.0"
+ "#)
+ .file("src/lib.rs", r#"
+ extern crate foo;
+
+ pub fn bar() {
+ foo::foo();
+ }
+ "#)
+ .build();
+
+ let cksum = Package::new("foo", "0.1.0")
+ .file("src/lib.rs", "pub fn foo() -> u32 { 0 }")
+ .publish();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr("\
+[UPDATING] registry `[..]`
+[DOWNLOADING] foo v0.1.0 ([..])
+[COMPILING] foo v0.1.0
+[COMPILING] bar v0.1.0 ([..]bar)
+[FINISHED] [..]
+"));
+
+ setup();
+
+ let mut v = VendorPackage::new("foo");
+ v.file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ "#);
+ v.file("src/lib.rs", "pub fn foo() -> u32 { 1 }");
+ v.cksum.package = Some(cksum);
+ v.build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr("\
+[COMPILING] foo v0.1.0
+[COMPILING] bar v0.1.0 ([..]bar)
+[FINISHED] [..]
+"));
+}
+
+#[test]
+fn crates_io_then_bad_checksum() {
+ let p = project("bar")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+
+ [dependencies]
+ foo = "0.1.0"
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+
+ Package::new("foo", "0.1.0").publish();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0));
+ setup();
+
+ VendorPackage::new("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101).with_stderr("\
+error: checksum for `foo 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 `foo v0.1.0` is the same as when the lockfile was generated
+
+"));
+}
+
+#[test]
+fn bad_file_checksum() {
+ setup();
+
+ VendorPackage::new("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+
+ let mut f = t!(File::create(paths::root().join("index/foo/src/lib.rs")));
+ t!(f.write_all(b"fn foo() -> u32 { 0 }"));
+
+ let p = project("bar")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+
+ [dependencies]
+ foo = "0.1.0"
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().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 [replace] is used with a forked copy of \
+the source
+"));
+}
+
+#[test]
+fn only_dot_files_ok() {
+ setup();
+
+ VendorPackage::new("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+ VendorPackage::new("bar")
+ .file(".foo", "")
+ .build();
+
+ let p = project("bar")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+
+ [dependencies]
+ foo = "0.1.0"
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"), execs().with_status(0));
+}
+
+#[test]
+fn random_files_ok() {
+ setup();
+
+ VendorPackage::new("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+ VendorPackage::new("bar")
+ .file("foo", "")
+ .file("../test", "")
+ .build();
+
+ let p = project("bar")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+
+ [dependencies]
+ foo = "0.1.0"
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"), execs().with_status(0));
+}
+
+#[test]
+fn git_lock_file_doesnt_change() {
+
+ let git = git::new("git", |p| {
+ p.file("Cargo.toml", r#"
+ [project]
+ name = "git"
+ version = "0.5.0"
+ authors = []
+ "#)
+ .file("src/lib.rs", "")
+ }).unwrap();
+
+ VendorPackage::new("git")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "git"
+ version = "0.5.0"
+ authors = []
+ "#)
+ .file("src/lib.rs", "")
+ .disable_checksum()
+ .build();
+
+ let p = project("bar")
+ .file("Cargo.toml", &format!(r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ git = {{ git = '{0}' }}
+ "#, git.url()))
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"), execs().with_status(0));
+
+ let mut lock1 = String::new();
+ t!(t!(File::open(p.root().join("Cargo.lock"))).read_to_string(&mut lock1));
+
+ let root = paths::root();
+ t!(fs::create_dir(&root.join(".cargo")));
+ t!(t!(File::create(root.join(".cargo/config"))).write_all(&format!(r#"
+ [source.my-git-repo]
+ git = '{}'
+ replace-with = 'my-awesome-local-registry'
+
+ [source.my-awesome-local-registry]
+ directory = 'index'
+ "#, git.url()).as_bytes()));
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0)
+ .with_stderr("\
+[COMPILING] [..]
+[COMPILING] [..]
+[FINISHED] [..]
+"));
+
+ let mut lock2 = String::new();
+ t!(t!(File::open(p.root().join("Cargo.lock"))).read_to_string(&mut lock2));
+ assert!(lock1 == lock2, "lock files changed");
+}
+
+#[test]
+fn git_override_requires_lockfile() {
+ VendorPackage::new("git")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "git"
+ version = "0.5.0"
+ authors = []
+ "#)
+ .file("src/lib.rs", "")
+ .disable_checksum()
+ .build();
+
+ let p = project("bar")
+ .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!(t!(File::create(root.join(".cargo/config"))).write_all(br#"
+ [source.my-git-repo]
+ git = 'https://example.com/'
+ replace-with = 'my-awesome-local-registry'
+
+ [source.my-awesome-local-registry]
+ directory = 'index'
+ "#));
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101)
+ .with_stderr("\
+error: failed to load source for a dependency on `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
+
+"));
+}
--- /dev/null
+use cargotest;
+use std::str;
+use std::fs::{self, File};
+use std::io::Read;
+
+use cargotest::rustc_host;
+use cargotest::support::{project, execs, path2url};
+use cargotest::support::registry::Package;
+use hamcrest::{assert_that, existing_file, existing_dir, is_not};
+use cargo::util::ProcessError;
+
+#[test]
+fn simple() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ build = "build.rs"
+ "#)
+ .file("build.rs", "fn main() {}")
+ .file("src/lib.rs", r#"
+ pub fn foo() {}
+ "#)
+ .build();
+
+ assert_that(p.cargo("doc"),
+ execs().with_status(0).with_stderr(&format!("\
+[..] foo v0.0.1 ({dir})
+[..] foo v0.0.1 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+",
+ dir = path2url(p.root()))));
+ assert_that(&p.root().join("target/doc"), existing_dir());
+ assert_that(&p.root().join("target/doc/foo/index.html"), existing_file());
+}
+
+#[test]
+fn doc_no_libs() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [[bin]]
+ name = "foo"
+ doc = false
+ "#)
+ .file("src/main.rs", r#"
+ bad code
+ "#)
+ .build();
+
+ assert_that(p.cargo("doc"),
+ execs().with_status(0));
+}
+
+#[test]
+fn doc_twice() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/lib.rs", r#"
+ pub fn foo() {}
+ "#)
+ .build();
+
+ assert_that(p.cargo("doc"),
+ execs().with_status(0).with_stderr(&format!("\
+[DOCUMENTING] foo v0.0.1 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+",
+ dir = path2url(p.root()))));
+
+ assert_that(p.cargo("doc"),
+ execs().with_status(0).with_stdout(""))
+}
+
+#[test]
+fn doc_deps() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.bar]
+ path = "bar"
+ "#)
+ .file("src/lib.rs", r#"
+ extern crate bar;
+ pub fn foo() {}
+ "#)
+ .file("bar/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("bar/src/lib.rs", r#"
+ pub fn bar() {}
+ "#)
+ .build();
+
+ assert_that(p.cargo("doc"),
+ execs().with_status(0).with_stderr(&format!("\
+[..] bar v0.0.1 ({dir}/bar)
+[..] bar v0.0.1 ({dir}/bar)
+[DOCUMENTING] foo v0.0.1 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+",
+ dir = path2url(p.root()))));
+
+ assert_that(&p.root().join("target/doc"), existing_dir());
+ assert_that(&p.root().join("target/doc/foo/index.html"), existing_file());
+ assert_that(&p.root().join("target/doc/bar/index.html"), existing_file());
+
+ assert_that(p.cargo("doc")
+ .env("RUST_LOG", "cargo::ops::cargo_rustc::fingerprint"),
+ execs().with_status(0).with_stdout(""));
+
+ assert_that(&p.root().join("target/doc"), existing_dir());
+ assert_that(&p.root().join("target/doc/foo/index.html"), existing_file());
+ assert_that(&p.root().join("target/doc/bar/index.html"), existing_file());
+}
+
+#[test]
+fn doc_no_deps() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.bar]
+ path = "bar"
+ "#)
+ .file("src/lib.rs", r#"
+ extern crate bar;
+ pub fn foo() {}
+ "#)
+ .file("bar/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("bar/src/lib.rs", r#"
+ pub fn bar() {}
+ "#)
+ .build();
+
+ assert_that(p.cargo("doc").arg("--no-deps"),
+ execs().with_status(0).with_stderr(&format!("\
+[COMPILING] bar v0.0.1 ({dir}/bar)
+[DOCUMENTING] foo v0.0.1 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+",
+ dir = path2url(p.root()))));
+
+ assert_that(&p.root().join("target/doc"), existing_dir());
+ assert_that(&p.root().join("target/doc/foo/index.html"), existing_file());
+ assert_that(&p.root().join("target/doc/bar/index.html"), is_not(existing_file()));
+}
+
+#[test]
+fn doc_only_bin() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.bar]
+ path = "bar"
+ "#)
+ .file("src/main.rs", r#"
+ extern crate bar;
+ pub fn foo() {}
+ "#)
+ .file("bar/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("bar/src/lib.rs", r#"
+ pub fn bar() {}
+ "#)
+ .build();
+
+ assert_that(p.cargo("doc").arg("-v"),
+ execs().with_status(0));
+
+ assert_that(&p.root().join("target/doc"), existing_dir());
+ assert_that(&p.root().join("target/doc/bar/index.html"), existing_file());
+ assert_that(&p.root().join("target/doc/foo/index.html"), existing_file());
+}
+
+#[test]
+fn doc_multiple_targets_same_name_lib() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [workspace]
+ members = ["foo", "bar"]
+ "#)
+ .file("foo/Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ [lib]
+ name = "foo_lib"
+ "#)
+ .file("foo/src/lib.rs", "")
+ .file("bar/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.1.0"
+ [lib]
+ name = "foo_lib"
+ "#)
+ .file("bar/src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("doc").arg("--all"),
+ execs()
+ .with_status(101)
+ .with_stderr_contains("[..] library `foo_lib` is specified [..]")
+ .with_stderr_contains("[..] `foo v0.1.0[..]` [..]")
+ .with_stderr_contains("[..] `bar v0.1.0[..]` [..]"));
+}
+
+#[test]
+fn doc_multiple_targets_same_name() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [workspace]
+ members = ["foo", "bar"]
+ "#)
+ .file("foo/Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ [[bin]]
+ name = "foo_lib"
+ path = "src/foo_lib.rs"
+ "#)
+ .file("foo/src/foo_lib.rs", "")
+ .file("bar/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.1.0"
+ [lib]
+ name = "foo_lib"
+ "#)
+ .file("bar/src/lib.rs", "")
+ .build();
+
+ let root = path2url(p.root());
+
+ assert_that(p.cargo("doc").arg("--all"),
+ execs()
+ .with_status(0)
+ .with_stderr_contains(&format!("[DOCUMENTING] foo v0.1.0 ({}/foo)", root))
+ .with_stderr_contains(&format!("[DOCUMENTING] bar v0.1.0 ({}/bar)", root))
+ .with_stderr_contains("[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]"));
+ assert_that(&p.root().join("target/doc"), existing_dir());
+ let doc_file = p.root().join("target/doc/foo_lib/index.html");
+ assert_that(&doc_file, existing_file());
+}
+
+#[test]
+fn doc_multiple_targets_same_name_bin() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [workspace]
+ members = ["foo", "bar"]
+ "#)
+ .file("foo/Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ [[bin]]
+ name = "foo-cli"
+ "#)
+ .file("foo/src/foo-cli.rs", "")
+ .file("bar/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.1.0"
+ [[bin]]
+ name = "foo-cli"
+ "#)
+ .file("bar/src/foo-cli.rs", "")
+ .build();
+
+ assert_that(p.cargo("doc").arg("--all"),
+ execs()
+ .with_status(101)
+ .with_stderr_contains("[..] binary `foo_cli` is specified [..]")
+ .with_stderr_contains("[..] `foo v0.1.0[..]` [..]")
+ .with_stderr_contains("[..] `bar v0.1.0[..]` [..]"));
+}
+
+#[test]
+fn doc_multiple_targets_same_name_undoced() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [workspace]
+ members = ["foo", "bar"]
+ "#)
+ .file("foo/Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ [[bin]]
+ name = "foo-cli"
+ "#)
+ .file("foo/src/foo-cli.rs", "")
+ .file("bar/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.1.0"
+ [[bin]]
+ name = "foo-cli"
+ doc = false
+ "#)
+ .file("bar/src/foo-cli.rs", "")
+ .build();
+
+ assert_that(p.cargo("doc").arg("--all"),
+ execs().with_status(0));
+}
+
+#[test]
+fn doc_lib_bin_same_name_documents_lib() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/main.rs", r#"
+ //! Binary documentation
+ extern crate foo;
+ fn main() {
+ foo::foo();
+ }
+ "#)
+ .file("src/lib.rs", r#"
+ //! Library documentation
+ pub fn foo() {}
+ "#)
+ .build();
+
+ assert_that(p.cargo("doc"),
+ execs().with_status(0).with_stderr(&format!("\
+[DOCUMENTING] foo v0.0.1 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+", dir = path2url(p.root()))));
+ assert_that(&p.root().join("target/doc"), existing_dir());
+ let doc_file = p.root().join("target/doc/foo/index.html");
+ assert_that(&doc_file, existing_file());
+ let mut doc_html = String::new();
+ File::open(&doc_file).unwrap().read_to_string(&mut doc_html).unwrap();
+ assert!(doc_html.contains("Library"));
+ assert!(!doc_html.contains("Binary"));
+}
+
+#[test]
+fn doc_lib_bin_same_name_documents_lib_when_requested() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/main.rs", r#"
+ //! Binary documentation
+ extern crate foo;
+ fn main() {
+ foo::foo();
+ }
+ "#)
+ .file("src/lib.rs", r#"
+ //! Library documentation
+ pub fn foo() {}
+ "#)
+ .build();
+
+ assert_that(p.cargo("doc").arg("--lib"),
+ execs().with_status(0).with_stderr(&format!("\
+[DOCUMENTING] foo v0.0.1 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+", dir = path2url(p.root()))));
+ assert_that(&p.root().join("target/doc"), existing_dir());
+ let doc_file = p.root().join("target/doc/foo/index.html");
+ assert_that(&doc_file, existing_file());
+ let mut doc_html = String::new();
+ File::open(&doc_file).unwrap().read_to_string(&mut doc_html).unwrap();
+ assert!(doc_html.contains("Library"));
+ assert!(!doc_html.contains("Binary"));
+}
+
+#[test]
+fn doc_lib_bin_same_name_documents_named_bin_when_requested() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/main.rs", r#"
+ //! Binary documentation
+ extern crate foo;
+ fn main() {
+ foo::foo();
+ }
+ "#)
+ .file("src/lib.rs", r#"
+ //! Library documentation
+ pub fn foo() {}
+ "#)
+ .build();
+
+ assert_that(p.cargo("doc").arg("--bin").arg("foo"),
+ execs().with_status(0).with_stderr(&format!("\
+[COMPILING] foo v0.0.1 ({dir})
+[DOCUMENTING] foo v0.0.1 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+", dir = path2url(p.root()))));
+ assert_that(&p.root().join("target/doc"), existing_dir());
+ let doc_file = p.root().join("target/doc/foo/index.html");
+ assert_that(&doc_file, existing_file());
+ let mut doc_html = String::new();
+ File::open(&doc_file).unwrap().read_to_string(&mut doc_html).unwrap();
+ assert!(!doc_html.contains("Library"));
+ assert!(doc_html.contains("Binary"));
+}
+
+#[test]
+fn doc_lib_bin_same_name_documents_bins_when_requested() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/main.rs", r#"
+ //! Binary documentation
+ extern crate foo;
+ fn main() {
+ foo::foo();
+ }
+ "#)
+ .file("src/lib.rs", r#"
+ //! Library documentation
+ pub fn foo() {}
+ "#)
+ .build();
+
+ assert_that(p.cargo("doc").arg("--bins"),
+ execs().with_status(0).with_stderr(&format!("\
+[COMPILING] foo v0.0.1 ({dir})
+[DOCUMENTING] foo v0.0.1 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+", dir = path2url(p.root()))));
+ assert_that(&p.root().join("target/doc"), existing_dir());
+ let doc_file = p.root().join("target/doc/foo/index.html");
+ assert_that(&doc_file, existing_file());
+ let mut doc_html = String::new();
+ File::open(&doc_file).unwrap().read_to_string(&mut doc_html).unwrap();
+ assert!(!doc_html.contains("Library"));
+ assert!(doc_html.contains("Binary"));
+}
+
+#[test]
+fn doc_dash_p() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.a]
+ path = "a"
+ "#)
+ .file("src/lib.rs", "extern crate a;")
+ .file("a/Cargo.toml", r#"
+ [package]
+ name = "a"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.b]
+ path = "../b"
+ "#)
+ .file("a/src/lib.rs", "extern crate b;")
+ .file("b/Cargo.toml", r#"
+ [package]
+ name = "b"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("b/src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("doc").arg("-p").arg("a"),
+ execs().with_status(0)
+ .with_stderr("\
+[..] b v0.0.1 (file://[..])
+[..] b v0.0.1 (file://[..])
+[DOCUMENTING] a v0.0.1 (file://[..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+}
+
+#[test]
+fn doc_same_name() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/lib.rs", "")
+ .file("src/bin/main.rs", "fn main() {}")
+ .file("examples/main.rs", "fn main() {}")
+ .file("tests/main.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("doc"),
+ execs().with_status(0));
+}
+
+#[test]
+fn doc_target() {
+ const TARGET: &'static str = "arm-unknown-linux-gnueabihf";
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/lib.rs", r#"
+ #![feature(no_core)]
+ #![no_core]
+
+ extern {
+ pub static A: u32;
+ }
+ "#)
+ .build();
+
+ assert_that(p.cargo("doc").arg("--target").arg(TARGET).arg("--verbose"),
+ execs().with_status(0));
+ assert_that(&p.root().join(&format!("target/{}/doc", TARGET)), existing_dir());
+ assert_that(&p.root().join(&format!("target/{}/doc/foo/index.html", TARGET)), existing_file());
+}
+
+#[test]
+fn target_specific_not_documented() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [target.foo.dependencies]
+ a = { path = "a" }
+ "#)
+ .file("src/lib.rs", "")
+ .file("a/Cargo.toml", r#"
+ [package]
+ name = "a"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("a/src/lib.rs", "not rust")
+ .build();
+
+ assert_that(p.cargo("doc"),
+ execs().with_status(0));
+}
+
+#[test]
+fn output_not_captured() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ a = { path = "a" }
+ "#)
+ .file("src/lib.rs", "")
+ .file("a/Cargo.toml", r#"
+ [package]
+ name = "a"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("a/src/lib.rs", "
+ /// ```
+ /// ☃
+ /// ```
+ pub fn foo() {}
+ ")
+ .build();
+
+ let error = p.cargo("doc").exec_with_output().err().unwrap();
+ if let Ok(perr) = error.downcast::<ProcessError>() {
+ let output = perr.output.unwrap();
+ let stderr = str::from_utf8(&output.stderr).unwrap();
+
+ assert!(stderr.contains("☃"), "no snowman\n{}", stderr);
+ assert!(stderr.contains("unknown start of token"), "no message{}", stderr);
+ } else {
+ assert!(false, "an error kind other than ProcessErrorKind was encountered");
+ }
+}
+
+#[test]
+fn target_specific_documented() {
+ let p = project("foo")
+ .file("Cargo.toml", &format!(r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [target.foo.dependencies]
+ a = {{ path = "a" }}
+ [target.{}.dependencies]
+ a = {{ path = "a" }}
+ "#, rustc_host()))
+ .file("src/lib.rs", "
+ extern crate a;
+
+ /// test
+ pub fn foo() {}
+ ")
+ .file("a/Cargo.toml", r#"
+ [package]
+ name = "a"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("a/src/lib.rs", "
+ /// test
+ pub fn foo() {}
+ ")
+ .build();
+
+ assert_that(p.cargo("doc"),
+ execs().with_status(0));
+}
+
+#[test]
+fn no_document_build_deps() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [build-dependencies]
+ a = { path = "a" }
+ "#)
+ .file("src/lib.rs", "
+ pub fn foo() {}
+ ")
+ .file("a/Cargo.toml", r#"
+ [package]
+ name = "a"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("a/src/lib.rs", "
+ /// ```
+ /// ☃
+ /// ```
+ pub fn foo() {}
+ ")
+ .build();
+
+ assert_that(p.cargo("doc"),
+ execs().with_status(0));
+}
+
+#[test]
+fn doc_release() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build").arg("--release"),
+ execs().with_status(0));
+ assert_that(p.cargo("doc").arg("--release").arg("-v"),
+ execs().with_status(0)
+ .with_stderr("\
+[DOCUMENTING] foo v0.0.1 ([..])
+[RUNNING] `rustdoc [..] src[/]lib.rs [..]`
+[FINISHED] release [optimized] target(s) in [..]
+"));
+}
+
+#[test]
+fn doc_multiple_deps() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.bar]
+ path = "bar"
+
+ [dependencies.baz]
+ path = "baz"
+ "#)
+ .file("src/lib.rs", r#"
+ extern crate bar;
+ pub fn foo() {}
+ "#)
+ .file("bar/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("bar/src/lib.rs", r#"
+ pub fn bar() {}
+ "#)
+ .file("baz/Cargo.toml", r#"
+ [package]
+ name = "baz"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("baz/src/lib.rs", r#"
+ pub fn baz() {}
+ "#)
+ .build();
+
+ assert_that(p.cargo("doc")
+ .arg("-p").arg("bar")
+ .arg("-p").arg("baz")
+ .arg("-v"),
+ execs().with_status(0));
+
+ assert_that(&p.root().join("target/doc"), existing_dir());
+ assert_that(&p.root().join("target/doc/bar/index.html"), existing_file());
+ assert_that(&p.root().join("target/doc/baz/index.html"), existing_file());
+}
+
+#[test]
+fn features() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.bar]
+ path = "bar"
+
+ [features]
+ foo = ["bar/bar"]
+ "#)
+ .file("src/lib.rs", r#"
+ #[cfg(feature = "foo")]
+ pub fn foo() {}
+ "#)
+ .file("bar/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+
+ [features]
+ bar = []
+ "#)
+ .file("bar/build.rs", r#"
+ fn main() {
+ println!("cargo:rustc-cfg=bar");
+ }
+ "#)
+ .file("bar/src/lib.rs", r#"
+ #[cfg(feature = "bar")]
+ pub fn bar() {}
+ "#)
+ .build();
+ assert_that(p.cargo("doc").arg("--features").arg("foo"),
+ execs().with_status(0));
+ assert_that(&p.root().join("target/doc"), existing_dir());
+ assert_that(&p.root().join("target/doc/foo/fn.foo.html"), existing_file());
+ assert_that(&p.root().join("target/doc/bar/fn.bar.html"), existing_file());
+}
+
+#[test]
+fn rerun_when_dir_removed() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/lib.rs", r#"
+ /// dox
+ pub fn foo() {}
+ "#)
+ .build();
+
+ assert_that(p.cargo("doc"),
+ execs().with_status(0));
+ assert_that(&p.root().join("target/doc/foo/index.html"), existing_file());
+
+ fs::remove_dir_all(p.root().join("target/doc/foo")).unwrap();
+
+ assert_that(p.cargo("doc"),
+ execs().with_status(0));
+ assert_that(&p.root().join("target/doc/foo/index.html"), existing_file());
+}
+
+#[test]
+fn document_only_lib() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/lib.rs", r#"
+ /// dox
+ pub fn foo() {}
+ "#)
+ .file("src/bin/bar.rs", r#"
+ /// ```
+ /// ☃
+ /// ```
+ pub fn foo() {}
+ fn main() { foo(); }
+ "#)
+ .build();
+ assert_that(p.cargo("doc").arg("--lib"),
+ execs().with_status(0));
+ assert_that(&p.root().join("target/doc/foo/index.html"), existing_file());
+}
+
+#[test]
+fn plugins_no_use_target() {
+ if !cargotest::is_nightly() {
+ return
+ }
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [lib]
+ proc-macro = true
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+ assert_that(p.cargo("doc")
+ .arg("--target=x86_64-unknown-openbsd")
+ .arg("-v"),
+ execs().with_status(0));
+}
+
+#[test]
+fn doc_all_workspace() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+
+ [dependencies]
+ bar = { path = "bar" }
+
+ [workspace]
+ "#)
+ .file("src/main.rs", r#"
+ fn main() {}
+ "#)
+ .file("bar/Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.1.0"
+ "#)
+ .file("bar/src/lib.rs", r#"
+ pub fn bar() {}
+ "#)
+ .build();
+
+ // The order in which bar is compiled or documented is not deterministic
+ assert_that(p.cargo("doc")
+ .arg("--all"),
+ execs().with_status(0)
+ .with_stderr_contains("[..] Documenting bar v0.1.0 ([..])")
+ .with_stderr_contains("[..] Compiling bar v0.1.0 ([..])")
+ .with_stderr_contains("[..] Documenting foo v0.1.0 ([..])"));
+}
+
+#[test]
+fn doc_all_virtual_manifest() {
+ let p = project("workspace")
+ .file("Cargo.toml", r#"
+ [workspace]
+ members = ["foo", "bar"]
+ "#)
+ .file("foo/Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+ "#)
+ .file("foo/src/lib.rs", r#"
+ pub fn foo() {}
+ "#)
+ .file("bar/Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.1.0"
+ "#)
+ .file("bar/src/lib.rs", r#"
+ pub fn bar() {}
+ "#)
+ .build();
+
+ // The order in which foo and bar are documented is not guaranteed
+ assert_that(p.cargo("doc")
+ .arg("--all"),
+ execs().with_status(0)
+ .with_stderr_contains("[..] Documenting bar v0.1.0 ([..])")
+ .with_stderr_contains("[..] Documenting foo v0.1.0 ([..])"));
+}
+
+#[test]
+fn doc_virtual_manifest_all_implied() {
+ let p = project("workspace")
+ .file("Cargo.toml", r#"
+ [workspace]
+ members = ["foo", "bar"]
+ "#)
+ .file("foo/Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+ "#)
+ .file("foo/src/lib.rs", r#"
+ pub fn foo() {}
+ "#)
+ .file("bar/Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.1.0"
+ "#)
+ .file("bar/src/lib.rs", r#"
+ pub fn bar() {}
+ "#)
+ .build();
+
+ // The order in which foo and bar are documented is not guaranteed
+ assert_that(p.cargo("doc"),
+ execs().with_status(0)
+ .with_stderr_contains("[..] Documenting bar v0.1.0 ([..])")
+ .with_stderr_contains("[..] Documenting foo v0.1.0 ([..])"));
+}
+
+#[test]
+fn doc_all_member_dependency_same_name() {
+ let p = project("workspace")
+ .file("Cargo.toml", r#"
+ [workspace]
+ members = ["a"]
+ "#)
+ .file("a/Cargo.toml", r#"
+ [project]
+ name = "a"
+ version = "0.1.0"
+
+ [dependencies]
+ a = "0.1.0"
+ "#)
+ .file("a/src/lib.rs", r#"
+ pub fn a() {}
+ "#)
+ .build();
+
+ Package::new("a", "0.1.0").publish();
+
+ assert_that(p.cargo("doc")
+ .arg("--all"),
+ execs().with_status(0)
+ .with_stderr_contains("[..] Updating registry `[..]`")
+ .with_stderr_contains("[..] Documenting a v0.1.0 ([..])"));
+}
+
+#[test]
+fn doc_workspace_open_help_message() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [workspace]
+ members = ["foo", "bar"]
+ "#)
+ .file("foo/Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ "#)
+ .file("foo/src/lib.rs", "")
+ .file("bar/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.1.0"
+ "#)
+ .file("bar/src/lib.rs", "")
+ .build();
+
+ // The order in which bar is compiled or documented is not deterministic
+ assert_that(p.cargo("doc")
+ .arg("--all")
+ .arg("--open"),
+ execs().with_status(101)
+ .with_stderr_contains("[..] Documenting bar v0.1.0 ([..])")
+ .with_stderr_contains("[..] Documenting foo v0.1.0 ([..])")
+ .with_stderr_contains("error: Passing multiple packages and `open` is not supported.")
+ .with_stderr_contains("Please re-run this command with `-p <spec>` where `<spec>` is one of the following:")
+ .with_stderr_contains(" foo")
+ .with_stderr_contains(" bar"));
+}
--- /dev/null
+use std::fs::File;
+use std::io::prelude::*;
+
+use cargotest::support::paths::CargoPathExt;
+use cargotest::support::{project, execs};
+use hamcrest::assert_that;
+
+#[test]
+fn invalid1() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [features]
+ bar = ["baz"]
+ "#)
+ .file("src/main.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101).with_stderr("\
+[ERROR] failed to parse manifest at `[..]`
+
+Caused by:
+ Feature `bar` includes `baz` which is neither a dependency nor another feature
+"));
+}
+
+#[test]
+fn invalid2() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [features]
+ bar = ["baz"]
+
+ [dependencies.bar]
+ path = "foo"
+ "#)
+ .file("src/main.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101).with_stderr("\
+[ERROR] failed to parse manifest at `[..]`
+
+Caused by:
+ Features and dependencies cannot have the same name: `bar`
+"));
+}
+
+#[test]
+fn invalid3() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [features]
+ bar = ["baz"]
+
+ [dependencies.baz]
+ path = "foo"
+ "#)
+ .file("src/main.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101).with_stderr("\
+[ERROR] failed to parse manifest at `[..]`
+
+Caused by:
+ Feature `bar` depends on `baz` which is not an optional dependency.
+Consider adding `optional = true` to the dependency
+"));
+}
+
+#[test]
+fn invalid4() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.bar]
+ path = "bar"
+ features = ["bar"]
+ "#)
+ .file("src/main.rs", "")
+ .file("bar/Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("bar/src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101).with_stderr("\
+[ERROR] Package `bar v0.0.1 ([..])` does not have these features: `bar`
+"));
+
+ p.change_file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#);
+
+ assert_that(p.cargo("build").arg("--features").arg("test"),
+ execs().with_status(101).with_stderr("\
+[ERROR] Package `foo v0.0.1 ([..])` does not have these features: `test`
+"));
+}
+
+#[test]
+fn invalid5() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dev-dependencies.bar]
+ path = "bar"
+ optional = true
+ "#)
+ .file("src/main.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101).with_stderr("\
+[ERROR] failed to parse manifest at `[..]`
+
+Caused by:
+ Dev-dependencies are not allowed to be optional: `bar`
+"));
+}
+
+#[test]
+fn invalid6() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [features]
+ foo = ["bar/baz"]
+ "#)
+ .file("src/main.rs", "")
+ .build();
+
+ assert_that(p.cargo("build").arg("--features").arg("foo"),
+ execs().with_status(101).with_stderr("\
+[ERROR] failed to parse manifest at `[..]`
+
+Caused by:
+ Feature `foo` requires a feature of `bar` which is not a dependency
+"));
+}
+
+#[test]
+fn invalid7() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [features]
+ foo = ["bar/baz"]
+ bar = []
+ "#)
+ .file("src/main.rs", "")
+ .build();
+
+ assert_that(p.cargo("build").arg("--features").arg("foo"),
+ execs().with_status(101).with_stderr("\
+[ERROR] failed to parse manifest at `[..]`
+
+Caused by:
+ Feature `foo` requires a feature of `bar` which is not a dependency
+"));
+}
+
+#[test]
+fn invalid8() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.bar]
+ path = "bar"
+ features = ["foo/bar"]
+ "#)
+ .file("src/main.rs", "")
+ .file("bar/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("bar/src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build").arg("--features").arg("foo"),
+ execs().with_status(101).with_stderr("\
+[ERROR] feature names may not contain slashes: `foo/bar`
+"));
+}
+
+#[test]
+fn invalid9() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.bar]
+ path = "bar"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .file("bar/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("bar/src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build").arg("--features").arg("bar"),
+ execs().with_status(0).with_stderr("\
+warning: Package `foo v0.0.1 ([..])` does not have feature `bar`. It has a required dependency with \
+that name, but only optional dependencies can be used as features. [..]
+ Compiling bar v0.0.1 ([..])
+ Compiling foo v0.0.1 ([..])
+ Finished dev [unoptimized + debuginfo] target(s) in [..] secs
+"));
+}
+
+#[test]
+fn invalid10() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.bar]
+ path = "bar"
+ features = ["baz"]
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .file("bar/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.baz]
+ path = "baz"
+ "#)
+ .file("bar/src/lib.rs", "")
+ .file("bar/baz/Cargo.toml", r#"
+ [package]
+ name = "baz"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("bar/baz/src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr("\
+warning: Package `bar v0.0.1 ([..])` does not have feature `baz`. It has a required dependency with \
+that name, but only optional dependencies can be used as features. [..]
+ Compiling baz v0.0.1 ([..])
+ Compiling bar v0.0.1 ([..])
+ Compiling foo v0.0.1 ([..])
+ Finished dev [unoptimized + debuginfo] target(s) in [..] secs
+"));
+}
+
+#[test]
+fn no_transitive_dep_feature_requirement() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.derived]
+ path = "derived"
+
+ [features]
+ default = ["derived/bar/qux"]
+ "#)
+ .file("src/main.rs", r#"
+ extern crate derived;
+ fn main() { derived::test(); }
+ "#)
+ .file("derived/Cargo.toml", r#"
+ [package]
+ name = "derived"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.bar]
+ path = "../bar"
+ "#)
+ .file("derived/src/lib.rs", r#"
+ extern crate bar;
+ pub use bar::test;
+ "#)
+ .file("bar/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+
+ [features]
+ qux = []
+ "#)
+ .file("bar/src/lib.rs", r#"
+ #[cfg(feature = "qux")]
+ pub fn test() { print!("test"); }
+ "#)
+ .build();
+ assert_that(p.cargo("build"),
+ execs().with_status(101).with_stderr("\
+[ERROR] feature names may not contain slashes: `bar/qux`
+"));
+}
+
+#[test]
+fn no_feature_doesnt_build() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.bar]
+ path = "bar"
+ optional = true
+ "#)
+ .file("src/main.rs", r#"
+ #[cfg(feature = "bar")]
+ extern crate bar;
+ #[cfg(feature = "bar")]
+ fn main() { bar::bar(); println!("bar") }
+ #[cfg(not(feature = "bar"))]
+ fn main() {}
+ "#)
+ .file("bar/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("bar/src/lib.rs", "pub fn bar() {}")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr(format!("\
+[COMPILING] foo v0.0.1 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+", dir = p.url())));
+ assert_that(p.process(&p.bin("foo")),
+ execs().with_status(0).with_stdout(""));
+
+ assert_that(p.cargo("build").arg("--features").arg("bar"),
+ execs().with_status(0).with_stderr(format!("\
+[COMPILING] bar v0.0.1 ({dir}/bar)
+[COMPILING] foo v0.0.1 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+", dir = p.url())));
+ assert_that(p.process(&p.bin("foo")),
+ execs().with_status(0).with_stdout("bar\n"));
+}
+
+#[test]
+fn default_feature_pulled_in() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [features]
+ default = ["bar"]
+
+ [dependencies.bar]
+ path = "bar"
+ optional = true
+ "#)
+ .file("src/main.rs", r#"
+ #[cfg(feature = "bar")]
+ extern crate bar;
+ #[cfg(feature = "bar")]
+ fn main() { bar::bar(); println!("bar") }
+ #[cfg(not(feature = "bar"))]
+ fn main() {}
+ "#)
+ .file("bar/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("bar/src/lib.rs", "pub fn bar() {}")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr(format!("\
+[COMPILING] bar v0.0.1 ({dir}/bar)
+[COMPILING] foo v0.0.1 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+", dir = p.url())));
+ assert_that(p.process(&p.bin("foo")),
+ execs().with_status(0).with_stdout("bar\n"));
+
+ assert_that(p.cargo("build").arg("--no-default-features"),
+ execs().with_status(0).with_stderr(format!("\
+[COMPILING] foo v0.0.1 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+", dir = p.url())));
+ assert_that(p.process(&p.bin("foo")),
+ execs().with_status(0).with_stdout(""));
+}
+
+#[test]
+fn cyclic_feature() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [features]
+ default = ["default"]
+ "#)
+ .file("src/main.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101).with_stderr("\
+[ERROR] Cyclic feature dependency: feature `default` depends on itself
+"));
+}
+
+#[test]
+fn cyclic_feature2() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [features]
+ foo = ["bar"]
+ bar = ["foo"]
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stdout(""));
+}
+
+#[test]
+fn groups_on_groups_on_groups() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [features]
+ default = ["f1"]
+ f1 = ["f2", "bar"]
+ f2 = ["f3", "f4"]
+ f3 = ["f5", "f6", "baz"]
+ f4 = ["f5", "f7"]
+ f5 = ["f6"]
+ f6 = ["f7"]
+ f7 = ["bar"]
+
+ [dependencies.bar]
+ path = "bar"
+ optional = true
+
+ [dependencies.baz]
+ path = "baz"
+ optional = true
+ "#)
+ .file("src/main.rs", r#"
+ #[allow(unused_extern_crates)]
+ extern crate bar;
+ #[allow(unused_extern_crates)]
+ extern crate baz;
+ fn main() {}
+ "#)
+ .file("bar/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("bar/src/lib.rs", "pub fn bar() {}")
+ .file("baz/Cargo.toml", r#"
+ [package]
+ name = "baz"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("baz/src/lib.rs", "pub fn baz() {}")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr(format!("\
+[COMPILING] ba[..] v0.0.1 ({dir}/ba[..])
+[COMPILING] ba[..] v0.0.1 ({dir}/ba[..])
+[COMPILING] foo v0.0.1 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+", dir = p.url())));
+}
+
+#[test]
+fn many_cli_features() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.bar]
+ path = "bar"
+ optional = true
+
+ [dependencies.baz]
+ path = "baz"
+ optional = true
+ "#)
+ .file("src/main.rs", r#"
+ #[allow(unused_extern_crates)]
+ extern crate bar;
+ #[allow(unused_extern_crates)]
+ extern crate baz;
+ fn main() {}
+ "#)
+ .file("bar/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("bar/src/lib.rs", "pub fn bar() {}")
+ .file("baz/Cargo.toml", r#"
+ [package]
+ name = "baz"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("baz/src/lib.rs", "pub fn baz() {}")
+ .build();
+
+ assert_that(p.cargo("build").arg("--features").arg("bar baz"),
+ execs().with_status(0).with_stderr(format!("\
+[COMPILING] ba[..] v0.0.1 ({dir}/ba[..])
+[COMPILING] ba[..] v0.0.1 ({dir}/ba[..])
+[COMPILING] foo v0.0.1 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+", dir = p.url())));
+}
+
+#[test]
+fn union_features() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.d1]
+ path = "d1"
+ features = ["f1"]
+ [dependencies.d2]
+ path = "d2"
+ features = ["f2"]
+ "#)
+ .file("src/main.rs", r#"
+ #[allow(unused_extern_crates)]
+ extern crate d1;
+ extern crate d2;
+ fn main() {
+ d2::f1();
+ d2::f2();
+ }
+ "#)
+ .file("d1/Cargo.toml", r#"
+ [package]
+ name = "d1"
+ version = "0.0.1"
+ authors = []
+
+ [features]
+ f1 = ["d2"]
+
+ [dependencies.d2]
+ path = "../d2"
+ features = ["f1"]
+ optional = true
+ "#)
+ .file("d1/src/lib.rs", "")
+ .file("d2/Cargo.toml", r#"
+ [package]
+ name = "d2"
+ version = "0.0.1"
+ authors = []
+
+ [features]
+ f1 = []
+ f2 = []
+ "#)
+ .file("d2/src/lib.rs", r#"
+ #[cfg(feature = "f1")] pub fn f1() {}
+ #[cfg(feature = "f2")] pub fn f2() {}
+ "#)
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr(format!("\
+[COMPILING] d2 v0.0.1 ({dir}/d2)
+[COMPILING] d1 v0.0.1 ({dir}/d1)
+[COMPILING] foo v0.0.1 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+", dir = p.url())));
+}
+
+#[test]
+fn many_features_no_rebuilds() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "b"
+ version = "0.1.0"
+ authors = []
+
+ [dependencies.a]
+ path = "a"
+ features = ["fall"]
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .file("a/Cargo.toml", r#"
+ [package]
+ name = "a"
+ version = "0.1.0"
+ authors = []
+
+ [features]
+ ftest = []
+ ftest2 = []
+ fall = ["ftest", "ftest2"]
+ "#)
+ .file("a/src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr(format!("\
+[COMPILING] a v0.1.0 ({dir}/a)
+[COMPILING] b v0.1.0 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+", dir = p.url())));
+ p.root().move_into_the_past();
+
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(0).with_stderr("\
+[FRESH] a v0.1.0 ([..]/a)
+[FRESH] b v0.1.0 ([..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+}
+
+// Tests that all cmd lines work with `--features ""`
+#[test]
+fn empty_features() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("build").arg("--features").arg(""),
+ execs().with_status(0));
+}
+
+// Tests that all cmd lines work with `--features ""`
+#[test]
+fn transitive_features() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [features]
+ foo = ["bar/baz"]
+
+ [dependencies.bar]
+ path = "bar"
+ "#)
+ .file("src/main.rs", "
+ extern crate bar;
+ fn main() { bar::baz(); }
+ ")
+ .file("bar/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+
+ [features]
+ baz = []
+ "#)
+ .file("bar/src/lib.rs", r#"
+ #[cfg(feature = "baz")]
+ pub fn baz() {}
+ "#)
+ .build();
+
+ assert_that(p.cargo("build").arg("--features").arg("foo"),
+ execs().with_status(0));
+}
+
+#[test]
+fn everything_in_the_lockfile() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [features]
+ f1 = ["d1/f1"]
+ f2 = ["d2"]
+
+ [dependencies.d1]
+ path = "d1"
+ [dependencies.d2]
+ path = "d2"
+ optional = true
+ [dependencies.d3]
+ path = "d3"
+ optional = true
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .file("d1/Cargo.toml", r#"
+ [package]
+ name = "d1"
+ version = "0.0.1"
+ authors = []
+
+ [features]
+ f1 = []
+ "#)
+ .file("d1/src/lib.rs", "")
+ .file("d2/Cargo.toml", r#"
+ [package]
+ name = "d2"
+ version = "0.0.2"
+ authors = []
+ "#)
+ .file("d2/src/lib.rs", "")
+ .file("d3/Cargo.toml", r#"
+ [package]
+ name = "d3"
+ version = "0.0.3"
+ authors = []
+
+ [features]
+ f3 = []
+ "#)
+ .file("d3/src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("fetch"), execs().with_status(0));
+ let loc = p.root().join("Cargo.lock");
+ let mut lockfile = String::new();
+ t!(t!(File::open(&loc)).read_to_string(&mut lockfile));
+ assert!(lockfile.contains(r#"name = "d1""#), "d1 not found\n{}", lockfile);
+ assert!(lockfile.contains(r#"name = "d2""#), "d2 not found\n{}", lockfile);
+ assert!(lockfile.contains(r#"name = "d3""#), "d3 not found\n{}", lockfile);
+}
+
+#[test]
+fn no_rebuild_when_frobbing_default_feature() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+
+ [dependencies]
+ a = { path = "a" }
+ b = { path = "b" }
+ "#)
+ .file("src/lib.rs", "")
+ .file("b/Cargo.toml", r#"
+ [package]
+ name = "b"
+ version = "0.1.0"
+ authors = []
+
+ [dependencies]
+ a = { path = "../a", features = ["f1"], default-features = false }
+ "#)
+ .file("b/src/lib.rs", "")
+ .file("a/Cargo.toml", r#"
+ [package]
+ name = "a"
+ version = "0.1.0"
+ authors = []
+
+ [features]
+ default = ["f1"]
+ f1 = []
+ "#)
+ .file("a/src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"), execs().with_status(0));
+ assert_that(p.cargo("build"), execs().with_status(0).with_stdout(""));
+ assert_that(p.cargo("build"), execs().with_status(0).with_stdout(""));
+}
+
+#[test]
+fn unions_work_with_no_default_features() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+
+ [dependencies]
+ a = { path = "a" }
+ b = { path = "b" }
+ "#)
+ .file("src/lib.rs", r#"
+ extern crate a;
+ pub fn foo() { a::a(); }
+ "#)
+ .file("b/Cargo.toml", r#"
+ [package]
+ name = "b"
+ version = "0.1.0"
+ authors = []
+
+ [dependencies]
+ a = { path = "../a", features = [], default-features = false }
+ "#)
+ .file("b/src/lib.rs", "")
+ .file("a/Cargo.toml", r#"
+ [package]
+ name = "a"
+ version = "0.1.0"
+ authors = []
+
+ [features]
+ default = ["f1"]
+ f1 = []
+ "#)
+ .file("a/src/lib.rs", r#"
+ #[cfg(feature = "f1")]
+ pub fn a() {}
+ "#)
+ .build();
+
+ assert_that(p.cargo("build"), execs().with_status(0));
+ assert_that(p.cargo("build"), execs().with_status(0).with_stdout(""));
+ assert_that(p.cargo("build"), execs().with_status(0).with_stdout(""));
+}
+
+#[test]
+fn optional_and_dev_dep() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "test"
+ version = "0.1.0"
+ authors = []
+
+ [dependencies]
+ foo = { path = "foo", optional = true }
+ [dev-dependencies]
+ foo = { path = "foo" }
+ "#)
+ .file("src/lib.rs", "")
+ .file("foo/Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("foo/src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr("\
+[COMPILING] test v0.1.0 ([..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+}
+
+#[test]
+fn activating_feature_activates_dep() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "test"
+ version = "0.1.0"
+ authors = []
+
+ [dependencies]
+ foo = { path = "foo", optional = true }
+
+ [features]
+ a = ["foo/a"]
+ "#)
+ .file("src/lib.rs", "
+ extern crate foo;
+ pub fn bar() {
+ foo::bar();
+ }
+ ")
+ .file("foo/Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+
+ [features]
+ a = []
+ "#)
+ .file("foo/src/lib.rs", r#"
+ #[cfg(feature = "a")]
+ pub fn bar() {}
+ "#)
+ .build();
+
+ assert_that(p.cargo("build").arg("--features").arg("a").arg("-v"),
+ execs().with_status(0));
+}
+
+#[test]
+fn dep_feature_in_cmd_line() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.derived]
+ path = "derived"
+ "#)
+ .file("src/main.rs", r#"
+ extern crate derived;
+ fn main() { derived::test(); }
+ "#)
+ .file("derived/Cargo.toml", r#"
+ [package]
+ name = "derived"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.bar]
+ path = "../bar"
+
+ [features]
+ default = []
+ derived-feat = ["bar/some-feat"]
+ "#)
+ .file("derived/src/lib.rs", r#"
+ extern crate bar;
+ pub use bar::test;
+ "#)
+ .file("bar/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+
+ [features]
+ some-feat = []
+ "#)
+ .file("bar/src/lib.rs", r#"
+ #[cfg(feature = "some-feat")]
+ pub fn test() { print!("test"); }
+ "#)
+ .build();
+
+ // The foo project requires that feature "some-feat" in "bar" is enabled.
+ // Building without any features enabled should fail:
+ assert_that(p.cargo("build"),
+ execs().with_status(101));
+
+ // We should be able to enable the feature "derived-feat", which enables "some-feat",
+ // on the command line. The feature is enabled, thus building should be successful:
+ assert_that(p.cargo("build").arg("--features").arg("derived/derived-feat"),
+ execs().with_status(0));
+
+ // Trying to enable features of transitive dependencies is an error
+ assert_that(p.cargo("build").arg("--features").arg("bar/some-feat"),
+ execs().with_status(101).with_stderr("\
+[ERROR] Package `foo v0.0.1 ([..])` does not have these features: `bar`
+"));
+
+ // Hierarchical feature specification should still be disallowed
+ assert_that(p.cargo("build").arg("--features").arg("derived/bar/some-feat"),
+ execs().with_status(101).with_stderr("\
+[ERROR] feature names may not contain slashes: `bar/some-feat`
+"));
+}
+
+#[test]
+fn all_features_flag_enables_all_features() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [features]
+ foo = []
+ bar = []
+
+ [dependencies.baz]
+ path = "baz"
+ optional = true
+ "#)
+ .file("src/main.rs", r#"
+ #[cfg(feature = "foo")]
+ pub fn foo() {}
+
+ #[cfg(feature = "bar")]
+ pub fn bar() {
+ extern crate baz;
+ baz::baz();
+ }
+
+ fn main() {
+ foo();
+ bar();
+ }
+ "#)
+ .file("baz/Cargo.toml", r#"
+ [package]
+ name = "baz"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("baz/src/lib.rs", "pub fn baz() {}")
+ .build();
+
+ assert_that(p.cargo("build").arg("--all-features"),
+ execs().with_status(0));
+}
+
+#[test]
+fn many_cli_features_comma_delimited() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.bar]
+ path = "bar"
+ optional = true
+
+ [dependencies.baz]
+ path = "baz"
+ optional = true
+ "#)
+ .file("src/main.rs", r#"
+ #[allow(unused_extern_crates)]
+ extern crate bar;
+ #[allow(unused_extern_crates)]
+ extern crate baz;
+ fn main() {}
+ "#)
+ .file("bar/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("bar/src/lib.rs", "pub fn bar() {}")
+ .file("baz/Cargo.toml", r#"
+ [package]
+ name = "baz"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("baz/src/lib.rs", "pub fn baz() {}")
+ .build();
+
+ assert_that(p.cargo("build").arg("--features").arg("bar,baz"),
+ execs().with_status(0).with_stderr(format!("\
+[COMPILING] ba[..] v0.0.1 ({dir}/ba[..])
+[COMPILING] ba[..] v0.0.1 ({dir}/ba[..])
+[COMPILING] foo v0.0.1 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+", dir = p.url())));
+}
+
+#[test]
+fn many_cli_features_comma_and_space_delimited() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.bar]
+ path = "bar"
+ optional = true
+
+ [dependencies.baz]
+ path = "baz"
+ optional = true
+
+ [dependencies.bam]
+ path = "bam"
+ optional = true
+
+ [dependencies.bap]
+ path = "bap"
+ optional = true
+ "#)
+ .file("src/main.rs", r#"
+ #[allow(unused_extern_crates)]
+ extern crate bar;
+ #[allow(unused_extern_crates)]
+ extern crate baz;
+ #[allow(unused_extern_crates)]
+ extern crate bam;
+ #[allow(unused_extern_crates)]
+ extern crate bap;
+ fn main() {}
+ "#)
+ .file("bar/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("bar/src/lib.rs", "pub fn bar() {}")
+ .file("baz/Cargo.toml", r#"
+ [package]
+ name = "baz"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("baz/src/lib.rs", "pub fn baz() {}")
+ .file("bam/Cargo.toml", r#"
+ [package]
+ name = "bam"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("bam/src/lib.rs", "pub fn bam() {}")
+ .file("bap/Cargo.toml", r#"
+ [package]
+ name = "bap"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("bap/src/lib.rs", "pub fn bap() {}")
+ .build();
+
+ assert_that(p.cargo("build").arg("--features").arg("bar,baz bam bap"),
+ execs().with_status(0).with_stderr(format!("\
+[COMPILING] ba[..] v0.0.1 ({dir}/ba[..])
+[COMPILING] ba[..] v0.0.1 ({dir}/ba[..])
+[COMPILING] ba[..] v0.0.1 ({dir}/ba[..])
+[COMPILING] ba[..] v0.0.1 ({dir}/ba[..])
+[COMPILING] foo v0.0.1 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+", dir = p.url())));
+}
--- /dev/null
+use cargotest::support::{project, execs};
+use hamcrest::assert_that;
+
+#[test]
+fn no_deps() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ authors = []
+ version = "0.0.1"
+ "#)
+ .file("src/main.rs", r#"
+ mod a; fn main() {}
+ "#)
+ .file("src/a.rs", "")
+ .build();
+
+ assert_that(p.cargo("fetch"),
+ execs().with_status(0).with_stdout(""));
+}
--- /dev/null
+use std::fs::{self, File};
+use std::io::prelude::*;
+
+use cargotest::sleep_ms;
+use cargotest::support::{project, execs, path2url};
+use cargotest::support::paths::CargoPathExt;
+use hamcrest::{assert_that, existing_file};
+
+#[test]
+fn modifying_and_moving() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ authors = []
+ version = "0.0.1"
+ "#)
+ .file("src/main.rs", r#"
+ mod a; fn main() {}
+ "#)
+ .file("src/a.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr(format!("\
+[COMPILING] foo v0.0.1 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+", dir = path2url(p.root()))));
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stdout(""));
+ p.root().move_into_the_past();
+ p.root().join("target").move_into_the_past();
+
+ File::create(&p.root().join("src/a.rs")).unwrap()
+ .write_all(b"#[allow(unused)]fn main() {}").unwrap();
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr(format!("\
+[COMPILING] foo v0.0.1 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+", dir = path2url(p.root()))));
+
+ fs::rename(&p.root().join("src/a.rs"), &p.root().join("src/b.rs")).unwrap();
+ assert_that(p.cargo("build"),
+ execs().with_status(101));
+}
+
+#[test]
+fn modify_only_some_files() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ authors = []
+ version = "0.0.1"
+ "#)
+ .file("src/lib.rs", "mod a;")
+ .file("src/a.rs", "")
+ .file("src/main.rs", r#"
+ mod b;
+ fn main() {}
+ "#)
+ .file("src/b.rs", "")
+ .file("tests/test.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr(format!("\
+[COMPILING] foo v0.0.1 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+", dir = path2url(p.root()))));
+ assert_that(p.cargo("test"),
+ execs().with_status(0));
+ sleep_ms(1000);
+
+ assert_that(&p.bin("foo"), existing_file());
+
+ let lib = p.root().join("src/lib.rs");
+ let bin = p.root().join("src/b.rs");
+
+ File::create(&lib).unwrap().write_all(b"invalid rust code").unwrap();
+ File::create(&bin).unwrap().write_all(b"#[allow(unused)]fn foo() {}").unwrap();
+ lib.move_into_the_past();
+
+ // Make sure the binary is rebuilt, not the lib
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr(format!("\
+[COMPILING] foo v0.0.1 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+", dir = path2url(p.root()))));
+ assert_that(&p.bin("foo"), existing_file());
+}
+
+#[test]
+fn rebuild_sub_package_then_while_package() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ authors = []
+ version = "0.0.1"
+
+ [dependencies.a]
+ path = "a"
+ [dependencies.b]
+ path = "b"
+ "#)
+ .file("src/lib.rs", "extern crate a; extern crate b;")
+ .file("a/Cargo.toml", r#"
+ [package]
+ name = "a"
+ authors = []
+ version = "0.0.1"
+ [dependencies.b]
+ path = "../b"
+ "#)
+ .file("a/src/lib.rs", "extern crate b;")
+ .file("b/Cargo.toml", r#"
+ [package]
+ name = "b"
+ authors = []
+ version = "0.0.1"
+ "#)
+ .file("b/src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0));
+
+ File::create(&p.root().join("b/src/lib.rs")).unwrap().write_all(br#"
+ pub fn b() {}
+ "#).unwrap();
+
+ assert_that(p.cargo("build").arg("-pb"),
+ execs().with_status(0));
+
+ File::create(&p.root().join("src/lib.rs")).unwrap().write_all(br#"
+ extern crate a;
+ extern crate b;
+ pub fn toplevel() {}
+ "#).unwrap();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0));
+}
+
+#[test]
+fn changing_lib_features_caches_targets() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ authors = []
+ version = "0.0.1"
+
+ [features]
+ foo = []
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0)
+ .with_stderr("\
+[..]Compiling foo v0.0.1 ([..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+
+ assert_that(p.cargo("build").arg("--features").arg("foo"),
+ execs().with_status(0)
+ .with_stderr("\
+[..]Compiling foo v0.0.1 ([..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+
+ /* Targets should be cached from the first build */
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0)
+ .with_stderr("\
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0)
+ .with_stdout(""));
+
+ assert_that(p.cargo("build").arg("--features").arg("foo"),
+ execs().with_status(0)
+ .with_stderr("\
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+}
+
+#[test]
+fn changing_profiles_caches_targets() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ authors = []
+ version = "0.0.1"
+
+ [profile.dev]
+ panic = "abort"
+
+ [profile.test]
+ panic = "unwind"
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0)
+ .with_stderr("\
+[..]Compiling foo v0.0.1 ([..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+
+ assert_that(p.cargo("test"),
+ execs().with_status(0)
+ .with_stderr("\
+[..]Compiling foo v0.0.1 ([..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] target[..]debug[..]deps[..]foo-[..][EXE]
+[DOCTEST] foo
+"));
+
+ /* Targets should be cached from the first build */
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0)
+ .with_stderr("\
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+
+ assert_that(p.cargo("test").arg("foo"),
+ execs().with_status(0)
+ .with_stderr("\
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] target[..]debug[..]deps[..]foo-[..][EXE]
+[DOCTEST] foo
+"));
+}
+
+#[test]
+fn changing_bin_paths_common_target_features_caches_targets() {
+ // Make sure dep_cache crate is built once per feature
+ let p = project("foo")
+ .file(".cargo/config", r#"
+ [build]
+ target-dir = "./target"
+ "#)
+ .file("dep_crate/Cargo.toml", r#"
+ [package]
+ name = "dep_crate"
+ version = "0.0.1"
+ authors = []
+
+ [features]
+ ftest = []
+ "#)
+ .file("dep_crate/src/lib.rs", r#"
+ #[cfg(feature = "ftest")]
+ pub fn yo() {
+ println!("ftest on")
+ }
+ #[cfg(not(feature = "ftest"))]
+ pub fn yo() {
+ println!("ftest off")
+ }
+ "#)
+ .file("a/Cargo.toml", r#"
+ [package]
+ name = "a"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ dep_crate = {path = "../dep_crate", features = []}
+ "#)
+ .file("a/src/lib.rs", "")
+ .file("a/src/main.rs", r#"
+ extern crate dep_crate;
+ use dep_crate::yo;
+ fn main() {
+ yo();
+ }
+ "#)
+ .file("b/Cargo.toml", r#"
+ [package]
+ name = "b"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ dep_crate = {path = "../dep_crate", features = ["ftest"]}
+ "#)
+ .file("b/src/lib.rs", "")
+ .file("b/src/main.rs", r#"
+ extern crate dep_crate;
+ use dep_crate::yo;
+ fn main() {
+ yo();
+ }
+ "#)
+ .build();
+
+ /* Build and rebuild a/. Ensure dep_crate only builds once */
+ assert_that(p.cargo("run").cwd(p.root().join("a")),
+ execs().with_status(0)
+ .with_stdout("ftest off")
+ .with_stderr("\
+[..]Compiling dep_crate v0.0.1 ([..])
+[..]Compiling a v0.0.1 ([..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] `[..]target[/]debug[/]a[EXE]`
+"));
+ assert_that(p.cargo("clean").arg("-p").arg("a").cwd(p.root().join("a")),
+ execs().with_status(0));
+ assert_that(p.cargo("run").cwd(p.root().join("a")),
+ execs().with_status(0)
+ .with_stdout("ftest off")
+ .with_stderr("\
+[..]Compiling a v0.0.1 ([..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] `[..]target[/]debug[/]a[EXE]`
+"));
+
+ /* Build and rebuild b/. Ensure dep_crate only builds once */
+ assert_that(p.cargo("run").cwd(p.root().join("b")),
+ execs().with_status(0)
+ .with_stdout("ftest on")
+ .with_stderr("\
+[..]Compiling dep_crate v0.0.1 ([..])
+[..]Compiling b v0.0.1 ([..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] `[..]target[/]debug[/]b[EXE]`
+"));
+ assert_that(p.cargo("clean").arg("-p").arg("b").cwd(p.root().join("b")),
+ execs().with_status(0));
+ assert_that(p.cargo("run").cwd(p.root().join("b")),
+ execs().with_status(0)
+ .with_stdout("ftest on")
+ .with_stderr("\
+[..]Compiling b v0.0.1 ([..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] `[..]target[/]debug[/]b[EXE]`
+"));
+
+ /* Build a/ package again. If we cache different feature dep builds correctly,
+ * this should not cause a rebuild of dep_crate */
+ assert_that(p.cargo("clean").arg("-p").arg("a").cwd(p.root().join("a")),
+ execs().with_status(0));
+ assert_that(p.cargo("run").cwd(p.root().join("a")),
+ execs().with_status(0)
+ .with_stdout("ftest off")
+ .with_stderr("\
+[..]Compiling a v0.0.1 ([..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] `[..]target[/]debug[/]a[EXE]`
+"));
+
+ /* Build b/ package again. If we cache different feature dep builds correctly,
+ * this should not cause a rebuild */
+ assert_that(p.cargo("clean").arg("-p").arg("b").cwd(p.root().join("b")),
+ execs().with_status(0));
+ assert_that(p.cargo("run").cwd(p.root().join("b")),
+ execs().with_status(0)
+ .with_stdout("ftest on")
+ .with_stderr("\
+[..]Compiling b v0.0.1 ([..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] `[..]target[/]debug[/]b[EXE]`
+"));
+}
+
+#[test]
+fn changing_bin_features_caches_targets() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ authors = []
+ version = "0.0.1"
+
+ [features]
+ foo = []
+ "#)
+ .file("src/main.rs", r#"
+ fn main() {
+ let msg = if cfg!(feature = "foo") { "feature on" } else { "feature off" };
+ println!("{}", msg);
+ }
+ "#)
+ .build();
+
+ assert_that(p.cargo("run"),
+ execs().with_status(0)
+ .with_stdout("feature off")
+ .with_stderr("\
+[..]Compiling foo v0.0.1 ([..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] `target[/]debug[/]foo[EXE]`
+"));
+
+ assert_that(p.cargo("run").arg("--features").arg("foo"),
+ execs().with_status(0)
+ .with_stdout("feature on")
+ .with_stderr("\
+[..]Compiling foo v0.0.1 ([..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] `target[/]debug[/]foo[EXE]`
+"));
+
+ /* Targets should be cached from the first build */
+
+ assert_that(p.cargo("run"),
+ execs().with_status(0)
+ .with_stdout("feature off")
+ .with_stderr("\
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] `target[/]debug[/]foo[EXE]`
+"));
+
+ assert_that(p.cargo("run").arg("--features").arg("foo"),
+ execs().with_status(0)
+ .with_stdout("feature on")
+ .with_stderr("\
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] `target[/]debug[/]foo[EXE]`
+"));
+}
+
+#[test]
+fn rebuild_tests_if_lib_changes() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/lib.rs", "pub fn foo() {}")
+ .file("tests/foo.rs", r#"
+ extern crate foo;
+ #[test]
+ fn test() { foo::foo(); }
+ "#)
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0));
+ assert_that(p.cargo("test"),
+ execs().with_status(0));
+
+ sleep_ms(1000);
+ File::create(&p.root().join("src/lib.rs")).unwrap();
+
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(0));
+ assert_that(p.cargo("test").arg("-v"),
+ execs().with_status(101));
+}
+
+#[test]
+fn no_rebuild_transitive_target_deps() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ a = { path = "a" }
+ [dev-dependencies]
+ b = { path = "b" }
+ "#)
+ .file("src/lib.rs", "")
+ .file("tests/foo.rs", "")
+ .file("a/Cargo.toml", r#"
+ [package]
+ name = "a"
+ version = "0.0.1"
+ authors = []
+
+ [target.foo.dependencies]
+ c = { path = "../c" }
+ "#)
+ .file("a/src/lib.rs", "")
+ .file("b/Cargo.toml", r#"
+ [package]
+ name = "b"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ c = { path = "../c" }
+ "#)
+ .file("b/src/lib.rs", "")
+ .file("c/Cargo.toml", r#"
+ [package]
+ name = "c"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("c/src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0));
+ assert_that(p.cargo("test").arg("--no-run"),
+ execs().with_status(0)
+ .with_stderr("\
+[COMPILING] c v0.0.1 ([..])
+[COMPILING] b v0.0.1 ([..])
+[COMPILING] foo v0.0.1 ([..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+}
+
+#[test]
+fn rerun_if_changed_in_dep() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ a = { path = "a" }
+ "#)
+ .file("src/lib.rs", "")
+ .file("a/Cargo.toml", r#"
+ [package]
+ name = "a"
+ version = "0.0.1"
+ authors = []
+ build = "build.rs"
+ "#)
+ .file("a/build.rs", r#"
+ fn main() {
+ println!("cargo:rerun-if-changed=build.rs");
+ }
+ "#)
+ .file("a/src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0));
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stdout(""));
+}
+
+#[test]
+fn same_build_dir_cached_packages() {
+ let p = project("foo")
+ .file("a1/Cargo.toml", r#"
+ [package]
+ name = "a1"
+ version = "0.0.1"
+ authors = []
+ [dependencies]
+ b = { path = "../b" }
+ "#)
+ .file("a1/src/lib.rs", "")
+ .file("a2/Cargo.toml", r#"
+ [package]
+ name = "a2"
+ version = "0.0.1"
+ authors = []
+ [dependencies]
+ b = { path = "../b" }
+ "#)
+ .file("a2/src/lib.rs", "")
+ .file("b/Cargo.toml", r#"
+ [package]
+ name = "b"
+ version = "0.0.1"
+ authors = []
+ [dependencies]
+ c = { path = "../c" }
+ "#)
+ .file("b/src/lib.rs", "")
+ .file("c/Cargo.toml", r#"
+ [package]
+ name = "c"
+ version = "0.0.1"
+ authors = []
+ [dependencies]
+ d = { path = "../d" }
+ "#)
+ .file("c/src/lib.rs", "")
+ .file("d/Cargo.toml", r#"
+ [package]
+ name = "d"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("d/src/lib.rs", "")
+ .file(".cargo/config", r#"
+ [build]
+ target-dir = "./target"
+ "#)
+ .build();
+
+ assert_that(p.cargo("build").cwd(p.root().join("a1")),
+ execs().with_status(0).with_stderr(&format!("\
+[COMPILING] d v0.0.1 ({dir}/d)
+[COMPILING] c v0.0.1 ({dir}/c)
+[COMPILING] b v0.0.1 ({dir}/b)
+[COMPILING] a1 v0.0.1 ({dir}/a1)
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+", dir = p.url())));
+ assert_that(p.cargo("build").cwd(p.root().join("a2")),
+ execs().with_status(0).with_stderr(&format!("\
+[COMPILING] a2 v0.0.1 ({dir}/a2)
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+", dir = p.url())));
+}
+
+#[test]
+fn no_rebuild_if_build_artifacts_move_backwards_in_time() {
+ let p = project("backwards_in_time")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "backwards_in_time"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ a = { path = "a" }
+ "#)
+ .file("src/lib.rs", "")
+ .file("a/Cargo.toml", r#"
+ [package]
+ name = "a"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("a/src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0));
+
+ p.root().move_into_the_past();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stdout("").with_stderr("\
+[FINISHED] [..]
+"));
+}
+
+#[test]
+fn rebuild_if_build_artifacts_move_forward_in_time() {
+ let p = project("forwards_in_time")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "forwards_in_time"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ a = { path = "a" }
+ "#)
+ .file("src/lib.rs", "")
+ .file("a/Cargo.toml", r#"
+ [package]
+ name = "a"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("a/src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0));
+
+ p.root().move_into_the_future();
+
+ assert_that(p.cargo("build").env("RUST_LOG", ""),
+ execs().with_status(0).with_stdout("").with_stderr("\
+[COMPILING] a v0.0.1 ([..])
+[COMPILING] forwards_in_time v0.0.1 ([..])
+[FINISHED] [..]
+"));
+}
+
+#[test]
+fn rebuild_if_environment_changes() {
+ let p = project("env_change")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "env_change"
+ description = "old desc"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/main.rs", r#"
+ fn main() {
+ println!("{}", env!("CARGO_PKG_DESCRIPTION"));
+ }
+ "#)
+ .build();
+
+ assert_that(p.cargo("run"),
+ execs().with_status(0)
+ .with_stdout("old desc").with_stderr(&format!("\
+[COMPILING] env_change v0.0.1 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] `target[/]debug[/]env_change[EXE]`
+", dir = p.url())));
+
+ File::create(&p.root().join("Cargo.toml")).unwrap().write_all(br#"
+ [package]
+ name = "env_change"
+ description = "new desc"
+ version = "0.0.1"
+ authors = []
+ "#).unwrap();
+
+ assert_that(p.cargo("run"),
+ execs().with_status(0)
+ .with_stdout("new desc").with_stderr(&format!("\
+[COMPILING] env_change v0.0.1 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] `target[/]debug[/]env_change[EXE]`
+", dir = p.url())));
+}
+
+#[test]
+fn no_rebuild_when_rename_dir() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ foo = { path = "foo" }
+ "#)
+ .file("src/lib.rs", "")
+ .file("foo/Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("foo/src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"), execs().with_status(0));
+ let mut new = p.root();
+ new.pop();
+ new.push("bar");
+ fs::rename(p.root(), &new).unwrap();
+
+ assert_that(p.cargo("build").cwd(&new),
+ execs().with_status(0)
+ .with_stderr("\
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+}
--- /dev/null
+use std::fs::{self, File};
+use std::io::prelude::*;
+
+use cargotest::support::{project, execs};
+use hamcrest::{assert_that, existing_file, is_not};
+
+#[test]
+fn adding_and_removing_packages() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ authors = []
+ version = "0.0.1"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .file("bar/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ authors = []
+ version = "0.0.1"
+ "#)
+ .file("bar/src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("generate-lockfile"),
+ execs().with_status(0));
+
+ let toml = p.root().join("Cargo.toml");
+ let lock1 = p.read_lockfile();
+
+ // add a dep
+ File::create(&toml).unwrap().write_all(br#"
+ [package]
+ name = "foo"
+ authors = []
+ version = "0.0.1"
+
+ [dependencies.bar]
+ path = "bar"
+ "#).unwrap();
+ assert_that(p.cargo("generate-lockfile"),
+ execs().with_status(0));
+ let lock2 = p.read_lockfile();
+ assert!(lock1 != lock2);
+
+ // change the dep
+ File::create(&p.root().join("bar/Cargo.toml")).unwrap().write_all(br#"
+ [package]
+ name = "bar"
+ authors = []
+ version = "0.0.2"
+ "#).unwrap();
+ assert_that(p.cargo("generate-lockfile"),
+ execs().with_status(0));
+ let lock3 = p.read_lockfile();
+ assert!(lock1 != lock3);
+ assert!(lock2 != lock3);
+
+ // remove the dep
+ println!("lock4");
+ File::create(&toml).unwrap().write_all(br#"
+ [package]
+ name = "foo"
+ authors = []
+ version = "0.0.1"
+ "#).unwrap();
+ assert_that(p.cargo("generate-lockfile"),
+ execs().with_status(0));
+ let lock4 = p.read_lockfile();
+ assert_eq!(lock1, lock4);
+}
+
+#[test]
+fn no_index_update() {
+ use cargotest::ChannelChanger;
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ authors = []
+ version = "0.0.1"
+
+ [dependencies]
+ serde = "1.0"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("generate-lockfile"),
+ execs().with_status(0).with_stdout("")
+ .with_stderr_contains(" Updating registry `https://github.com/rust-lang/crates.io-index`"));
+
+ assert_that(p.cargo("generate-lockfile").masquerade_as_nightly_cargo().arg("-Zno-index-update"),
+ execs().with_status(0).with_stdout("")
+ .with_stderr_does_not_contain(" Updating registry `https://github.com/rust-lang/crates.io-index`"));
+}
+
+#[test]
+fn preserve_metadata() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ authors = []
+ version = "0.0.1"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .file("bar/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ authors = []
+ version = "0.0.1"
+ "#)
+ .file("bar/src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("generate-lockfile"),
+ execs().with_status(0));
+
+ let metadata = r#"
+[metadata]
+bar = "baz"
+foo = "bar"
+"#;
+ let lockfile = p.root().join("Cargo.lock");
+ let lock = p.read_lockfile();
+ let data = lock + metadata;
+ File::create(&lockfile).unwrap().write_all(data.as_bytes()).unwrap();
+
+ // Build and make sure the metadata is still there
+ assert_that(p.cargo("build"),
+ execs().with_status(0));
+ let lock = p.read_lockfile();
+ assert!(lock.contains(metadata.trim()), "{}", lock);
+
+ // Update and make sure the metadata is still there
+ assert_that(p.cargo("update"),
+ execs().with_status(0));
+ let lock = p.read_lockfile();
+ assert!(lock.contains(metadata.trim()), "{}", lock);
+}
+
+#[test]
+fn preserve_line_endings_issue_2076() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ authors = []
+ version = "0.0.1"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .file("bar/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ authors = []
+ version = "0.0.1"
+ "#)
+ .file("bar/src/lib.rs", "")
+ .build();
+
+ let lockfile = p.root().join("Cargo.lock");
+ assert_that(p.cargo("generate-lockfile"),
+ execs().with_status(0));
+ assert_that(&lockfile,
+ existing_file());
+ assert_that(p.cargo("generate-lockfile"),
+ execs().with_status(0));
+
+ let lock0 = p.read_lockfile();
+
+ assert!(lock0.starts_with("[[package]]\n"));
+
+ let lock1 = lock0.replace("\n", "\r\n");
+ {
+ File::create(&lockfile).unwrap().write_all(lock1.as_bytes()).unwrap();
+ }
+
+ assert_that(p.cargo("generate-lockfile"),
+ execs().with_status(0));
+
+ let lock2 = p.read_lockfile();
+
+ assert!(lock2.starts_with("[[package]]\r\n"));
+ assert_eq!(lock1, lock2);
+}
+
+#[test]
+fn cargo_update_generate_lockfile() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ authors = []
+ version = "0.0.1"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ let lockfile = p.root().join("Cargo.lock");
+ assert_that(&lockfile, is_not(existing_file()));
+ assert_that(p.cargo("update"), execs().with_status(0).with_stdout(""));
+ assert_that(&lockfile, existing_file());
+
+ fs::remove_file(p.root().join("Cargo.lock")).unwrap();
+
+ assert_that(&lockfile, is_not(existing_file()));
+ assert_that(p.cargo("update"), execs().with_status(0).with_stdout(""));
+ assert_that(&lockfile, existing_file());
+
+}
--- /dev/null
+use git2;
+use std::fs::{self, File};
+use std::io::prelude::*;
+use std::net::{TcpListener, TcpStream};
+use std::path::Path;
+use std::sync::Arc;
+use std::sync::atomic::{AtomicBool, Ordering};
+use std::thread;
+
+use cargo::util::process;
+use cargotest::sleep_ms;
+use cargotest::support::paths::{self, CargoPathExt};
+use cargotest::support::{git, project, execs, main_file, path2url};
+use cargotest::ChannelChanger;
+use hamcrest::{assert_that,existing_file};
+
+#[test]
+fn cargo_compile_simple_git_dep() {
+ let project = project("foo");
+ let git_project = git::new("dep1", |project| {
+ project
+ .file("Cargo.toml", r#"
+ [project]
+
+ name = "dep1"
+ version = "0.5.0"
+ authors = ["carlhuda@example.com"]
+
+ [lib]
+
+ name = "dep1"
+ "#)
+ .file("src/dep1.rs", r#"
+ pub fn hello() -> &'static str {
+ "hello world"
+ }
+ "#)
+ }).unwrap();
+
+ let project = project
+ .file("Cargo.toml", &format!(r#"
+ [project]
+
+ name = "foo"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+
+ [dependencies.dep1]
+
+ git = '{}'
+ "#, git_project.url()))
+ .file("src/main.rs", &main_file(r#""{}", dep1::hello()"#, &["dep1"]))
+ .build();
+
+ let root = project.root();
+ let git_root = git_project.root();
+
+ assert_that(project.cargo("build"),
+ execs()
+ .with_stderr(&format!("[UPDATING] git repository `{}`\n\
+ [COMPILING] dep1 v0.5.0 ({}#[..])\n\
+ [COMPILING] foo v0.5.0 ({})\n\
+ [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]\n",
+ path2url(git_root.clone()),
+ path2url(git_root),
+ path2url(root))));
+
+ assert_that(&project.bin("foo"), existing_file());
+
+ assert_that(
+ process(&project.bin("foo")),
+ execs().with_stdout("hello world\n"));
+}
+
+#[test]
+fn cargo_compile_forbird_git_httpsrepo_offline() {
+
+ let p = project("need_remote_repo")
+ .file("Cargo.toml", r#"
+
+ [project]
+ name = "need_remote_repo"
+ version = "0.5.0"
+ authors = ["chabapok@example.com"]
+
+ [dependencies.dep1]
+ git = 'https://github.com/some_user/dep1.git'
+ "#)
+ .file("src/main.rs", "")
+ .build();
+
+
+ assert_that(p.cargo("build").masquerade_as_nightly_cargo().arg("-Zoffline"),
+ execs().with_status(101).
+ with_stderr("\
+error: failed to load source for a dependency on `dep1`
+
+Caused by:
+ Unable to update https://github.com/some_user/dep1.git
+
+Caused by:
+ can't checkout from 'https://github.com/some_user/dep1.git': you are in the offline mode (-Z offline)"));
+}
+
+
+#[test]
+fn cargo_compile_offline_with_cached_git_dep() {
+ let git_project = git::new("dep1", |project| {
+ project
+ .file("Cargo.toml", r#"
+ [project]
+ name = "dep1"
+ version = "0.5.0"
+ authors = ["chabapok@example.com"]
+
+ [lib]
+ name = "dep1""#)
+ .file("src/lib.rs", r#"
+ pub static COOL_STR:&str = "cached git repo rev1";
+ "#)
+ }).unwrap();
+
+ let repo = git2::Repository::open(&git_project.root()).unwrap();
+ let rev1 = repo.revparse_single("HEAD").unwrap().id();
+
+ // Commit the changes and make sure we trigger a recompile
+ File::create(&git_project.root().join("src/lib.rs")).unwrap().write_all(br#"
+ pub static COOL_STR:&str = "cached git repo rev2";
+ "#).unwrap();
+ git::add(&repo);
+ let rev2 = git::commit(&repo);
+
+ {
+ // cache to regisrty rev1 and rev2
+ let prj = project("cache_git_dep")
+ .file("Cargo.toml", &format!(r#"
+ [project]
+ name = "cache_git_dep"
+ version = "0.5.0"
+
+ [dependencies.dep1]
+ git = '{}'
+ rev = "{}"
+ "#, git_project.url(), rev1.clone()))
+ .file("src/main.rs", "fn main(){}")
+ .build();
+ assert_that(prj.cargo("build"), execs().with_status(0));
+
+ File::create(&prj.root().join("Cargo.toml")).unwrap().write_all(
+ &format!(r#"
+ [project]
+ name = "cache_git_dep"
+ version = "0.5.0"
+
+ [dependencies.dep1]
+ git = '{}'
+ rev = "{}"
+ "#, git_project.url(), rev2.clone()).as_bytes()
+ ).unwrap();
+ assert_that(prj.cargo("build"), execs().with_status(0));
+ }
+
+ let project = project("foo")
+ .file("Cargo.toml", &format!(r#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+
+ [dependencies.dep1]
+ git = '{}'
+ "#, git_project.url()))
+ .file("src/main.rs", &main_file(r#""hello from {}", dep1::COOL_STR"#, &["dep1"]))
+ .build();
+
+ let root = project.root();
+ let git_root = git_project.root();
+
+ assert_that(project.cargo("build").masquerade_as_nightly_cargo().arg("-Zoffline"),
+ execs().with_stderr(format!("\
+[COMPILING] dep1 v0.5.0 ({}#[..])
+[COMPILING] foo v0.5.0 ({})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]",
+ path2url(git_root),
+ path2url(root)
+ )));
+
+ assert_that(&project.bin("foo"), existing_file());
+
+ assert_that(process(&project.bin("foo")),
+ execs().with_stdout("hello from cached git repo rev2\n"));
+
+ drop( File::create(&project.root().join("Cargo.toml")).unwrap()
+ .write_all(&format!(r#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+
+ [dependencies.dep1]
+ git = '{}'
+ rev = "{}"
+ "#, git_project.url(), rev1).as_bytes()).unwrap() );
+
+ let _out = project.cargo("build").masquerade_as_nightly_cargo()
+ .arg("-Zoffline").exec_with_output();
+ assert_that(process(&project.bin("foo")),
+ execs().with_stdout("hello from cached git repo rev1\n"));
+}
+
+
+#[test]
+fn cargo_compile_git_dep_branch() {
+ let project = project("foo");
+ let git_project = git::new("dep1", |project| {
+ project
+ .file("Cargo.toml", r#"
+ [project]
+
+ name = "dep1"
+ version = "0.5.0"
+ authors = ["carlhuda@example.com"]
+
+ [lib]
+
+ name = "dep1"
+ "#)
+ .file("src/dep1.rs", r#"
+ pub fn hello() -> &'static str {
+ "hello world"
+ }
+ "#)
+ }).unwrap();
+
+ // Make a new branch based on the current HEAD commit
+ let repo = git2::Repository::open(&git_project.root()).unwrap();
+ let head = repo.head().unwrap().target().unwrap();
+ let head = repo.find_commit(head).unwrap();
+ repo.branch("branchy", &head, true).unwrap();
+
+ let project = project
+ .file("Cargo.toml", &format!(r#"
+ [project]
+
+ name = "foo"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+
+ [dependencies.dep1]
+
+ git = '{}'
+ branch = "branchy"
+
+ "#, git_project.url()))
+ .file("src/main.rs", &main_file(r#""{}", dep1::hello()"#, &["dep1"]))
+ .build();
+
+ let root = project.root();
+ let git_root = git_project.root();
+
+ assert_that(project.cargo("build"),
+ execs()
+ .with_stderr(&format!("[UPDATING] git repository `{}`\n\
+ [COMPILING] dep1 v0.5.0 ({}?branch=branchy#[..])\n\
+ [COMPILING] foo v0.5.0 ({})\n\
+ [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]\n",
+ path2url(git_root.clone()),
+ path2url(git_root),
+ path2url(root))));
+
+ assert_that(&project.bin("foo"), existing_file());
+
+ assert_that(
+ process(&project.bin("foo")),
+ execs().with_stdout("hello world\n"));
+}
+
+#[test]
+fn cargo_compile_git_dep_tag() {
+ let project = project("foo");
+ let git_project = git::new("dep1", |project| {
+ project
+ .file("Cargo.toml", r#"
+ [project]
+
+ name = "dep1"
+ version = "0.5.0"
+ authors = ["carlhuda@example.com"]
+
+ [lib]
+
+ name = "dep1"
+ "#)
+ .file("src/dep1.rs", r#"
+ pub fn hello() -> &'static str {
+ "hello world"
+ }
+ "#)
+ }).unwrap();
+
+ // Make a tag corresponding to the current HEAD
+ let repo = git2::Repository::open(&git_project.root()).unwrap();
+ let head = repo.head().unwrap().target().unwrap();
+ repo.tag("v0.1.0",
+ &repo.find_object(head, None).unwrap(),
+ &repo.signature().unwrap(),
+ "make a new tag",
+ false).unwrap();
+
+ let project = project
+ .file("Cargo.toml", &format!(r#"
+ [project]
+
+ name = "foo"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+
+ [dependencies.dep1]
+
+ git = '{}'
+ tag = "v0.1.0"
+ "#, git_project.url()))
+ .file("src/main.rs", &main_file(r#""{}", dep1::hello()"#, &["dep1"]))
+ .build();
+
+ let root = project.root();
+ let git_root = git_project.root();
+
+ assert_that(project.cargo("build"),
+ execs()
+ .with_stderr(&format!("[UPDATING] git repository `{}`\n\
+ [COMPILING] dep1 v0.5.0 ({}?tag=v0.1.0#[..])\n\
+ [COMPILING] foo v0.5.0 ({})\n\
+ [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]\n",
+ path2url(git_root.clone()),
+ path2url(git_root),
+ path2url(root))));
+
+ assert_that(&project.bin("foo"), existing_file());
+
+ assert_that(process(&project.bin("foo")),
+ execs().with_stdout("hello world\n"));
+
+ assert_that(project.cargo("build"),
+ execs().with_status(0));
+}
+
+#[test]
+fn cargo_compile_with_nested_paths() {
+ let git_project = git::new("dep1", |project| {
+ project
+ .file("Cargo.toml", r#"
+ [project]
+
+ name = "dep1"
+ version = "0.5.0"
+ authors = ["carlhuda@example.com"]
+
+ [dependencies.dep2]
+
+ version = "0.5.0"
+ path = "vendor/dep2"
+
+ [lib]
+
+ name = "dep1"
+ "#)
+ .file("src/dep1.rs", r#"
+ extern crate dep2;
+
+ pub fn hello() -> &'static str {
+ dep2::hello()
+ }
+ "#)
+ .file("vendor/dep2/Cargo.toml", r#"
+ [project]
+
+ name = "dep2"
+ version = "0.5.0"
+ authors = ["carlhuda@example.com"]
+
+ [lib]
+
+ name = "dep2"
+ "#)
+ .file("vendor/dep2/src/dep2.rs", r#"
+ pub fn hello() -> &'static str {
+ "hello world"
+ }
+ "#)
+ }).unwrap();
+
+ let p = project("parent")
+ .file("Cargo.toml", &format!(r#"
+ [project]
+
+ name = "parent"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+
+ [dependencies.dep1]
+
+ version = "0.5.0"
+ git = '{}'
+
+ [[bin]]
+
+ name = "parent"
+ "#, git_project.url()))
+ .file("src/parent.rs",
+ &main_file(r#""{}", dep1::hello()"#, &["dep1"]))
+ .build();
+
+ p.cargo("build")
+ .exec_with_output()
+ .unwrap();
+
+ assert_that(&p.bin("parent"), existing_file());
+
+ assert_that(process(&p.bin("parent")),
+ execs().with_stdout("hello world\n"));
+}
+
+#[test]
+fn cargo_compile_with_malformed_nested_paths() {
+ let git_project = git::new("dep1", |project| {
+ project
+ .file("Cargo.toml", r#"
+ [project]
+
+ name = "dep1"
+ version = "0.5.0"
+ authors = ["carlhuda@example.com"]
+
+ [lib]
+
+ name = "dep1"
+ "#)
+ .file("src/dep1.rs", r#"
+ pub fn hello() -> &'static str {
+ "hello world"
+ }
+ "#)
+ .file("vendor/dep2/Cargo.toml", r#"
+ !INVALID!
+ "#)
+ }).unwrap();
+
+ let p = project("parent")
+ .file("Cargo.toml", &format!(r#"
+ [project]
+
+ name = "parent"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+
+ [dependencies.dep1]
+
+ version = "0.5.0"
+ git = '{}'
+
+ [[bin]]
+
+ name = "parent"
+ "#, git_project.url()))
+ .file("src/parent.rs",
+ &main_file(r#""{}", dep1::hello()"#, &["dep1"]))
+ .build();
+
+ p.cargo("build")
+ .exec_with_output()
+ .unwrap();
+
+ assert_that(&p.bin("parent"), existing_file());
+
+ assert_that(process(&p.bin("parent")),
+ execs().with_stdout("hello world\n"));
+}
+
+#[test]
+fn cargo_compile_with_meta_package() {
+ let git_project = git::new("meta-dep", |project| {
+ project
+ .file("dep1/Cargo.toml", r#"
+ [project]
+
+ name = "dep1"
+ version = "0.5.0"
+ authors = ["carlhuda@example.com"]
+
+ [lib]
+
+ name = "dep1"
+ "#)
+ .file("dep1/src/dep1.rs", r#"
+ pub fn hello() -> &'static str {
+ "this is dep1"
+ }
+ "#)
+ .file("dep2/Cargo.toml", r#"
+ [project]
+
+ name = "dep2"
+ version = "0.5.0"
+ authors = ["carlhuda@example.com"]
+
+ [lib]
+
+ name = "dep2"
+ "#)
+ .file("dep2/src/dep2.rs", r#"
+ pub fn hello() -> &'static str {
+ "this is dep2"
+ }
+ "#)
+ }).unwrap();
+
+ let p = project("parent")
+ .file("Cargo.toml", &format!(r#"
+ [project]
+
+ name = "parent"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+
+ [dependencies.dep1]
+
+ version = "0.5.0"
+ git = '{}'
+
+ [dependencies.dep2]
+
+ version = "0.5.0"
+ git = '{}'
+
+ [[bin]]
+
+ name = "parent"
+ "#, git_project.url(), git_project.url()))
+ .file("src/parent.rs",
+ &main_file(r#""{} {}", dep1::hello(), dep2::hello()"#, &["dep1", "dep2"]))
+ .build();
+
+ p.cargo("build")
+ .exec_with_output()
+ .unwrap();
+
+ assert_that(&p.bin("parent"), existing_file());
+
+ assert_that(process(&p.bin("parent")),
+ execs().with_stdout("this is dep1 this is dep2\n"));
+}
+
+#[test]
+fn cargo_compile_with_short_ssh_git() {
+ let url = "git@github.com:a/dep";
+
+ let project = project("project")
+ .file("Cargo.toml", &format!(r#"
+ [project]
+
+ name = "foo"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+
+ [dependencies.dep]
+
+ git = "{}"
+
+ [[bin]]
+
+ name = "foo"
+ "#, url))
+ .file("src/foo.rs", &main_file(r#""{}", dep1::hello()"#, &["dep1"]))
+ .build();
+
+ assert_that(project.cargo("build"),
+ execs()
+ .with_stdout("")
+ .with_stderr(&format!("\
+[ERROR] failed to parse manifest at `[..]`
+
+Caused by:
+ invalid url `{}`: relative URL without a base
+", url)));
+}
+
+#[test]
+fn two_revs_same_deps() {
+ let bar = git::new("meta-dep", |project| {
+ project.file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.0"
+ authors = []
+ "#)
+ .file("src/lib.rs", "pub fn bar() -> i32 { 1 }")
+ }).unwrap();
+
+ let repo = git2::Repository::open(&bar.root()).unwrap();
+ let rev1 = repo.revparse_single("HEAD").unwrap().id();
+
+ // Commit the changes and make sure we trigger a recompile
+ File::create(&bar.root().join("src/lib.rs")).unwrap().write_all(br#"
+ pub fn bar() -> i32 { 2 }
+ "#).unwrap();
+ git::add(&repo);
+ let rev2 = git::commit(&repo);
+
+ let foo = project("foo")
+ .file("Cargo.toml", &format!(r#"
+ [project]
+ name = "foo"
+ version = "0.0.0"
+ authors = []
+
+ [dependencies.bar]
+ git = '{}'
+ rev = "{}"
+
+ [dependencies.baz]
+ path = "../baz"
+ "#, bar.url(), rev1))
+ .file("src/main.rs", r#"
+ extern crate bar;
+ extern crate baz;
+
+ fn main() {
+ assert_eq!(bar::bar(), 1);
+ assert_eq!(baz::baz(), 2);
+ }
+ "#)
+ .build();
+
+ let _baz = project("baz")
+ .file("Cargo.toml", &format!(r#"
+ [package]
+ name = "baz"
+ version = "0.0.0"
+ authors = []
+
+ [dependencies.bar]
+ git = '{}'
+ rev = "{}"
+ "#, bar.url(), rev2))
+ .file("src/lib.rs", r#"
+ extern crate bar;
+ pub fn baz() -> i32 { bar::bar() }
+ "#)
+ .build();
+
+ assert_that(foo.cargo("build").arg("-v"),
+ execs().with_status(0));
+ assert_that(&foo.bin("foo"), existing_file());
+ assert_that(foo.process(&foo.bin("foo")), execs().with_status(0));
+}
+
+#[test]
+fn recompilation() {
+ let git_project = git::new("bar", |project| {
+ project
+ .file("Cargo.toml", r#"
+ [project]
+
+ name = "bar"
+ version = "0.5.0"
+ authors = ["carlhuda@example.com"]
+
+ [lib]
+ name = "bar"
+ "#)
+ .file("src/bar.rs", r#"
+ pub fn bar() {}
+ "#)
+ }).unwrap();
+
+ let p = project("foo")
+ .file("Cargo.toml", &format!(r#"
+ [project]
+
+ name = "foo"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+
+ [dependencies.bar]
+
+ version = "0.5.0"
+ git = '{}'
+ "#, git_project.url()))
+ .file("src/main.rs",
+ &main_file(r#""{:?}", bar::bar()"#, &["bar"]))
+ .build();
+
+ // First time around we should compile both foo and bar
+ assert_that(p.cargo("build"),
+ execs().with_stderr(&format!("[UPDATING] git repository `{}`\n\
+ [COMPILING] bar v0.5.0 ({}#[..])\n\
+ [COMPILING] foo v0.5.0 ({})\n\
+ [FINISHED] dev [unoptimized + debuginfo] target(s) \
+ in [..]\n",
+ git_project.url(),
+ git_project.url(),
+ p.url())));
+
+ // Don't recompile the second time
+ assert_that(p.cargo("build"),
+ execs().with_stdout(""));
+
+ // Modify a file manually, shouldn't trigger a recompile
+ File::create(&git_project.root().join("src/bar.rs")).unwrap().write_all(br#"
+ pub fn bar() { println!("hello!"); }
+ "#).unwrap();
+
+ assert_that(p.cargo("build"),
+ execs().with_stdout(""));
+
+ assert_that(p.cargo("update"),
+ execs().with_stderr(&format!("[UPDATING] git repository `{}`",
+ git_project.url())));
+
+ assert_that(p.cargo("build"),
+ execs().with_stdout(""));
+
+ // Commit the changes and make sure we don't trigger a recompile because the
+ // lockfile says not to change
+ let repo = git2::Repository::open(&git_project.root()).unwrap();
+ git::add(&repo);
+ git::commit(&repo);
+
+ println!("compile after commit");
+ assert_that(p.cargo("build"),
+ execs().with_stdout(""));
+ p.root().move_into_the_past();
+
+ // Update the dependency and carry on!
+ assert_that(p.cargo("update"),
+ execs().with_stderr(&format!("[UPDATING] git repository `{}`\n\
+ [UPDATING] bar v0.5.0 ([..]) -> #[..]\n\
+ ",
+ git_project.url())));
+ println!("going for the last compile");
+ assert_that(p.cargo("build"),
+ execs().with_stderr(&format!("[COMPILING] bar v0.5.0 ({}#[..])\n\
+ [COMPILING] foo v0.5.0 ({})\n\
+ [FINISHED] dev [unoptimized + debuginfo] target(s) \
+ in [..]\n",
+ git_project.url(),
+ p.url())));
+
+ // Make sure clean only cleans one dep
+ assert_that(p.cargo("clean")
+ .arg("-p").arg("foo"),
+ execs().with_stdout(""));
+ assert_that(p.cargo("build"),
+ execs().with_stderr(&format!("[COMPILING] foo v0.5.0 ({})\n\
+ [FINISHED] dev [unoptimized + debuginfo] target(s) \
+ in [..]\n",
+ p.url())));
+}
+
+#[test]
+fn update_with_shared_deps() {
+ let git_project = git::new("bar", |project| {
+ project
+ .file("Cargo.toml", r#"
+ [project]
+
+ name = "bar"
+ version = "0.5.0"
+ authors = ["carlhuda@example.com"]
+
+ [lib]
+ name = "bar"
+ "#)
+ .file("src/bar.rs", r#"
+ pub fn bar() {}
+ "#)
+ }).unwrap();
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+
+ [dependencies.dep1]
+ path = "dep1"
+ [dependencies.dep2]
+ path = "dep2"
+ "#)
+ .file("src/main.rs", r#"
+ #[allow(unused_extern_crates)]
+ extern crate dep1;
+ #[allow(unused_extern_crates)]
+ extern crate dep2;
+ fn main() {}
+ "#)
+ .file("dep1/Cargo.toml", &format!(r#"
+ [package]
+ name = "dep1"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+
+ [dependencies.bar]
+ version = "0.5.0"
+ git = '{}'
+ "#, git_project.url()))
+ .file("dep1/src/lib.rs", "")
+ .file("dep2/Cargo.toml", &format!(r#"
+ [package]
+ name = "dep2"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+
+ [dependencies.bar]
+ version = "0.5.0"
+ git = '{}'
+ "#, git_project.url()))
+ .file("dep2/src/lib.rs", "")
+ .build();
+
+ // First time around we should compile both foo and bar
+ assert_that(p.cargo("build"),
+ execs().with_stderr(&format!("\
+[UPDATING] git repository `{git}`
+[COMPILING] bar v0.5.0 ({git}#[..])
+[COMPILING] [..] v0.5.0 ([..])
+[COMPILING] [..] v0.5.0 ([..])
+[COMPILING] foo v0.5.0 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]\n",
+git = git_project.url(), dir = p.url())));
+
+ // Modify a file manually, and commit it
+ File::create(&git_project.root().join("src/bar.rs")).unwrap().write_all(br#"
+ pub fn bar() { println!("hello!"); }
+ "#).unwrap();
+ let repo = git2::Repository::open(&git_project.root()).unwrap();
+ let old_head = repo.head().unwrap().target().unwrap();
+ git::add(&repo);
+ git::commit(&repo);
+
+ sleep_ms(1000);
+
+ // By default, not transitive updates
+ println!("dep1 update");
+ assert_that(p.cargo("update")
+ .arg("-p").arg("dep1"),
+ execs().with_stdout(""));
+
+ // Don't do anything bad on a weird --precise argument
+ println!("bar bad precise update");
+ assert_that(p.cargo("update")
+ .arg("-p").arg("bar")
+ .arg("--precise").arg("0.1.2"),
+ execs().with_status(101).with_stderr("\
+[UPDATING] git repository [..]
+[ERROR] Unable to update [..]
+
+To learn more, run the command again with --verbose.
+"));
+
+ // Specifying a precise rev to the old rev shouldn't actually update
+ // anything because we already have the rev in the db.
+ println!("bar precise update");
+ assert_that(p.cargo("update")
+ .arg("-p").arg("bar")
+ .arg("--precise").arg(&old_head.to_string()),
+ execs().with_stdout(""));
+
+ // Updating aggressively should, however, update the repo.
+ println!("dep1 aggressive update");
+ assert_that(p.cargo("update")
+ .arg("-p").arg("dep1")
+ .arg("--aggressive"),
+ execs().with_stderr(&format!("[UPDATING] git repository `{}`\n\
+ [UPDATING] bar v0.5.0 ([..]) -> #[..]\n\
+ ", git_project.url())));
+
+ // Make sure we still only compile one version of the git repo
+ println!("build");
+ assert_that(p.cargo("build"),
+ execs().with_stderr(&format!("\
+[COMPILING] bar v0.5.0 ({git}#[..])
+[COMPILING] [..] v0.5.0 ({dir}[..]dep[..])
+[COMPILING] [..] v0.5.0 ({dir}[..]dep[..])
+[COMPILING] foo v0.5.0 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]\n",
+ git = git_project.url(), dir = p.url())));
+
+ // We should be able to update transitive deps
+ assert_that(p.cargo("update").arg("-p").arg("bar"),
+ execs().with_stderr(&format!("[UPDATING] git repository `{}`",
+ git_project.url())));
+}
+
+#[test]
+fn dep_with_submodule() {
+ let project = project("foo");
+ let git_project = git::new("dep1", |project| {
+ project
+ .file("Cargo.toml", r#"
+ [package]
+ name = "dep1"
+ version = "0.5.0"
+ authors = ["carlhuda@example.com"]
+ "#)
+ }).unwrap();
+ let git_project2 = git::new("dep2", |project| {
+ project.file("lib.rs", "pub fn dep() {}")
+ }).unwrap();
+
+ let repo = git2::Repository::open(&git_project.root()).unwrap();
+ let url = path2url(git_project2.root()).to_string();
+ git::add_submodule(&repo, &url, Path::new("src"));
+ git::commit(&repo);
+
+ let project = project
+ .file("Cargo.toml", &format!(r#"
+ [project]
+
+ name = "foo"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+
+ [dependencies.dep1]
+
+ git = '{}'
+ "#, git_project.url()))
+ .file("src/lib.rs", "
+ extern crate dep1;
+ pub fn foo() { dep1::dep() }
+ ")
+ .build();
+
+ assert_that(project.cargo("build"),
+ execs().with_stderr("\
+[UPDATING] git repository [..]
+[COMPILING] dep1 [..]
+[COMPILING] foo [..]
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]\n").with_status(0));
+}
+
+#[test]
+fn dep_with_bad_submodule() {
+ let project = project("foo");
+ let git_project = git::new("dep1", |project| {
+ project
+ .file("Cargo.toml", r#"
+ [package]
+ name = "dep1"
+ version = "0.5.0"
+ authors = ["carlhuda@example.com"]
+ "#)
+ }).unwrap();
+ let git_project2 = git::new("dep2", |project| {
+ project.file("lib.rs", "pub fn dep() {}")
+ }).unwrap();
+
+ let repo = git2::Repository::open(&git_project.root()).unwrap();
+ let url = path2url(git_project2.root()).to_string();
+ git::add_submodule(&repo, &url, Path::new("src"));
+ git::commit(&repo);
+
+ // now amend the first commit on git_project2 to make submodule ref point to not-found
+ // commit
+ let repo = git2::Repository::open(&git_project2.root()).unwrap();
+ let original_submodule_ref = repo.refname_to_id("refs/heads/master").unwrap();
+ let commit = repo.find_commit(original_submodule_ref).unwrap();
+ commit.amend(
+ Some("refs/heads/master"),
+ None,
+ None,
+ None,
+ Some("something something"),
+ None).unwrap();
+
+ let p = project
+ .file("Cargo.toml", &format!(r#"
+ [project]
+
+ name = "foo"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+
+ [dependencies.dep1]
+
+ git = '{}'
+ "#, git_project.url()))
+ .file("src/lib.rs", "
+ extern crate dep1;
+ pub fn foo() { dep1::dep() }
+ ")
+ .build();
+
+ let expected = format!("\
+[UPDATING] git repository [..]
+[ERROR] failed to load source for a dependency on `dep1`
+
+Caused by:
+ Unable to update {}
+
+Caused by:
+ failed to update submodule `src`
+
+Caused by:
+ object not found - no match for id [..]
+", path2url(git_project.root()));
+
+ assert_that(p.cargo("build"),
+ execs().with_stderr(expected).with_status(101));
+}
+
+#[test]
+fn two_deps_only_update_one() {
+ let project = project("foo");
+ let git1 = git::new("dep1", |project| {
+ project
+ .file("Cargo.toml", r#"
+ [package]
+ name = "dep1"
+ version = "0.5.0"
+ authors = ["carlhuda@example.com"]
+ "#)
+ .file("src/lib.rs", "")
+ }).unwrap();
+ let git2 = git::new("dep2", |project| {
+ project
+ .file("Cargo.toml", r#"
+ [package]
+ name = "dep2"
+ version = "0.5.0"
+ authors = ["carlhuda@example.com"]
+ "#)
+ .file("src/lib.rs", "")
+ }).unwrap();
+
+ let p = project
+ .file("Cargo.toml", &format!(r#"
+ [project]
+
+ name = "foo"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+
+ [dependencies.dep1]
+ git = '{}'
+ [dependencies.dep2]
+ git = '{}'
+ "#, git1.url(), git2.url()))
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs()
+ .with_stderr(&format!("[UPDATING] git repository `[..]`\n\
+ [UPDATING] git repository `[..]`\n\
+ [COMPILING] [..] v0.5.0 ([..])\n\
+ [COMPILING] [..] v0.5.0 ([..])\n\
+ [COMPILING] foo v0.5.0 ({})\n\
+ [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]\n",
+ p.url())));
+
+ File::create(&git1.root().join("src/lib.rs")).unwrap().write_all(br#"
+ pub fn foo() {}
+ "#).unwrap();
+ let repo = git2::Repository::open(&git1.root()).unwrap();
+ git::add(&repo);
+ git::commit(&repo);
+
+ assert_that(p.cargo("update")
+ .arg("-p").arg("dep1"),
+ execs()
+ .with_stderr(&format!("[UPDATING] git repository `{}`\n\
+ [UPDATING] dep1 v0.5.0 ([..]) -> #[..]\n\
+ ", git1.url())));
+}
+
+#[test]
+fn stale_cached_version() {
+ let bar = git::new("meta-dep", |project| {
+ project.file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.0"
+ authors = []
+ "#)
+ .file("src/lib.rs", "pub fn bar() -> i32 { 1 }")
+ }).unwrap();
+
+ // Update the git database in the cache with the current state of the git
+ // repo
+ let foo = project("foo")
+ .file("Cargo.toml", &format!(r#"
+ [project]
+ name = "foo"
+ version = "0.0.0"
+ authors = []
+
+ [dependencies.bar]
+ git = '{}'
+ "#, bar.url()))
+ .file("src/main.rs", r#"
+ extern crate bar;
+
+ fn main() { assert_eq!(bar::bar(), 1) }
+ "#)
+ .build();
+
+ assert_that(foo.cargo("build"), execs().with_status(0));
+ assert_that(foo.process(&foo.bin("foo")), execs().with_status(0));
+
+ // Update the repo, and simulate someone else updating the lockfile and then
+ // us pulling it down.
+ File::create(&bar.root().join("src/lib.rs")).unwrap().write_all(br#"
+ pub fn bar() -> i32 { 1 + 0 }
+ "#).unwrap();
+ let repo = git2::Repository::open(&bar.root()).unwrap();
+ git::add(&repo);
+ git::commit(&repo);
+
+ sleep_ms(1000);
+
+ let rev = repo.revparse_single("HEAD").unwrap().id();
+
+ File::create(&foo.root().join("Cargo.lock")).unwrap().write_all(format!(r#"
+ [[package]]
+ name = "foo"
+ version = "0.0.0"
+ dependencies = [
+ 'bar 0.0.0 (git+{url}#{hash})'
+ ]
+
+ [[package]]
+ name = "bar"
+ version = "0.0.0"
+ source = 'git+{url}#{hash}'
+ "#, url = bar.url(), hash = rev).as_bytes()).unwrap();
+
+ // Now build!
+ assert_that(foo.cargo("build"),
+ execs().with_status(0)
+ .with_stderr(&format!("\
+[UPDATING] git repository `{bar}`
+[COMPILING] bar v0.0.0 ({bar}#[..])
+[COMPILING] foo v0.0.0 ({foo})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+", bar = bar.url(), foo = foo.url())));
+ assert_that(foo.process(&foo.bin("foo")), execs().with_status(0));
+}
+
+#[test]
+fn dep_with_changed_submodule() {
+ let project = project("foo");
+ let git_project = git::new("dep1", |project| {
+ project
+ .file("Cargo.toml", r#"
+ [package]
+ name = "dep1"
+ version = "0.5.0"
+ authors = ["carlhuda@example.com"]
+ "#)
+ }).unwrap();
+
+ let git_project2 = git::new("dep2", |project| {
+ project
+ .file("lib.rs", "pub fn dep() -> &'static str { \"project2\" }")
+ }).unwrap();
+
+ let git_project3 = git::new("dep3", |project| {
+ project
+ .file("lib.rs", "pub fn dep() -> &'static str { \"project3\" }")
+ }).unwrap();
+
+ let repo = git2::Repository::open(&git_project.root()).unwrap();
+ let mut sub = git::add_submodule(&repo, &git_project2.url().to_string(),
+ Path::new("src"));
+ git::commit(&repo);
+
+ let p = project
+ .file("Cargo.toml", &format!(r#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+ [dependencies.dep1]
+ git = '{}'
+ "#, git_project.url()))
+ .file("src/main.rs", "
+ extern crate dep1;
+ pub fn main() { println!(\"{}\", dep1::dep()) }
+ ")
+ .build();
+
+ println!("first run");
+ assert_that(p.cargo("run"), execs()
+ .with_stderr("[UPDATING] git repository `[..]`\n\
+ [COMPILING] dep1 v0.5.0 ([..])\n\
+ [COMPILING] foo v0.5.0 ([..])\n\
+ [FINISHED] dev [unoptimized + debuginfo] target(s) in \
+ [..]\n\
+ [RUNNING] `target[/]debug[/]foo[EXE]`\n")
+ .with_stdout("project2\n")
+ .with_status(0));
+
+ File::create(&git_project.root().join(".gitmodules")).unwrap()
+ .write_all(format!("[submodule \"src\"]\n\tpath = src\n\turl={}",
+ git_project3.url()).as_bytes()).unwrap();
+
+ // Sync the submodule and reset it to the new remote.
+ sub.sync().unwrap();
+ {
+ let subrepo = sub.open().unwrap();
+ subrepo.remote_add_fetch("origin",
+ "refs/heads/*:refs/heads/*").unwrap();
+ subrepo.remote_set_url("origin",
+ &git_project3.url().to_string()).unwrap();
+ let mut origin = subrepo.find_remote("origin").unwrap();
+ origin.fetch(&[], None, None).unwrap();
+ let id = subrepo.refname_to_id("refs/remotes/origin/master").unwrap();
+ let obj = subrepo.find_object(id, None).unwrap();
+ subrepo.reset(&obj, git2::ResetType::Hard, None).unwrap();
+ }
+ sub.add_to_index(true).unwrap();
+ git::add(&repo);
+ git::commit(&repo);
+
+ sleep_ms(1000);
+ // Update the dependency and carry on!
+ println!("update");
+ assert_that(p.cargo("update").arg("-v"),
+ execs()
+ .with_stderr("")
+ .with_stderr(&format!("[UPDATING] git repository `{}`\n\
+ [UPDATING] dep1 v0.5.0 ([..]) -> #[..]\n\
+ ", git_project.url())));
+
+ println!("last run");
+ assert_that(p.cargo("run"), execs()
+ .with_stderr("[COMPILING] dep1 v0.5.0 ([..])\n\
+ [COMPILING] foo v0.5.0 ([..])\n\
+ [FINISHED] dev [unoptimized + debuginfo] target(s) in \
+ [..]\n\
+ [RUNNING] `target[/]debug[/]foo[EXE]`\n")
+ .with_stdout("project3\n")
+ .with_status(0));
+}
+
+#[test]
+fn dev_deps_with_testing() {
+ let p2 = git::new("bar", |project| {
+ project.file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+ "#)
+ .file("src/lib.rs", r#"
+ pub fn gimme() -> &'static str { "zoidberg" }
+ "#)
+ }).unwrap();
+
+ let p = project("foo")
+ .file("Cargo.toml", &format!(r#"
+ [project]
+
+ name = "foo"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+
+ [dev-dependencies.bar]
+ version = "0.5.0"
+ git = '{}'
+ "#, p2.url()))
+ .file("src/main.rs", r#"
+ fn main() {}
+
+ #[cfg(test)]
+ mod tests {
+ extern crate bar;
+ #[test] fn foo() { bar::gimme(); }
+ }
+ "#)
+ .build();
+
+ // Generate a lockfile which did not use `bar` to compile, but had to update
+ // `bar` to generate the lockfile
+ assert_that(p.cargo("build"),
+ execs().with_stderr(&format!("\
+[UPDATING] git repository `{bar}`
+[COMPILING] foo v0.5.0 ({url})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+", url = p.url(), bar = p2.url())));
+
+ // Make sure we use the previous resolution of `bar` instead of updating it
+ // a second time.
+ assert_that(p.cargo("test"),
+ execs().with_stderr("\
+[COMPILING] [..] v0.5.0 ([..])
+[COMPILING] [..] v0.5.0 ([..]
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] target[/]debug[/]deps[/]foo-[..][EXE]")
+ .with_stdout_contains("test tests::foo ... ok"));
+}
+
+#[test]
+fn git_build_cmd_freshness() {
+ let foo = git::new("foo", |project| {
+ project.file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.0"
+ authors = []
+ build = "build.rs"
+ "#)
+ .file("build.rs", "fn main() {}")
+ .file("src/lib.rs", "pub fn bar() -> i32 { 1 }")
+ .file(".gitignore", "
+ src/bar.rs
+ ")
+ }).unwrap();
+ foo.root().move_into_the_past();
+
+ sleep_ms(1000);
+
+ assert_that(foo.cargo("build"),
+ execs().with_status(0)
+ .with_stderr(&format!("\
+[COMPILING] foo v0.0.0 ({url})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+", url = foo.url())));
+
+ // Smoke test to make sure it doesn't compile again
+ println!("first pass");
+ assert_that(foo.cargo("build"),
+ execs().with_status(0)
+ .with_stdout(""));
+
+ // Modify an ignored file and make sure we don't rebuild
+ println!("second pass");
+ File::create(&foo.root().join("src/bar.rs")).unwrap();
+ assert_that(foo.cargo("build"),
+ execs().with_status(0)
+ .with_stdout(""));
+}
+
+#[test]
+fn git_name_not_always_needed() {
+ let p2 = git::new("bar", |project| {
+ project.file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+ "#)
+ .file("src/lib.rs", r#"
+ pub fn gimme() -> &'static str { "zoidberg" }
+ "#)
+ }).unwrap();
+
+ let repo = git2::Repository::open(&p2.root()).unwrap();
+ let mut cfg = repo.config().unwrap();
+ let _ = cfg.remove("user.name");
+ let _ = cfg.remove("user.email");
+
+ let p = project("foo")
+ .file("Cargo.toml", &format!(r#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+ authors = []
+
+ [dev-dependencies.bar]
+ git = '{}'
+ "#, p2.url()))
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ // Generate a lockfile which did not use `bar` to compile, but had to update
+ // `bar` to generate the lockfile
+ assert_that(p.cargo("build"),
+ execs().with_stderr(&format!("\
+[UPDATING] git repository `{bar}`
+[COMPILING] foo v0.5.0 ({url})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+", url = p.url(), bar = p2.url())));
+}
+
+#[test]
+fn git_repo_changing_no_rebuild() {
+ let bar = git::new("bar", |project| {
+ project.file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+ "#)
+ .file("src/lib.rs", "pub fn bar() -> i32 { 1 }")
+ }).unwrap();
+
+ // Lock p1 to the first rev in the git repo
+ let p1 = project("p1")
+ .file("Cargo.toml", &format!(r#"
+ [project]
+ name = "p1"
+ version = "0.5.0"
+ authors = []
+ build = 'build.rs'
+ [dependencies.bar]
+ git = '{}'
+ "#, bar.url()))
+ .file("src/main.rs", "fn main() {}")
+ .file("build.rs", "fn main() {}")
+ .build();
+ p1.root().move_into_the_past();
+ assert_that(p1.cargo("build"),
+ execs().with_stderr(&format!("\
+[UPDATING] git repository `{bar}`
+[COMPILING] [..]
+[COMPILING] [..]
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+", bar = bar.url())));
+
+ // Make a commit to lock p2 to a different rev
+ File::create(&bar.root().join("src/lib.rs")).unwrap().write_all(br#"
+ pub fn bar() -> i32 { 2 }
+ "#).unwrap();
+ let repo = git2::Repository::open(&bar.root()).unwrap();
+ git::add(&repo);
+ git::commit(&repo);
+
+ // Lock p2 to the second rev
+ let p2 = project("p2")
+ .file("Cargo.toml", &format!(r#"
+ [project]
+ name = "p2"
+ version = "0.5.0"
+ authors = []
+ [dependencies.bar]
+ git = '{}'
+ "#, bar.url()))
+ .file("src/main.rs", "fn main() {}")
+ .build();
+ assert_that(p2.cargo("build"),
+ execs().with_stderr(&format!("\
+[UPDATING] git repository `{bar}`
+[COMPILING] [..]
+[COMPILING] [..]
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+", bar = bar.url())));
+
+ // And now for the real test! Make sure that p1 doesn't get rebuilt
+ // even though the git repo has changed.
+ assert_that(p1.cargo("build"),
+ execs().with_stdout(""));
+}
+
+#[test]
+fn git_dep_build_cmd() {
+ let p = git::new("foo", |project| {
+ project.file("Cargo.toml", r#"
+ [project]
+
+ name = "foo"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+
+ [dependencies.bar]
+
+ version = "0.5.0"
+ path = "bar"
+
+ [[bin]]
+
+ name = "foo"
+ "#)
+ .file("src/foo.rs",
+ &main_file(r#""{}", bar::gimme()"#, &["bar"]))
+ .file("bar/Cargo.toml", r#"
+ [project]
+
+ name = "bar"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+ build = "build.rs"
+
+ [lib]
+ name = "bar"
+ path = "src/bar.rs"
+ "#)
+ .file("bar/src/bar.rs.in", r#"
+ pub fn gimme() -> i32 { 0 }
+ "#)
+ .file("bar/build.rs", r#"
+ use std::fs;
+ fn main() {
+ fs::copy("src/bar.rs.in", "src/bar.rs").unwrap();
+ }
+ "#)
+ }).unwrap();
+
+ p.root().join("bar").move_into_the_past();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0));
+
+ assert_that(process(&p.bin("foo")),
+ execs().with_stdout("0\n"));
+
+ // Touching bar.rs.in should cause the `build` command to run again.
+ fs::File::create(&p.root().join("bar/src/bar.rs.in")).unwrap()
+ .write_all(b"pub fn gimme() -> i32 { 1 }").unwrap();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0));
+
+ assert_that(process(&p.bin("foo")),
+ execs().with_stdout("1\n"));
+}
+
+#[test]
+fn fetch_downloads() {
+ let bar = git::new("bar", |project| {
+ project.file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+ "#)
+ .file("src/lib.rs", "pub fn bar() -> i32 { 1 }")
+ }).unwrap();
+
+ let p = project("p1")
+ .file("Cargo.toml", &format!(r#"
+ [project]
+ name = "p1"
+ version = "0.5.0"
+ authors = []
+ [dependencies.bar]
+ git = '{}'
+ "#, bar.url()))
+ .file("src/main.rs", "fn main() {}")
+ .build();
+ assert_that(p.cargo("fetch"),
+ execs().with_status(0).with_stderr(&format!("\
+[UPDATING] git repository `{url}`
+", url = bar.url())));
+
+ assert_that(p.cargo("fetch"),
+ execs().with_status(0).with_stdout(""));
+}
+
+#[test]
+fn warnings_in_git_dep() {
+ let bar = git::new("bar", |project| {
+ project.file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+ "#)
+ .file("src/lib.rs", "fn unused() {}")
+ }).unwrap();
+
+ let p = project("foo")
+ .file("Cargo.toml", &format!(r#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+ authors = []
+ [dependencies.bar]
+ git = '{}'
+ "#, bar.url()))
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs()
+ .with_stderr(&format!("[UPDATING] git repository `{}`\n\
+ [COMPILING] bar v0.5.0 ({}#[..])\n\
+ [COMPILING] foo v0.5.0 ({})\n\
+ [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]\n",
+ bar.url(),
+ bar.url(),
+ p.url())));
+}
+
+#[test]
+fn update_ambiguous() {
+ let foo1 = git::new("foo1", |project| {
+ project.file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+ "#)
+ .file("src/lib.rs", "")
+ }).unwrap();
+ let foo2 = git::new("foo2", |project| {
+ project.file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.6.0"
+ authors = ["wycats@example.com"]
+ "#)
+ .file("src/lib.rs", "")
+ }).unwrap();
+ let bar = git::new("bar", |project| {
+ project.file("Cargo.toml", &format!(r#"
+ [package]
+ name = "bar"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+
+ [dependencies.foo]
+ git = '{}'
+ "#, foo2.url()))
+ .file("src/lib.rs", "")
+ }).unwrap();
+
+ let p = project("project")
+ .file("Cargo.toml", &format!(r#"
+ [project]
+ name = "project"
+ version = "0.5.0"
+ authors = []
+ [dependencies.foo]
+ git = '{}'
+ [dependencies.bar]
+ git = '{}'
+ "#, foo1.url(), bar.url()))
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("generate-lockfile"), execs().with_status(0));
+ assert_that(p.cargo("update")
+ .arg("-p").arg("foo"),
+ execs().with_status(101)
+ .with_stderr("\
+[ERROR] There are multiple `foo` packages in your project, and the specification `foo` \
+is ambiguous.
+Please re-run this command with `-p <spec>` where `<spec>` is one of the \
+following:
+ foo:0.[..].0
+ foo:0.[..].0
+"));
+}
+
+#[test]
+fn update_one_dep_in_repo_with_many_deps() {
+ let foo = git::new("foo", |project| {
+ project.file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+ "#)
+ .file("src/lib.rs", "")
+ .file("a/Cargo.toml", r#"
+ [package]
+ name = "a"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+ "#)
+ .file("a/src/lib.rs", "")
+ }).unwrap();
+
+ let p = project("project")
+ .file("Cargo.toml", &format!(r#"
+ [project]
+ name = "project"
+ version = "0.5.0"
+ authors = []
+ [dependencies.foo]
+ git = '{}'
+ [dependencies.a]
+ git = '{}'
+ "#, foo.url(), foo.url()))
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("generate-lockfile"), execs().with_status(0));
+ assert_that(p.cargo("update")
+ .arg("-p").arg("foo"),
+ execs().with_status(0)
+ .with_stderr(&format!("\
+[UPDATING] git repository `{}`
+", foo.url())));
+}
+
+#[test]
+fn switch_deps_does_not_update_transitive() {
+ let transitive = git::new("transitive", |project| {
+ project.file("Cargo.toml", r#"
+ [package]
+ name = "transitive"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+ "#)
+ .file("src/lib.rs", "")
+ }).unwrap();
+ let dep1 = git::new("dep1", |project| {
+ project.file("Cargo.toml", &format!(r#"
+ [package]
+ name = "dep"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+
+ [dependencies.transitive]
+ git = '{}'
+ "#, transitive.url()))
+ .file("src/lib.rs", "")
+ }).unwrap();
+ let dep2 = git::new("dep2", |project| {
+ project.file("Cargo.toml", &format!(r#"
+ [package]
+ name = "dep"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+
+ [dependencies.transitive]
+ git = '{}'
+ "#, transitive.url()))
+ .file("src/lib.rs", "")
+ }).unwrap();
+
+ let p = project("project")
+ .file("Cargo.toml", &format!(r#"
+ [project]
+ name = "project"
+ version = "0.5.0"
+ authors = []
+ [dependencies.dep]
+ git = '{}'
+ "#, dep1.url()))
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0)
+ .with_stderr(&format!("\
+[UPDATING] git repository `{}`
+[UPDATING] git repository `{}`
+[COMPILING] transitive [..]
+[COMPILING] dep [..]
+[COMPILING] project [..]
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+", dep1.url(), transitive.url())));
+
+ // Update the dependency to point to the second repository, but this
+ // shouldn't update the transitive dependency which is the same.
+ File::create(&p.root().join("Cargo.toml")).unwrap().write_all(format!(r#"
+ [project]
+ name = "project"
+ version = "0.5.0"
+ authors = []
+ [dependencies.dep]
+ git = '{}'
+ "#, dep2.url()).as_bytes()).unwrap();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0)
+ .with_stderr(&format!("\
+[UPDATING] git repository `{}`
+[COMPILING] dep [..]
+[COMPILING] project [..]
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+", dep2.url())));
+}
+
+#[test]
+fn update_one_source_updates_all_packages_in_that_git_source() {
+ let dep = git::new("dep", |project| {
+ project.file("Cargo.toml", r#"
+ [package]
+ name = "dep"
+ version = "0.5.0"
+ authors = []
+
+ [dependencies.a]
+ path = "a"
+ "#)
+ .file("src/lib.rs", "")
+ .file("a/Cargo.toml", r#"
+ [package]
+ name = "a"
+ version = "0.5.0"
+ authors = []
+ "#)
+ .file("a/src/lib.rs", "")
+ }).unwrap();
+
+ let p = project("project")
+ .file("Cargo.toml", &format!(r#"
+ [project]
+ name = "project"
+ version = "0.5.0"
+ authors = []
+ [dependencies.dep]
+ git = '{}'
+ "#, dep.url()))
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0));
+
+ let repo = git2::Repository::open(&dep.root()).unwrap();
+ let rev1 = repo.revparse_single("HEAD").unwrap().id();
+
+ // Just be sure to change a file
+ File::create(&dep.root().join("src/lib.rs")).unwrap().write_all(br#"
+ pub fn bar() -> i32 { 2 }
+ "#).unwrap();
+ git::add(&repo);
+ git::commit(&repo);
+
+ assert_that(p.cargo("update").arg("-p").arg("dep"),
+ execs().with_status(0));
+ let mut lockfile = String::new();
+ File::open(&p.root().join("Cargo.lock")).unwrap()
+ .read_to_string(&mut lockfile).unwrap();
+ assert!(!lockfile.contains(&rev1.to_string()),
+ "{} in {}", rev1, lockfile);
+}
+
+#[test]
+fn switch_sources() {
+ let a1 = git::new("a1", |project| {
+ project.file("Cargo.toml", r#"
+ [package]
+ name = "a"
+ version = "0.5.0"
+ authors = []
+ "#)
+ .file("src/lib.rs", "")
+ }).unwrap();
+ let a2 = git::new("a2", |project| {
+ project.file("Cargo.toml", r#"
+ [package]
+ name = "a"
+ version = "0.5.1"
+ authors = []
+ "#)
+ .file("src/lib.rs", "")
+ }).unwrap();
+
+ let p = project("project")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "project"
+ version = "0.5.0"
+ authors = []
+ [dependencies.b]
+ path = "b"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .file("b/Cargo.toml", &format!(r#"
+ [project]
+ name = "b"
+ version = "0.5.0"
+ authors = []
+ [dependencies.a]
+ git = '{}'
+ "#, a1.url()))
+ .file("b/src/lib.rs", "pub fn main() {}")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0)
+ .with_stderr("\
+[UPDATING] git repository `file://[..]a1`
+[COMPILING] a v0.5.0 ([..]a1#[..]
+[COMPILING] b v0.5.0 ([..])
+[COMPILING] project v0.5.0 ([..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+
+ File::create(&p.root().join("b/Cargo.toml")).unwrap().write_all(format!(r#"
+ [project]
+ name = "b"
+ version = "0.5.0"
+ authors = []
+ [dependencies.a]
+ git = '{}'
+ "#, a2.url()).as_bytes()).unwrap();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0)
+ .with_stderr("\
+[UPDATING] git repository `file://[..]a2`
+[COMPILING] a v0.5.1 ([..]a2#[..]
+[COMPILING] b v0.5.0 ([..])
+[COMPILING] project v0.5.0 ([..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+}
+
+#[test]
+fn dont_require_submodules_are_checked_out() {
+ let p = project("foo").build();
+ let git1 = git::new("dep1", |p| {
+ p.file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+ authors = []
+ build = "build.rs"
+ "#)
+ .file("build.rs", "fn main() {}")
+ .file("src/lib.rs", "")
+ .file("a/foo", "")
+ }).unwrap();
+ let git2 = git::new("dep2", |p| p).unwrap();
+
+ let repo = git2::Repository::open(&git1.root()).unwrap();
+ let url = path2url(git2.root()).to_string();
+ git::add_submodule(&repo, &url, Path::new("a/submodule"));
+ git::commit(&repo);
+
+ git2::Repository::init(&p.root()).unwrap();
+ let url = path2url(git1.root()).to_string();
+ let dst = paths::home().join("foo");
+ git2::Repository::clone(&url, &dst).unwrap();
+
+ assert_that(git1.cargo("build").arg("-v").cwd(&dst),
+ execs().with_status(0));
+}
+
+#[test]
+fn doctest_same_name() {
+ let a2 = git::new("a2", |p| {
+ p.file("Cargo.toml", r#"
+ [project]
+ name = "a"
+ version = "0.5.0"
+ authors = []
+ "#)
+ .file("src/lib.rs", "pub fn a2() {}")
+ }).unwrap();
+
+ let a1 = git::new("a1", |p| {
+ p.file("Cargo.toml", &format!(r#"
+ [project]
+ name = "a"
+ version = "0.5.0"
+ authors = []
+ [dependencies]
+ a = {{ git = '{}' }}
+ "#, a2.url()))
+ .file("src/lib.rs", "extern crate a; pub fn a1() {}")
+ }).unwrap();
+
+ let p = project("foo")
+ .file("Cargo.toml", &format!(r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ a = {{ git = '{}' }}
+ "#, a1.url()))
+ .file("src/lib.rs", r#"
+ #[macro_use]
+ extern crate a;
+ "#)
+ .build();
+
+ assert_that(p.cargo("test").arg("-v"),
+ execs().with_status(0));
+}
+
+#[test]
+fn lints_are_suppressed() {
+ let a = git::new("a", |p| {
+ p.file("Cargo.toml", r#"
+ [project]
+ name = "a"
+ version = "0.5.0"
+ authors = []
+ "#)
+ .file("src/lib.rs", "
+ use std::option;
+ ")
+ }).unwrap();
+
+ let p = project("foo")
+ .file("Cargo.toml", &format!(r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ a = {{ git = '{}' }}
+ "#, a.url()))
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr("\
+[UPDATING] git repository `[..]`
+[COMPILING] a v0.5.0 ([..])
+[COMPILING] foo v0.0.1 ([..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+}
+
+#[test]
+fn denied_lints_are_allowed() {
+ let a = git::new("a", |p| {
+ p.file("Cargo.toml", r#"
+ [project]
+ name = "a"
+ version = "0.5.0"
+ authors = []
+ "#)
+ .file("src/lib.rs", "
+ #![deny(warnings)]
+ use std::option;
+ ")
+ }).unwrap();
+
+ let p = project("foo")
+ .file("Cargo.toml", &format!(r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ a = {{ git = '{}' }}
+ "#, a.url()))
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr("\
+[UPDATING] git repository `[..]`
+[COMPILING] a v0.5.0 ([..])
+[COMPILING] foo v0.0.1 ([..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+}
+
+#[test]
+fn add_a_git_dep() {
+ let git = git::new("git", |p| {
+ p.file("Cargo.toml", r#"
+ [project]
+ name = "git"
+ version = "0.5.0"
+ authors = []
+ "#)
+ .file("src/lib.rs", "")
+ }).unwrap();
+
+ let p = project("foo")
+ .file("Cargo.toml", &format!(r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ a = {{ path = 'a' }}
+ git = {{ git = '{}' }}
+ "#, git.url()))
+ .file("src/lib.rs", "")
+ .file("a/Cargo.toml", r#"
+ [package]
+ name = "a"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("a/src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"), execs().with_status(0));
+
+ File::create(p.root().join("a/Cargo.toml")).unwrap().write_all(format!(r#"
+ [package]
+ name = "a"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ git = {{ git = '{}' }}
+ "#, git.url()).as_bytes()).unwrap();
+
+ assert_that(p.cargo("build"), execs().with_status(0));
+}
+
+#[test]
+fn two_at_rev_instead_of_tag() {
+ let git = git::new("git", |p| {
+ p.file("Cargo.toml", r#"
+ [project]
+ name = "git1"
+ version = "0.5.0"
+ authors = []
+ "#)
+ .file("src/lib.rs", "")
+ .file("a/Cargo.toml", r#"
+ [project]
+ name = "git2"
+ version = "0.5.0"
+ authors = []
+ "#)
+ .file("a/src/lib.rs", "")
+ }).unwrap();
+
+ // Make a tag corresponding to the current HEAD
+ let repo = git2::Repository::open(&git.root()).unwrap();
+ let head = repo.head().unwrap().target().unwrap();
+ repo.tag("v0.1.0",
+ &repo.find_object(head, None).unwrap(),
+ &repo.signature().unwrap(),
+ "make a new tag",
+ false).unwrap();
+
+ let p = project("foo")
+ .file("Cargo.toml", &format!(r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ git1 = {{ git = '{0}', rev = 'v0.1.0' }}
+ git2 = {{ git = '{0}', rev = 'v0.1.0' }}
+ "#, git.url()))
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("generate-lockfile"), execs().with_status(0));
+ assert_that(p.cargo("build").arg("-v"), execs().with_status(0));
+}
+
+#[test]
+#[ignore] // accesses crates.io
+fn include_overrides_gitignore() {
+ let p = git::new("reduction", |repo| {
+ repo.file("Cargo.toml", r#"
+ [package]
+ name = "reduction"
+ version = "0.5.0"
+ authors = ["pnkfelix"]
+ build = "tango-build.rs"
+ include = ["src/lib.rs", "src/incl.rs", "src/mod.md", "tango-build.rs", "Cargo.toml"]
+
+ [build-dependencies]
+ filetime = "0.1"
+ "#)
+ .file(".gitignore", r#"
+ target
+ Cargo.lock
+ # Below files represent generated code, thus not managed by `git`
+ src/incl.rs
+ src/not_incl.rs
+ "#)
+ .file("tango-build.rs", r#"
+ extern crate filetime;
+ use filetime::FileTime;
+ use std::fs::{self, File};
+
+ fn main() {
+ // generate files, or bring their timestamps into sync.
+ let source = "src/mod.md";
+
+ let metadata = fs::metadata(source).unwrap();
+ let mtime = FileTime::from_last_modification_time(&metadata);
+ let atime = FileTime::from_last_access_time(&metadata);
+
+ // sync time stamps for generated files with time stamp of source file.
+
+ let files = ["src/not_incl.rs", "src/incl.rs"];
+ for file in files.iter() {
+ File::create(file).unwrap();
+ filetime::set_file_times(file, atime, mtime).unwrap();
+ }
+ }
+ "#)
+ .file("src/lib.rs", r#"
+ mod not_incl;
+ mod incl;
+ "#)
+ .file("src/mod.md", r#"
+ (The content of this file does not matter since we are not doing real codegen.)
+ "#)
+ }).unwrap();
+
+ println!("build 1: all is new");
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(0)
+ .with_stderr("\
+[UPDATING] registry `[..]`
+[DOWNLOADING] filetime [..]
+[DOWNLOADING] libc [..]
+[COMPILING] libc [..]
+[RUNNING] `rustc --crate-name libc [..]`
+[COMPILING] filetime [..]
+[RUNNING] `rustc --crate-name filetime [..]`
+[COMPILING] reduction [..]
+[RUNNING] `rustc --crate-name build_script_tango_build tango-build.rs --crate-type bin [..]`
+[RUNNING] `[..][/]build-script-tango-build`
+[RUNNING] `rustc --crate-name reduction src[/]lib.rs --crate-type lib [..]`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+
+ println!("build 2: nothing changed; file timestamps reset by build script");
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(0)
+ .with_stderr("\
+[FRESH] libc [..]
+[FRESH] filetime [..]
+[FRESH] reduction [..]
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+
+ println!("build 3: touch `src/not_incl.rs`; expect build script *not* re-run");
+ sleep_ms(1000);
+ File::create(p.root().join("src").join("not_incl.rs")).unwrap();
+
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(0)
+ .with_stderr("\
+[FRESH] libc [..]
+[FRESH] filetime [..]
+[COMPILING] reduction [..]
+[RUNNING] `rustc --crate-name reduction src[/]lib.rs --crate-type lib [..]`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+
+ // This final case models the bug from rust-lang/cargo#4135: an
+ // explicitly included file should cause a build-script re-run,
+ // even if that same file is matched by `.gitignore`.
+ println!("build 4: touch `src/incl.rs`; expect build script re-run");
+ sleep_ms(1000);
+ File::create(p.root().join("src").join("incl.rs")).unwrap();
+
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(0)
+ .with_stderr("\
+[FRESH] libc [..]
+[FRESH] filetime [..]
+[COMPILING] reduction [..]
+[RUNNING] `[..][/]build-script-tango-build`
+[RUNNING] `rustc --crate-name reduction src[/]lib.rs --crate-type lib [..]`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+}
+
+#[test]
+fn invalid_git_dependency_manifest() {
+ let project = project("foo");
+ let git_project = git::new("dep1", |project| {
+ project
+ .file("Cargo.toml", r#"
+ [project]
+
+ name = "dep1"
+ version = "0.5.0"
+ authors = ["carlhuda@example.com"]
+ categories = ["algorithms"]
+ categories = ["algorithms"]
+
+ [lib]
+
+ name = "dep1"
+ "#)
+ .file("src/dep1.rs", r#"
+ pub fn hello() -> &'static str {
+ "hello world"
+ }
+ "#)
+ }).unwrap();
+
+ let project = project
+ .file("Cargo.toml", &format!(r#"
+ [project]
+
+ name = "foo"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+
+ [dependencies.dep1]
+
+ git = '{}'
+ "#, git_project.url()))
+ .file("src/main.rs", &main_file(r#""{}", dep1::hello()"#, &["dep1"]))
+ .build();
+
+ let git_root = git_project.root();
+
+ assert_that(project.cargo("build"),
+ execs()
+ .with_stderr(&format!("[UPDATING] git repository `{}`\n\
+ error: failed to load source for a dependency on `dep1`\n\
+ \n\
+ Caused by:\n \
+ Unable to update {}\n\
+ \n\
+ Caused by:\n \
+ failed to parse manifest at `[..]`\n\
+ \n\
+ Caused by:\n \
+ could not parse input as TOML\n\
+ \n\
+ Caused by:\n \
+ duplicate key: `categories` for key `project`",
+ path2url(git_root.clone()),
+ path2url(git_root),
+ )));
+}
+
+#[test]
+fn failed_submodule_checkout() {
+ let project = project("foo");
+ let git_project = git::new("dep1", |project| {
+ project
+ .file("Cargo.toml", r#"
+ [package]
+ name = "dep1"
+ version = "0.5.0"
+ authors = [""]
+ "#)
+ }).unwrap();
+
+ let git_project2 = git::new("dep2", |project| {
+ project.file("lib.rs", "")
+ }).unwrap();
+
+ let listener = TcpListener::bind("127.0.0.1:0").unwrap();
+ let addr = listener.local_addr().unwrap();
+ let done = Arc::new(AtomicBool::new(false));
+ let done2 = done.clone();
+
+ let t = thread::spawn(move || {
+ while !done2.load(Ordering::SeqCst) {
+ if let Ok((mut socket, _)) = listener.accept() {
+ drop(socket.write_all(b"foo\r\n"));
+ }
+ }
+ });
+
+ let repo = git2::Repository::open(&git_project2.root()).unwrap();
+ let url = format!("http://{}:{}/", addr.ip(), addr.port());
+ {
+ let mut s = repo.submodule(&url, Path::new("bar"), false).unwrap();
+ let subrepo = s.open().unwrap();
+ let mut cfg = subrepo.config().unwrap();
+ cfg.set_str("user.email", "foo@bar.com").unwrap();
+ cfg.set_str("user.name", "Foo Bar").unwrap();
+ git::commit(&subrepo);
+ s.add_finalize().unwrap();
+ }
+ git::commit(&repo);
+ drop((repo, url));
+
+ let repo = git2::Repository::open(&git_project.root()).unwrap();
+ let url = path2url(git_project2.root()).to_string();
+ git::add_submodule(&repo, &url, Path::new("src"));
+ git::commit(&repo);
+ drop(repo);
+
+ let project = project
+ .file("Cargo.toml", &format!(r#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+ authors = []
+
+ [dependencies]
+ dep1 = {{ git = '{}' }}
+ "#, git_project.url()))
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(project.cargo("build"),
+ execs().with_status(101)
+ .with_stderr_contains(" failed to update submodule `src`")
+ .with_stderr_contains(" failed to update submodule `bar`"));
+ assert_that(project.cargo("build"),
+ execs().with_status(101)
+ .with_stderr_contains(" failed to update submodule `src`")
+ .with_stderr_contains(" failed to update submodule `bar`"));
+
+ done.store(true, Ordering::SeqCst);
+ drop(TcpStream::connect(&addr));
+ t.join().unwrap();
+}
--- /dev/null
+use cargotest;
+use std::fs::{self, File};
+use std::io::prelude::*;
+use std::env;
+
+use cargo::util::ProcessBuilder;
+use cargotest::support::{execs, paths, cargo_exe};
+use hamcrest::{assert_that, existing_file, existing_dir, is_not};
+use tempdir::TempDir;
+
+fn cargo_process(s: &str) -> ProcessBuilder {
+ let mut p = cargotest::process(&cargo_exe());
+ p.arg(s).cwd(&paths::root()).env("HOME", &paths::home());
+ p
+}
+
+#[test]
+fn simple_lib() {
+ assert_that(cargo_process("init").arg("--lib").arg("--vcs").arg("none")
+ .env("USER", "foo"),
+ execs().with_status(0).with_stderr("\
+[CREATED] library project
+"));
+
+ assert_that(&paths::root().join("Cargo.toml"), existing_file());
+ assert_that(&paths::root().join("src/lib.rs"), existing_file());
+ assert_that(&paths::root().join(".gitignore"), is_not(existing_file()));
+
+ assert_that(cargo_process("build"),
+ execs().with_status(0));
+}
+
+#[test]
+fn simple_bin() {
+ let path = paths::root().join("foo");
+ fs::create_dir(&path).unwrap();
+ assert_that(cargo_process("init").arg("--bin").arg("--vcs").arg("none")
+ .env("USER", "foo").cwd(&path),
+ execs().with_status(0).with_stderr("\
+[CREATED] binary (application) project
+"));
+
+ assert_that(&paths::root().join("foo/Cargo.toml"), existing_file());
+ assert_that(&paths::root().join("foo/src/main.rs"), existing_file());
+
+ assert_that(cargo_process("build").cwd(&path),
+ execs().with_status(0));
+ assert_that(&paths::root().join(&format!("foo/target/debug/foo{}",
+ env::consts::EXE_SUFFIX)),
+ existing_file());
+}
+
+#[test]
+fn both_lib_and_bin() {
+ let td = TempDir::new("cargo").unwrap();
+ assert_that(cargo_process("init").arg("--lib").arg("--bin").cwd(td.path())
+ .env("USER", "foo"),
+ execs().with_status(101).with_stderr(
+ "[ERROR] can't specify both lib and binary outputs"));
+}
+
+fn bin_already_exists(explicit: bool, rellocation: &str) {
+ let path = paths::root().join("foo");
+ fs::create_dir_all(&path.join("src")).unwrap();
+
+ let sourcefile_path = path.join(rellocation);
+
+ let content = br#"
+ fn main() {
+ println!("Hello, world 2!");
+ }
+ "#;
+
+ File::create(&sourcefile_path).unwrap().write_all(content).unwrap();
+
+ if explicit {
+ assert_that(cargo_process("init").arg("--bin").arg("--vcs").arg("none")
+ .env("USER", "foo").cwd(&path),
+ execs().with_status(0));
+ } else {
+ assert_that(cargo_process("init").arg("--vcs").arg("none")
+ .env("USER", "foo").cwd(&path),
+ execs().with_status(0));
+ }
+
+ assert_that(&paths::root().join("foo/Cargo.toml"), existing_file());
+ assert_that(&paths::root().join("foo/src/lib.rs"), is_not(existing_file()));
+
+ // Check that our file is not overwritten
+ let mut new_content = Vec::new();
+ File::open(&sourcefile_path).unwrap().read_to_end(&mut new_content).unwrap();
+ assert_eq!(Vec::from(content as &[u8]), new_content);
+}
+
+#[test]
+fn bin_already_exists_explicit() {
+ bin_already_exists(true, "src/main.rs")
+}
+
+#[test]
+fn bin_already_exists_implicit() {
+ bin_already_exists(false, "src/main.rs")
+}
+
+#[test]
+fn bin_already_exists_explicit_nosrc() {
+ bin_already_exists(true, "main.rs")
+}
+
+#[test]
+fn bin_already_exists_implicit_nosrc() {
+ bin_already_exists(false, "main.rs")
+}
+
+#[test]
+fn bin_already_exists_implicit_namenosrc() {
+ bin_already_exists(false, "foo.rs")
+}
+
+#[test]
+fn bin_already_exists_implicit_namesrc() {
+ bin_already_exists(false, "src/foo.rs")
+}
+
+#[test]
+fn confused_by_multiple_lib_files() {
+ let path = paths::root().join("foo");
+ fs::create_dir_all(&path.join("src")).unwrap();
+
+ let sourcefile_path1 = path.join("src/lib.rs");
+
+ File::create(&sourcefile_path1).unwrap().write_all(br#"
+ fn qqq () {
+ println!("Hello, world 2!");
+ }
+ "#).unwrap();
+
+ let sourcefile_path2 = path.join("lib.rs");
+
+ File::create(&sourcefile_path2).unwrap().write_all(br#"
+ fn qqq () {
+ println!("Hello, world 3!");
+ }
+ "#).unwrap();
+
+ assert_that(cargo_process("init").arg("--vcs").arg("none")
+ .env("USER", "foo").cwd(&path),
+ execs().with_status(101).with_stderr("\
+[ERROR] cannot have a project with multiple libraries, found both `src/lib.rs` and `lib.rs`
+"));
+
+ assert_that(&paths::root().join("foo/Cargo.toml"), is_not(existing_file()));
+}
+
+
+#[test]
+fn multibin_project_name_clash() {
+ let path = paths::root().join("foo");
+ fs::create_dir(&path).unwrap();
+
+ let sourcefile_path1 = path.join("foo.rs");
+
+ File::create(&sourcefile_path1).unwrap().write_all(br#"
+ fn main () {
+ println!("Hello, world 2!");
+ }
+ "#).unwrap();
+
+ let sourcefile_path2 = path.join("main.rs");
+
+ File::create(&sourcefile_path2).unwrap().write_all(br#"
+ fn main () {
+ println!("Hello, world 3!");
+ }
+ "#).unwrap();
+
+ assert_that(cargo_process("init").arg("--lib").arg("--vcs").arg("none")
+ .env("USER", "foo").cwd(&path),
+ execs().with_status(101).with_stderr("\
+[ERROR] multiple possible binary sources found:
+ main.rs
+ foo.rs
+cannot automatically generate Cargo.toml as the main target would be ambiguous
+"));
+
+ assert_that(&paths::root().join("foo/Cargo.toml"), is_not(existing_file()));
+}
+
+fn lib_already_exists(rellocation: &str) {
+ let path = paths::root().join("foo");
+ fs::create_dir_all(&path.join("src")).unwrap();
+
+ let sourcefile_path = path.join(rellocation);
+
+ let content = br#"
+ pub fn qqq() {}
+ "#;
+
+ File::create(&sourcefile_path).unwrap().write_all(content).unwrap();
+
+ assert_that(cargo_process("init").arg("--vcs").arg("none")
+ .env("USER", "foo").cwd(&path),
+ execs().with_status(0));
+
+ assert_that(&paths::root().join("foo/Cargo.toml"), existing_file());
+ assert_that(&paths::root().join("foo/src/main.rs"), is_not(existing_file()));
+
+ // Check that our file is not overwritten
+ let mut new_content = Vec::new();
+ File::open(&sourcefile_path).unwrap().read_to_end(&mut new_content).unwrap();
+ assert_eq!(Vec::from(content as &[u8]), new_content);
+}
+
+#[test]
+fn lib_already_exists_src() {
+ lib_already_exists("src/lib.rs")
+}
+
+#[test]
+fn lib_already_exists_nosrc() {
+ lib_already_exists("lib.rs")
+}
+
+#[test]
+fn simple_git() {
+ assert_that(cargo_process("init").arg("--lib")
+ .arg("--vcs")
+ .arg("git")
+ .env("USER", "foo"),
+ execs().with_status(0));
+
+ assert_that(&paths::root().join("Cargo.toml"), existing_file());
+ assert_that(&paths::root().join("src/lib.rs"), existing_file());
+ assert_that(&paths::root().join(".git"), existing_dir());
+ assert_that(&paths::root().join(".gitignore"), existing_file());
+}
+
+#[test]
+fn auto_git() {
+ let td = TempDir::new("cargo").unwrap();
+ let foo = &td.path().join("foo");
+ fs::create_dir_all(&foo).unwrap();
+ assert_that(cargo_process("init").arg("--lib")
+ .cwd(foo.clone())
+ .env("USER", "foo"),
+ execs().with_status(0));
+
+ assert_that(&foo.join("Cargo.toml"), existing_file());
+ assert_that(&foo.join("src/lib.rs"), existing_file());
+ assert_that(&foo.join(".git"), existing_dir());
+ assert_that(&foo.join(".gitignore"), existing_file());
+}
+
+#[test]
+fn invalid_dir_name() {
+ let foo = &paths::root().join("foo.bar");
+ fs::create_dir_all(&foo).unwrap();
+ assert_that(cargo_process("init").cwd(foo.clone())
+ .env("USER", "foo"),
+ execs().with_status(101).with_stderr("\
+[ERROR] Invalid character `.` in crate name: `foo.bar`
+use --name to override crate name
+"));
+
+ assert_that(&foo.join("Cargo.toml"), is_not(existing_file()));
+}
+
+#[test]
+fn reserved_name() {
+ let test = &paths::root().join("test");
+ fs::create_dir_all(&test).unwrap();
+ assert_that(cargo_process("init").cwd(test.clone())
+ .env("USER", "foo"),
+ execs().with_status(101).with_stderr("\
+[ERROR] The name `test` cannot be used as a crate name\n\
+use --name to override crate name
+"));
+
+ assert_that(&test.join("Cargo.toml"), is_not(existing_file()));
+}
+
+#[test]
+fn git_autodetect() {
+ fs::create_dir(&paths::root().join(".git")).unwrap();
+
+ assert_that(cargo_process("init").arg("--lib")
+ .env("USER", "foo"),
+ execs().with_status(0));
+
+
+ assert_that(&paths::root().join("Cargo.toml"), existing_file());
+ assert_that(&paths::root().join("src/lib.rs"), existing_file());
+ assert_that(&paths::root().join(".git"), existing_dir());
+ assert_that(&paths::root().join(".gitignore"), existing_file());
+}
+
+
+#[test]
+fn mercurial_autodetect() {
+ fs::create_dir(&paths::root().join(".hg")).unwrap();
+
+ assert_that(cargo_process("init").arg("--lib")
+ .env("USER", "foo"),
+ execs().with_status(0));
+
+
+ assert_that(&paths::root().join("Cargo.toml"), existing_file());
+ assert_that(&paths::root().join("src/lib.rs"), existing_file());
+ assert_that(&paths::root().join(".git"), is_not(existing_dir()));
+ assert_that(&paths::root().join(".hgignore"), existing_file());
+}
+
+#[test]
+fn gitignore_appended_not_replaced() {
+ fs::create_dir(&paths::root().join(".git")).unwrap();
+
+ File::create(&paths::root().join(".gitignore")).unwrap().write_all(b"qqqqqq\n").unwrap();
+
+ assert_that(cargo_process("init").arg("--lib")
+ .env("USER", "foo"),
+ execs().with_status(0));
+
+
+ assert_that(&paths::root().join("Cargo.toml"), existing_file());
+ assert_that(&paths::root().join("src/lib.rs"), existing_file());
+ assert_that(&paths::root().join(".git"), existing_dir());
+ assert_that(&paths::root().join(".gitignore"), existing_file());
+
+ let mut contents = String::new();
+ File::open(&paths::root().join(".gitignore")).unwrap().read_to_string(&mut contents).unwrap();
+ assert!(contents.contains(r#"qqqqqq"#));
+}
+
+#[test]
+fn gitignore_added_newline_if_required() {
+ fs::create_dir(&paths::root().join(".git")).unwrap();
+
+ File::create(&paths::root().join(".gitignore")).unwrap().write_all(b"first").unwrap();
+
+ assert_that(cargo_process("init").arg("--lib")
+ .env("USER", "foo"),
+ execs().with_status(0));
+
+ assert_that(&paths::root().join(".gitignore"), existing_file());
+
+ let mut contents = String::new();
+ File::open(&paths::root().join(".gitignore")).unwrap().read_to_string(&mut contents).unwrap();
+ assert!(contents.starts_with("first\n"));
+}
+
+#[test]
+fn mercurial_added_newline_if_required() {
+ fs::create_dir(&paths::root().join(".hg")).unwrap();
+
+ File::create(&paths::root().join(".hgignore")).unwrap().write_all(b"first").unwrap();
+
+ assert_that(cargo_process("init").arg("--lib")
+ .env("USER", "foo"),
+ execs().with_status(0));
+
+ assert_that(&paths::root().join(".hgignore"), existing_file());
+
+ let mut contents = String::new();
+ File::open(&paths::root().join(".hgignore")).unwrap().read_to_string(&mut contents).unwrap();
+ assert!(contents.starts_with("first\n"));
+}
+
+#[test]
+fn cargo_lock_gitignored_if_lib1() {
+ fs::create_dir(&paths::root().join(".git")).unwrap();
+
+ assert_that(cargo_process("init").arg("--lib").arg("--vcs").arg("git")
+ .env("USER", "foo"),
+ execs().with_status(0));
+
+ assert_that(&paths::root().join(".gitignore"), existing_file());
+
+ let mut contents = String::new();
+ File::open(&paths::root().join(".gitignore")).unwrap().read_to_string(&mut contents).unwrap();
+ assert!(contents.contains(r#"Cargo.lock"#));
+}
+
+#[test]
+fn cargo_lock_gitignored_if_lib2() {
+ fs::create_dir(&paths::root().join(".git")).unwrap();
+
+ File::create(&paths::root().join("lib.rs")).unwrap().write_all(br#""#).unwrap();
+
+ assert_that(cargo_process("init").arg("--vcs").arg("git")
+ .env("USER", "foo"),
+ execs().with_status(0));
+
+ assert_that(&paths::root().join(".gitignore"), existing_file());
+
+ let mut contents = String::new();
+ File::open(&paths::root().join(".gitignore")).unwrap().read_to_string(&mut contents).unwrap();
+ assert!(contents.contains(r#"Cargo.lock"#));
+}
+
+#[test]
+fn cargo_lock_not_gitignored_if_bin1() {
+ fs::create_dir(&paths::root().join(".git")).unwrap();
+
+ assert_that(cargo_process("init").arg("--vcs").arg("git")
+ .arg("--bin")
+ .env("USER", "foo"),
+ execs().with_status(0));
+
+ assert_that(&paths::root().join(".gitignore"), existing_file());
+
+ let mut contents = String::new();
+ File::open(&paths::root().join(".gitignore")).unwrap().read_to_string(&mut contents).unwrap();
+ assert!(!contents.contains(r#"Cargo.lock"#));
+}
+
+#[test]
+fn cargo_lock_not_gitignored_if_bin2() {
+ fs::create_dir(&paths::root().join(".git")).unwrap();
+
+ File::create(&paths::root().join("main.rs")).unwrap().write_all(br#""#).unwrap();
+
+ assert_that(cargo_process("init").arg("--vcs").arg("git")
+ .env("USER", "foo"),
+ execs().with_status(0));
+
+ assert_that(&paths::root().join(".gitignore"), existing_file());
+
+ let mut contents = String::new();
+ File::open(&paths::root().join(".gitignore")).unwrap().read_to_string(&mut contents).unwrap();
+ assert!(!contents.contains(r#"Cargo.lock"#));
+}
+
+#[test]
+fn with_argument() {
+ assert_that(cargo_process("init").arg("foo").arg("--vcs").arg("none")
+ .env("USER", "foo"),
+ execs().with_status(0));
+ assert_that(&paths::root().join("foo/Cargo.toml"), existing_file());
+}
+
+
+#[test]
+fn unknown_flags() {
+ assert_that(cargo_process("init").arg("foo").arg("--flag"),
+ execs().with_status(1)
+ .with_stderr("\
+[ERROR] Unknown flag: '--flag'
+
+Usage:
+ cargo init [options] [<path>]
+ cargo init -h | --help
+"));
+}
+
+#[cfg(not(windows))]
+#[test]
+fn no_filename() {
+ assert_that(cargo_process("init").arg("/"),
+ execs().with_status(101)
+ .with_stderr("\
+[ERROR] cannot auto-detect project name from path \"/\" ; use --name to override
+".to_string()));
+}
--- /dev/null
+use cargotest;
+use std::fs::{self, File, OpenOptions};
+use std::io::prelude::*;
+
+use cargo::util::ProcessBuilder;
+use cargotest::install::{cargo_home, has_installed_exe};
+use cargotest::support::git;
+use cargotest::support::paths;
+use cargotest::support::registry::Package;
+use cargotest::support::{project, execs};
+use hamcrest::{assert_that, existing_dir, is_not};
+
+fn cargo_process(s: &str) -> ProcessBuilder {
+ let mut p = cargotest::cargo_process();
+ p.arg(s);
+ p
+}
+
+fn pkg(name: &str, vers: &str) {
+ Package::new(name, vers)
+ .file("src/lib.rs", "")
+ .file("src/main.rs", &format!("
+ extern crate {};
+ fn main() {{}}
+ ", name))
+ .publish();
+}
+
+#[test]
+fn simple() {
+ pkg("foo", "0.0.1");
+
+ assert_that(cargo_process("install").arg("foo"),
+ execs().with_status(0).with_stderr(&format!("\
+[UPDATING] registry `[..]`
+[DOWNLOADING] foo v0.0.1 (registry [..])
+[INSTALLING] foo v0.0.1
+[COMPILING] foo v0.0.1
+[FINISHED] release [optimized] target(s) in [..]
+[INSTALLING] {home}[..]bin[..]foo[..]
+warning: be sure to add `[..]` to your PATH to be able to run the installed binaries
+",
+ home = cargo_home().display())));
+ assert_that(cargo_home(), has_installed_exe("foo"));
+
+ assert_that(cargo_process("uninstall").arg("foo"),
+ execs().with_status(0).with_stderr(&format!("\
+[REMOVING] {home}[..]bin[..]foo[..]
+",
+ home = cargo_home().display())));
+ assert_that(cargo_home(), is_not(has_installed_exe("foo")));
+}
+
+#[test]
+fn multiple_pkgs() {
+ pkg("foo", "0.0.1");
+ pkg("bar", "0.0.2");
+
+ assert_that(cargo_process("install").args(&["foo", "bar", "baz"]),
+ execs().with_status(101).with_stderr(&format!("\
+[UPDATING] registry `[..]`
+[DOWNLOADING] foo v0.0.1 (registry `file://[..]`)
+[INSTALLING] foo v0.0.1
+[COMPILING] foo v0.0.1
+[FINISHED] release [optimized] target(s) in [..]
+[INSTALLING] {home}[..]bin[..]foo[..]
+[DOWNLOADING] bar v0.0.2 (registry `file://[..]`)
+[INSTALLING] bar v0.0.2
+[COMPILING] bar v0.0.2
+[FINISHED] release [optimized] target(s) in [..]
+[INSTALLING] {home}[..]bin[..]bar[..]
+error: could not find `baz` in registry `[..]`
+[SUMMARY] Successfully installed foo, bar! Failed to install baz (see error(s) above).
+warning: be sure to add `[..]` to your PATH to be able to run the installed binaries
+error: some crates failed to install
+",
+ home = cargo_home().display())));
+ assert_that(cargo_home(), has_installed_exe("foo"));
+ assert_that(cargo_home(), has_installed_exe("bar"));
+
+ assert_that(cargo_process("uninstall").args(&["foo", "bar"]),
+ execs().with_status(0).with_stderr(&format!("\
+[REMOVING] {home}[..]bin[..]foo[..]
+[REMOVING] {home}[..]bin[..]bar[..]
+[SUMMARY] Successfully uninstalled foo, bar!
+",
+ home = cargo_home().display())));
+
+ assert_that(cargo_home(), is_not(has_installed_exe("foo")));
+ assert_that(cargo_home(), is_not(has_installed_exe("bar")));
+}
+
+#[test]
+fn pick_max_version() {
+ pkg("foo", "0.0.1");
+ pkg("foo", "0.0.2");
+
+ assert_that(cargo_process("install").arg("foo"),
+ execs().with_status(0).with_stderr(&format!("\
+[UPDATING] registry `[..]`
+[DOWNLOADING] foo v0.0.2 (registry [..])
+[INSTALLING] foo v0.0.2
+[COMPILING] foo v0.0.2
+[FINISHED] release [optimized] target(s) in [..]
+[INSTALLING] {home}[..]bin[..]foo[..]
+warning: be sure to add `[..]` to your PATH to be able to run the installed binaries
+",
+ home = cargo_home().display())));
+ assert_that(cargo_home(), has_installed_exe("foo"));
+}
+
+#[test]
+fn missing() {
+ pkg("foo", "0.0.1");
+ assert_that(cargo_process("install").arg("bar"),
+ execs().with_status(101).with_stderr("\
+[UPDATING] registry [..]
+[ERROR] could not find `bar` in registry `[..]`
+"));
+}
+
+#[test]
+fn bad_version() {
+ pkg("foo", "0.0.1");
+ assert_that(cargo_process("install").arg("foo").arg("--vers=0.2.0"),
+ execs().with_status(101).with_stderr("\
+[UPDATING] registry [..]
+[ERROR] could not find `foo` in registry `[..]` with version `=0.2.0`
+"));
+}
+
+#[test]
+fn no_crate() {
+ assert_that(cargo_process("install"),
+ execs().with_status(101).with_stderr("\
+[ERROR] `[..]` is not a crate root; specify a crate to install [..]
+
+Caused by:
+ failed to read `[..]Cargo.toml`
+
+Caused by:
+ [..] (os error [..])
+"));
+}
+
+#[test]
+fn install_location_precedence() {
+ pkg("foo", "0.0.1");
+
+ let root = paths::root();
+ let t1 = root.join("t1");
+ let t2 = root.join("t2");
+ let t3 = root.join("t3");
+ let t4 = cargo_home();
+
+ fs::create_dir(root.join(".cargo")).unwrap();
+ File::create(root.join(".cargo/config")).unwrap().write_all(format!("\
+ [install]
+ root = '{}'
+ ", t3.display()).as_bytes()).unwrap();
+
+ println!("install --root");
+
+ assert_that(cargo_process("install").arg("foo")
+ .arg("--root").arg(&t1)
+ .env("CARGO_INSTALL_ROOT", &t2),
+ execs().with_status(0));
+ assert_that(&t1, has_installed_exe("foo"));
+ assert_that(&t2, is_not(has_installed_exe("foo")));
+
+ println!("install CARGO_INSTALL_ROOT");
+
+ assert_that(cargo_process("install").arg("foo")
+ .env("CARGO_INSTALL_ROOT", &t2),
+ execs().with_status(0));
+ assert_that(&t2, has_installed_exe("foo"));
+ assert_that(&t3, is_not(has_installed_exe("foo")));
+
+ println!("install install.root");
+
+ assert_that(cargo_process("install").arg("foo"),
+ execs().with_status(0));
+ assert_that(&t3, has_installed_exe("foo"));
+ assert_that(&t4, is_not(has_installed_exe("foo")));
+
+ fs::remove_file(root.join(".cargo/config")).unwrap();
+
+ println!("install cargo home");
+
+ assert_that(cargo_process("install").arg("foo"),
+ execs().with_status(0));
+ assert_that(&t4, has_installed_exe("foo"));
+}
+
+#[test]
+fn install_path() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ assert_that(cargo_process("install").arg("--path").arg(p.root()),
+ execs().with_status(0));
+ assert_that(cargo_home(), has_installed_exe("foo"));
+ assert_that(cargo_process("install").arg("--path").arg(".").cwd(p.root()),
+ execs().with_status(101).with_stderr("\
+[INSTALLING] foo v0.1.0 [..]
+[ERROR] binary `foo[..]` already exists in destination as part of `foo v0.1.0 [..]`
+Add --force to overwrite
+"));
+}
+
+#[test]
+fn multiple_crates_error() {
+ let p = git::repo(&paths::root().join("foo"))
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .file("a/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("a/src/main.rs", "fn main() {}")
+ .build();
+
+ assert_that(cargo_process("install").arg("--git").arg(p.url().to_string()),
+ execs().with_status(101).with_stderr("\
+[UPDATING] git repository [..]
+[ERROR] multiple packages with binaries found: bar, foo
+"));
+}
+
+#[test]
+fn multiple_crates_select() {
+ let p = git::repo(&paths::root().join("foo"))
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .file("a/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("a/src/main.rs", "fn main() {}")
+ .build();
+
+ assert_that(cargo_process("install").arg("--git").arg(p.url().to_string())
+ .arg("foo"),
+ execs().with_status(0));
+ assert_that(cargo_home(), has_installed_exe("foo"));
+ assert_that(cargo_home(), is_not(has_installed_exe("bar")));
+
+ assert_that(cargo_process("install").arg("--git").arg(p.url().to_string())
+ .arg("bar"),
+ execs().with_status(0));
+ assert_that(cargo_home(), has_installed_exe("bar"));
+}
+
+#[test]
+fn multiple_crates_auto_binaries() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+
+ [dependencies]
+ bar = { path = "a" }
+ "#)
+ .file("src/main.rs", "extern crate bar; fn main() {}")
+ .file("a/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("a/src/lib.rs", "")
+ .build();
+
+ assert_that(cargo_process("install").arg("--path").arg(p.root()),
+ execs().with_status(0));
+ assert_that(cargo_home(), has_installed_exe("foo"));
+}
+
+#[test]
+fn multiple_crates_auto_examples() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+
+ [dependencies]
+ bar = { path = "a" }
+ "#)
+ .file("src/lib.rs", "extern crate bar;")
+ .file("examples/foo.rs", "
+ extern crate bar;
+ extern crate foo;
+ fn main() {}
+ ")
+ .file("a/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("a/src/lib.rs", "")
+ .build();
+
+ assert_that(cargo_process("install").arg("--path").arg(p.root())
+ .arg("--example=foo"),
+ execs().with_status(0));
+ assert_that(cargo_home(), has_installed_exe("foo"));
+}
+
+#[test]
+fn no_binaries_or_examples() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+
+ [dependencies]
+ bar = { path = "a" }
+ "#)
+ .file("src/lib.rs", "")
+ .file("a/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("a/src/lib.rs", "")
+ .build();
+
+ assert_that(cargo_process("install").arg("--path").arg(p.root()),
+ execs().with_status(101).with_stderr("\
+[ERROR] no packages found with binaries or examples
+"));
+}
+
+#[test]
+fn no_binaries() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("src/lib.rs", "")
+ .file("examples/foo.rs", "fn main() {}")
+ .build();
+
+ assert_that(cargo_process("install").arg("--path").arg(p.root()).arg("foo"),
+ execs().with_status(101).with_stderr("\
+[INSTALLING] foo [..]
+[ERROR] specified package has no binaries
+"));
+}
+
+#[test]
+fn examples() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("src/lib.rs", "")
+ .file("examples/foo.rs", "extern crate foo; fn main() {}")
+ .build();
+
+ assert_that(cargo_process("install").arg("--path").arg(p.root())
+ .arg("--example=foo"),
+ execs().with_status(0));
+ assert_that(cargo_home(), has_installed_exe("foo"));
+}
+
+#[test]
+fn install_twice() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("src/bin/foo-bin1.rs", "fn main() {}")
+ .file("src/bin/foo-bin2.rs", "fn main() {}")
+ .build();
+
+ assert_that(cargo_process("install").arg("--path").arg(p.root()),
+ execs().with_status(0));
+ assert_that(cargo_process("install").arg("--path").arg(p.root()),
+ execs().with_status(101).with_stderr("\
+[INSTALLING] foo v0.1.0 [..]
+[ERROR] binary `foo-bin1[..]` already exists in destination as part of `foo v0.1.0 ([..])`
+binary `foo-bin2[..]` already exists in destination as part of `foo v0.1.0 ([..])`
+Add --force to overwrite
+"));
+}
+
+#[test]
+fn install_force() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ assert_that(cargo_process("install").arg("--path").arg(p.root()),
+ execs().with_status(0));
+
+ let p = project("foo2")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.2.0"
+ authors = []
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ assert_that(cargo_process("install").arg("--force").arg("--path").arg(p.root()),
+ execs().with_status(0).with_stderr(&format!("\
+[INSTALLING] foo v0.2.0 ([..])
+[COMPILING] foo v0.2.0 ([..])
+[FINISHED] release [optimized] target(s) in [..]
+[REPLACING] {home}[..]bin[..]foo[..]
+warning: be sure to add `[..]` to your PATH to be able to run the installed binaries
+",
+ home = cargo_home().display())));
+
+ assert_that(cargo_process("install").arg("--list"),
+ execs().with_status(0).with_stdout("\
+foo v0.2.0 ([..]):
+ foo[..]
+"));
+}
+
+#[test]
+fn install_force_partial_overlap() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("src/bin/foo-bin1.rs", "fn main() {}")
+ .file("src/bin/foo-bin2.rs", "fn main() {}")
+ .build();
+
+ assert_that(cargo_process("install").arg("--path").arg(p.root()),
+ execs().with_status(0));
+
+ let p = project("foo2")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.2.0"
+ authors = []
+ "#)
+ .file("src/bin/foo-bin2.rs", "fn main() {}")
+ .file("src/bin/foo-bin3.rs", "fn main() {}")
+ .build();
+
+ assert_that(cargo_process("install").arg("--force").arg("--path").arg(p.root()),
+ execs().with_status(0).with_stderr(&format!("\
+[INSTALLING] foo v0.2.0 ([..])
+[COMPILING] foo v0.2.0 ([..])
+[FINISHED] release [optimized] target(s) in [..]
+[INSTALLING] {home}[..]bin[..]foo-bin3[..]
+[REPLACING] {home}[..]bin[..]foo-bin2[..]
+warning: be sure to add `[..]` to your PATH to be able to run the installed binaries
+",
+ home = cargo_home().display())));
+
+ assert_that(cargo_process("install").arg("--list"),
+ execs().with_status(0).with_stdout("\
+foo v0.1.0 ([..]):
+ foo-bin1[..]
+foo v0.2.0 ([..]):
+ foo-bin2[..]
+ foo-bin3[..]
+"));
+}
+
+#[test]
+fn install_force_bin() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("src/bin/foo-bin1.rs", "fn main() {}")
+ .file("src/bin/foo-bin2.rs", "fn main() {}")
+ .build();
+
+ assert_that(cargo_process("install").arg("--path").arg(p.root()),
+ execs().with_status(0));
+
+ let p = project("foo2")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.2.0"
+ authors = []
+ "#)
+ .file("src/bin/foo-bin1.rs", "fn main() {}")
+ .file("src/bin/foo-bin2.rs", "fn main() {}")
+ .build();
+
+ assert_that(cargo_process("install").arg("--force")
+ .arg("--bin")
+ .arg("foo-bin2")
+ .arg("--path")
+ .arg(p.root()),
+ execs().with_status(0).with_stderr(&format!("\
+[INSTALLING] foo v0.2.0 ([..])
+[COMPILING] foo v0.2.0 ([..])
+[FINISHED] release [optimized] target(s) in [..]
+[REPLACING] {home}[..]bin[..]foo-bin2[..]
+warning: be sure to add `[..]` to your PATH to be able to run the installed binaries
+",
+ home = cargo_home().display())));
+
+ assert_that(cargo_process("install").arg("--list"),
+ execs().with_status(0).with_stdout("\
+foo v0.1.0 ([..]):
+ foo-bin1[..]
+foo v0.2.0 ([..]):
+ foo-bin2[..]
+"));
+}
+
+#[test]
+fn compile_failure() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("src/main.rs", "")
+ .build();
+
+ assert_that(cargo_process("install").arg("--path").arg(p.root()),
+ execs().with_status(101).with_stderr_contains("\
+[ERROR] failed to compile `foo v0.1.0 ([..])`, intermediate artifacts can be \
+ found at `[..]target`
+
+Caused by:
+ Could not compile `foo`.
+
+To learn more, run the command again with --verbose.
+"));
+}
+
+#[test]
+fn git_repo() {
+ let p = git::repo(&paths::root().join("foo"))
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ // use `--locked` to test that we don't even try to write a lockfile
+ assert_that(cargo_process("install").arg("--locked").arg("--git").arg(p.url().to_string()),
+ execs().with_status(0).with_stderr(&format!("\
+[UPDATING] git repository `[..]`
+[INSTALLING] foo v0.1.0 ([..])
+[COMPILING] foo v0.1.0 ([..])
+[FINISHED] release [optimized] target(s) in [..]
+[INSTALLING] {home}[..]bin[..]foo[..]
+warning: be sure to add `[..]` to your PATH to be able to run the installed binaries
+",
+ home = cargo_home().display())));
+ assert_that(cargo_home(), has_installed_exe("foo"));
+ assert_that(cargo_home(), has_installed_exe("foo"));
+}
+
+#[test]
+fn list() {
+ pkg("foo", "0.0.1");
+ pkg("bar", "0.2.1");
+ pkg("bar", "0.2.2");
+
+ assert_that(cargo_process("install").arg("--list"),
+ execs().with_status(0).with_stdout(""));
+
+ assert_that(cargo_process("install").arg("bar").arg("--vers").arg("=0.2.1"),
+ execs().with_status(0));
+ assert_that(cargo_process("install").arg("foo"),
+ execs().with_status(0));
+ assert_that(cargo_process("install").arg("--list"),
+ execs().with_status(0).with_stdout("\
+bar v0.2.1:
+ bar[..]
+foo v0.0.1:
+ foo[..]
+"));
+}
+
+#[test]
+fn list_error() {
+ pkg("foo", "0.0.1");
+ assert_that(cargo_process("install").arg("foo"),
+ execs().with_status(0));
+ assert_that(cargo_process("install").arg("--list"),
+ execs().with_status(0).with_stdout("\
+foo v0.0.1:
+ foo[..]
+"));
+ let mut worldfile_path = cargo_home();
+ worldfile_path.push(".crates.toml");
+ let mut worldfile = OpenOptions::new()
+ .write(true)
+ .open(worldfile_path)
+ .expect(".crates.toml should be there");
+ worldfile.write_all(b"\x00").unwrap();
+ drop(worldfile);
+ assert_that(cargo_process("install").arg("--list").arg("--verbose"),
+ execs().with_status(101).with_stderr("\
+[ERROR] failed to parse crate metadata at `[..]`
+
+Caused by:
+ invalid TOML found for metadata
+
+Caused by:
+ unexpected character[..]
+"));
+}
+
+#[test]
+fn uninstall_pkg_does_not_exist() {
+ assert_that(cargo_process("uninstall").arg("foo"),
+ execs().with_status(101).with_stderr("\
+[ERROR] package id specification `foo` matched no packages
+"));
+}
+
+#[test]
+fn uninstall_bin_does_not_exist() {
+ pkg("foo", "0.0.1");
+
+ assert_that(cargo_process("install").arg("foo"),
+ execs().with_status(0));
+ assert_that(cargo_process("uninstall").arg("foo").arg("--bin=bar"),
+ execs().with_status(101).with_stderr("\
+[ERROR] binary `bar[..]` not installed as part of `foo v0.0.1`
+"));
+}
+
+#[test]
+fn uninstall_piecemeal() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("src/bin/foo.rs", "fn main() {}")
+ .file("src/bin/bar.rs", "fn main() {}")
+ .build();
+
+ assert_that(cargo_process("install").arg("--path").arg(p.root()),
+ execs().with_status(0));
+ assert_that(cargo_home(), has_installed_exe("foo"));
+ assert_that(cargo_home(), has_installed_exe("bar"));
+
+ assert_that(cargo_process("uninstall").arg("foo").arg("--bin=bar"),
+ execs().with_status(0).with_stderr("\
+[REMOVING] [..]bar[..]
+"));
+
+ assert_that(cargo_home(), has_installed_exe("foo"));
+ assert_that(cargo_home(), is_not(has_installed_exe("bar")));
+
+ assert_that(cargo_process("uninstall").arg("foo").arg("--bin=foo"),
+ execs().with_status(0).with_stderr("\
+[REMOVING] [..]foo[..]
+"));
+ assert_that(cargo_home(), is_not(has_installed_exe("foo")));
+
+ assert_that(cargo_process("uninstall").arg("foo"),
+ execs().with_status(101).with_stderr("\
+[ERROR] package id specification `foo` matched no packages
+"));
+}
+
+#[test]
+fn subcommand_works_out_of_the_box() {
+ Package::new("cargo-foo", "1.0.0")
+ .file("src/main.rs", r#"
+ fn main() {
+ println!("bar");
+ }
+ "#)
+ .publish();
+ assert_that(cargo_process("install").arg("cargo-foo"),
+ execs().with_status(0));
+ assert_that(cargo_process("foo"),
+ execs().with_status(0).with_stdout("bar\n"));
+ assert_that(cargo_process("--list"),
+ execs().with_status(0).with_stdout_contains(" foo\n"));
+}
+
+#[test]
+fn installs_from_cwd_by_default() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ assert_that(cargo_process("install").cwd(p.root()),
+ execs().with_status(0));
+ assert_that(cargo_home(), has_installed_exe("foo"));
+}
+
+#[test]
+fn do_not_rebuilds_on_local_install() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("build").arg("--release"),
+ execs().with_status(0));
+ assert_that(cargo_process("install").arg("--path").arg(p.root()),
+ execs().with_status(0).with_stderr("[INSTALLING] [..]
+[FINISHED] release [optimized] target(s) in [..]
+[INSTALLING] [..]
+warning: be sure to add `[..]` to your PATH to be able to run the installed binaries
+"));
+
+ assert!(p.build_dir().exists());
+ assert!(p.release_bin("foo").exists());
+ assert_that(cargo_home(), has_installed_exe("foo"));
+}
+
+#[test]
+fn reports_unsuccessful_subcommand_result() {
+ Package::new("cargo-fail", "1.0.0")
+ .file("src/main.rs", r#"
+ fn main() {
+ panic!();
+ }
+ "#)
+ .publish();
+ assert_that(cargo_process("install").arg("cargo-fail"),
+ execs().with_status(0));
+ assert_that(cargo_process("--list"),
+ execs().with_status(0).with_stdout_contains(" fail\n"));
+ assert_that(cargo_process("fail"),
+ execs().with_status(101).with_stderr_contains("\
+thread '[..]' panicked at 'explicit panic', [..]
+"));
+}
+
+#[test]
+fn git_with_lockfile() {
+ let p = git::repo(&paths::root().join("foo"))
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+
+ [dependencies]
+ bar = { path = "bar" }
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .file("bar/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("bar/src/lib.rs", "fn main() {}")
+ .file("Cargo.lock", r#"
+ [[package]]
+ name = "foo"
+ version = "0.1.0"
+ dependencies = [ "bar 0.1.0" ]
+
+ [[package]]
+ name = "bar"
+ version = "0.1.0"
+ "#)
+ .build();
+
+ assert_that(cargo_process("install").arg("--git").arg(p.url().to_string()),
+ execs().with_status(0));
+}
+
+#[test]
+fn q_silences_warnings() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ assert_that(cargo_process("install").arg("-q").arg("--path").arg(p.root()),
+ execs().with_status(0).with_stderr(""));
+}
+
+#[test]
+fn readonly_dir() {
+ pkg("foo", "0.0.1");
+
+ let root = paths::root();
+ let dir = &root.join("readonly");
+ fs::create_dir(root.join("readonly")).unwrap();
+ let mut perms = fs::metadata(dir).unwrap().permissions();
+ perms.set_readonly(true);
+ fs::set_permissions(dir, perms).unwrap();
+
+ assert_that(cargo_process("install").arg("foo").cwd(dir),
+ execs().with_status(0));
+ assert_that(cargo_home(), has_installed_exe("foo"));
+}
+
+#[test]
+fn use_path_workspace() {
+ Package::new("foo", "1.0.0").publish();
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+
+ [workspace]
+ members = ["baz"]
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .file("baz/Cargo.toml", r#"
+ [package]
+ name = "baz"
+ version = "0.1.0"
+ authors = []
+
+ [dependencies]
+ foo = "1"
+ "#)
+ .file("baz/src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"), execs().with_status(0));
+ let lock = p.read_lockfile();
+ assert_that(p.cargo("install"), execs().with_status(0));
+ let lock2 = p.read_lockfile();
+ assert!(lock == lock2, "different lockfiles");
+}
+
+#[test]
+fn vers_precise() {
+ pkg("foo", "0.1.1");
+ pkg("foo", "0.1.2");
+
+ assert_that(cargo_process("install").arg("foo").arg("--vers").arg("0.1.1"),
+ execs().with_status(0).with_stderr_contains("\
+[DOWNLOADING] foo v0.1.1 (registry [..])
+"));
+}
+
+#[test]
+fn version_too() {
+ pkg("foo", "0.1.1");
+ pkg("foo", "0.1.2");
+
+ assert_that(cargo_process("install").arg("foo").arg("--version").arg("0.1.1"),
+ execs().with_status(0).with_stderr_contains("\
+ [DOWNLOADING] foo v0.1.1 (registry [..])
+"));
+}
+
+#[test]
+fn not_both_vers_and_version() {
+ pkg("foo", "0.1.1");
+ pkg("foo", "0.1.2");
+
+ assert_that(cargo_process("install").arg("foo").arg("--version").arg("0.1.1").arg("--vers").arg("0.1.2"),
+ execs().with_status(101).with_stderr_contains("\
+error: invalid arguments
+"));
+}
+
+#[test]
+fn legacy_version_requirement() {
+ pkg("foo", "0.1.1");
+
+ assert_that(cargo_process("install").arg("foo").arg("--vers").arg("0.1"),
+ execs().with_status(0).with_stderr_contains("\
+warning: the `--vers` provided, `0.1`, is not a valid semver version
+
+historically Cargo treated this as a semver version requirement accidentally
+and will continue to do so, but this behavior will be removed eventually
+"));
+}
+
+#[test]
+fn test_install_git_cannot_be_a_base_url() {
+ assert_that(cargo_process("install").arg("--git").arg("github.com:rust-lang-nursery/rustfmt.git"),
+ execs().with_status(101).with_stderr("\
+error: invalid url `github.com:rust-lang-nursery/rustfmt.git`: cannot-be-a-base-URLs are not supported
+"));
+}
+
+#[test]
+fn uninstall_multiple_and_specifying_bin() {
+ assert_that(cargo_process("uninstall").args(&["foo", "bar"]).arg("--bin").arg("baz"),
+ execs().with_status(101).with_stderr("\
+error: A binary can only be associated with a single installed package, specifying multiple specs with --bin is redundant.
+"));
+}
+
+#[test]
+fn uninstall_multiple_and_some_pkg_does_not_exist() {
+ pkg("foo", "0.0.1");
+
+ assert_that(cargo_process("install").arg("foo"),
+ execs().with_status(0));
+
+ assert_that(cargo_process("uninstall").args(&["foo", "bar"]),
+ execs().with_status(101).with_stderr(&format!("\
+[REMOVING] {home}[..]bin[..]foo[..]
+error: package id specification `bar` matched no packages
+[SUMMARY] Successfully uninstalled foo! Failed to uninstall bar (see error(s) above).
+error: some packages failed to uninstall
+",
+ home = cargo_home().display())));
+
+ assert_that(cargo_home(), is_not(has_installed_exe("foo")));
+ assert_that(cargo_home(), is_not(has_installed_exe("bar")));
+}
+
+#[test]
+fn custom_target_dir_for_git_source() {
+ let p = git::repo(&paths::root().join("foo"))
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ assert_that(cargo_process("install")
+ .arg("--git").arg(p.url().to_string()),
+ execs().with_status(0));
+ assert_that(&paths::root().join("target/release"),
+ is_not(existing_dir()));
+
+ assert_that(cargo_process("install").arg("--force")
+ .arg("--git").arg(p.url().to_string())
+ .env("CARGO_TARGET_DIR", "target"),
+ execs().with_status(0));
+ assert_that(&paths::root().join("target/release"),
+ existing_dir());
+}
--- /dev/null
+use std::net::TcpListener;
+use std::thread;
+use std::process::Command;
+
+use cargotest::support::{project, execs, cargo_exe};
+use hamcrest::assert_that;
+
+#[test]
+fn jobserver_exists() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("build.rs", r#"
+ use std::env;
+
+ fn main() {
+ let var = env::var("CARGO_MAKEFLAGS").unwrap();
+ let arg = var.split(' ')
+ .find(|p| p.starts_with("--jobserver"))
+ .unwrap();
+ let val = &arg[arg.find('=').unwrap() + 1..];
+ validate(val);
+ }
+
+ #[cfg(unix)]
+ fn validate(s: &str) {
+ use std::fs::File;
+ use std::io::*;
+ use std::os::unix::prelude::*;
+
+ let fds = s.split(',').collect::<Vec<_>>();
+ println!("{}", s);
+ assert_eq!(fds.len(), 2);
+ unsafe {
+ let mut read = File::from_raw_fd(fds[0].parse().unwrap());
+ let mut write = File::from_raw_fd(fds[1].parse().unwrap());
+
+ let mut buf = [0];
+ assert_eq!(read.read(&mut buf).unwrap(), 1);
+ assert_eq!(write.write(&buf).unwrap(), 1);
+ }
+ }
+
+ #[cfg(windows)]
+ fn validate(_: &str) {
+ // a little too complicated for a test...
+ }
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0));
+}
+
+#[test]
+fn makes_jobserver_used() {
+ let make = if cfg!(windows) {"mingw32-make"} else {"make"};
+ if Command::new(make).arg("--version").output().is_err() {
+ return
+ }
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ d1 = { path = "d1" }
+ d2 = { path = "d2" }
+ d3 = { path = "d3" }
+ "#)
+ .file("src/lib.rs", "")
+ .file("d1/Cargo.toml", r#"
+ [package]
+ name = "d1"
+ version = "0.0.1"
+ authors = []
+ build = "../dbuild.rs"
+ "#)
+ .file("d1/src/lib.rs", "")
+ .file("d2/Cargo.toml", r#"
+ [package]
+ name = "d2"
+ version = "0.0.1"
+ authors = []
+ build = "../dbuild.rs"
+ "#)
+ .file("d2/src/lib.rs", "")
+ .file("d3/Cargo.toml", r#"
+ [package]
+ name = "d3"
+ version = "0.0.1"
+ authors = []
+ build = "../dbuild.rs"
+ "#)
+ .file("d3/src/lib.rs", "")
+ .file("dbuild.rs", r#"
+ use std::net::TcpStream;
+ use std::env;
+ use std::io::Read;
+
+ fn main() {
+ let addr = env::var("ADDR").unwrap();
+ let mut stream = TcpStream::connect(addr).unwrap();
+ let mut v = Vec::new();
+ stream.read_to_end(&mut v).unwrap();
+ }
+ "#)
+ .file("Makefile", "\
+all:
+\t+$(CARGO) build
+")
+ .build();
+
+ let l = TcpListener::bind("127.0.0.1:0").unwrap();
+ let addr = l.local_addr().unwrap();
+
+ let child = thread::spawn(move || {
+ let a1 = l.accept().unwrap();
+ let a2 = l.accept().unwrap();
+ l.set_nonblocking(true).unwrap();
+
+ for _ in 0..1000 {
+ assert!(l.accept().is_err());
+ thread::yield_now();
+ }
+
+ drop(a1);
+ l.set_nonblocking(false).unwrap();
+ let a3 = l.accept().unwrap();
+
+ drop((a2, a3));
+ });
+
+ assert_that(p.process(make)
+ .env("CARGO", cargo_exe())
+ .env("ADDR", addr.to_string())
+ .arg("-j2"),
+ execs().with_status(0));
+ child.join().unwrap();
+}
+
+#[test]
+fn jobserver_and_j() {
+ let make = if cfg!(windows) {"mingw32-make"} else {"make"};
+ if Command::new(make).arg("--version").output().is_err() {
+ return
+ }
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/lib.rs", "")
+ .file("Makefile", "\
+all:
+\t+$(CARGO) build -j2
+")
+ .build();
+
+ assert_that(p.process(make)
+ .env("CARGO", cargo_exe())
+ .arg("-j2"),
+ execs().with_status(0).with_stderr("\
+warning: a `-j` argument was passed to Cargo but Cargo is also configured \
+with an external jobserver in its environment, ignoring the `-j` parameter
+[COMPILING] [..]
+[FINISHED] [..]
+"));
+}
--- /dev/null
+extern crate cargo;
+#[macro_use]
+extern crate cargotest;
+extern crate hamcrest;
+extern crate tempdir;
+extern crate bufstream;
+extern crate git2;
+extern crate glob;
+extern crate flate2;
+extern crate tar;
+extern crate libc;
+#[cfg(windows)]
+extern crate winapi;
+#[macro_use]
+extern crate serde_derive;
+extern crate serde_json;
+extern crate toml;
+extern crate url;
+
+
+mod alt_registry;
+mod bad_config;
+mod bad_manifest_path;
+mod bench;
+mod build_auth;
+mod build_lib;
+mod build;
+mod build_script_env;
+mod build_script;
+mod cargo_alias_config;
+mod cargo_features;
+//mod cargo;
+mod cfg;
+mod check;
+mod clean;
+mod concurrent;
+mod config;
+mod cross_compile;
+mod cross_publish;
+mod death;
+mod dep_info;
+mod directory;
+mod doc;
+mod features;
+mod fetch;
+mod freshness;
+mod generate_lockfile;
+mod git;
+mod init;
+mod install;
+mod jobserver;
+mod local_registry;
+mod lockfile_compat;
+mod login;
+mod metadata;
+mod net_config;
+mod new;
+mod overrides;
+mod package;
+mod patch;
+mod path;
+mod plugins;
+mod proc_macro;
+mod profiles;
+mod publish;
+mod read_manifest;
+mod registry;
+mod required_features;
+mod resolve;
+mod run;
+mod rustc;
+mod rustdocflags;
+mod rustdoc;
+mod rustflags;
+mod search;
+mod small_fd_limits;
+mod test;
+mod tool_paths;
+mod verify_project;
+mod version;
+mod warn_on_failure;
+mod workspaces;
--- /dev/null
+use std::fs::{self, File};
+use std::io::prelude::*;
+
+use cargotest::support::paths::{self, CargoPathExt};
+use cargotest::support::registry::Package;
+use cargotest::support::{project, execs};
+use hamcrest::assert_that;
+
+fn setup() {
+ let root = paths::root();
+ t!(fs::create_dir(&root.join(".cargo")));
+ t!(t!(File::create(root.join(".cargo/config"))).write_all(br#"
+ [source.crates-io]
+ registry = 'https://wut'
+ replace-with = 'my-awesome-local-registry'
+
+ [source.my-awesome-local-registry]
+ local-registry = 'registry'
+ "#));
+}
+
+#[test]
+fn simple() {
+ setup();
+ Package::new("foo", "0.0.1")
+ .local(true)
+ .file("src/lib.rs", "pub fn foo() {}")
+ .publish();
+
+ let p = project("bar")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ foo = "0.0.1"
+ "#)
+ .file("src/lib.rs", r#"
+ extern crate foo;
+ pub fn bar() {
+ foo::foo();
+ }
+ "#)
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr(&format!("\
+[UNPACKING] foo v0.0.1 ([..])
+[COMPILING] foo v0.0.1
+[COMPILING] bar v0.0.1 ({dir})
+[FINISHED] [..]
+",
+ dir = p.url())));
+ assert_that(p.cargo("build"), execs().with_status(0).with_stderr("\
+[FINISHED] [..]
+"));
+ assert_that(p.cargo("test"), execs().with_status(0));
+}
+
+#[test]
+fn multiple_versions() {
+ setup();
+ Package::new("foo", "0.0.1").local(true).publish();
+ Package::new("foo", "0.1.0")
+ .local(true)
+ .file("src/lib.rs", "pub fn foo() {}")
+ .publish();
+
+ let p = project("bar")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ foo = "*"
+ "#)
+ .file("src/lib.rs", r#"
+ extern crate foo;
+ pub fn bar() {
+ foo::foo();
+ }
+ "#)
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr(&format!("\
+[UNPACKING] foo v0.1.0 ([..])
+[COMPILING] foo v0.1.0
+[COMPILING] bar v0.0.1 ({dir})
+[FINISHED] [..]
+",
+ dir = p.url())));
+
+ Package::new("foo", "0.2.0")
+ .local(true)
+ .file("src/lib.rs", "pub fn foo() {}")
+ .publish();
+
+ assert_that(p.cargo("update").arg("-v"),
+ execs().with_status(0).with_stderr("\
+[UPDATING] foo v0.1.0 -> v0.2.0
+"));
+}
+
+#[test]
+fn multiple_names() {
+ setup();
+ Package::new("foo", "0.0.1")
+ .local(true)
+ .file("src/lib.rs", "pub fn foo() {}")
+ .publish();
+ Package::new("bar", "0.1.0")
+ .local(true)
+ .file("src/lib.rs", "pub fn bar() {}")
+ .publish();
+
+ let p = project("local")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "local"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ foo = "*"
+ bar = "*"
+ "#)
+ .file("src/lib.rs", r#"
+ extern crate foo;
+ extern crate bar;
+ pub fn local() {
+ foo::foo();
+ bar::bar();
+ }
+ "#)
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr(&format!("\
+[UNPACKING] [..]
+[UNPACKING] [..]
+[COMPILING] [..]
+[COMPILING] [..]
+[COMPILING] local v0.0.1 ({dir})
+[FINISHED] [..]
+",
+ dir = p.url())));
+}
+
+#[test]
+fn interdependent() {
+ setup();
+ Package::new("foo", "0.0.1")
+ .local(true)
+ .file("src/lib.rs", "pub fn foo() {}")
+ .publish();
+ Package::new("bar", "0.1.0")
+ .local(true)
+ .dep("foo", "*")
+ .file("src/lib.rs", "extern crate foo; pub fn bar() {}")
+ .publish();
+
+ let p = project("local")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "local"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ foo = "*"
+ bar = "*"
+ "#)
+ .file("src/lib.rs", r#"
+ extern crate foo;
+ extern crate bar;
+ pub fn local() {
+ foo::foo();
+ bar::bar();
+ }
+ "#)
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr(&format!("\
+[UNPACKING] [..]
+[UNPACKING] [..]
+[COMPILING] foo v0.0.1
+[COMPILING] bar v0.1.0
+[COMPILING] local v0.0.1 ({dir})
+[FINISHED] [..]
+",
+ dir = p.url())));
+}
+
+#[test]
+fn path_dep_rewritten() {
+ setup();
+ Package::new("foo", "0.0.1")
+ .local(true)
+ .file("src/lib.rs", "pub fn foo() {}")
+ .publish();
+ Package::new("bar", "0.1.0")
+ .local(true)
+ .dep("foo", "*")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+
+ [dependencies]
+ foo = { path = "foo", version = "*" }
+ "#)
+ .file("src/lib.rs", "extern crate foo; pub fn bar() {}")
+ .file("foo/Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("foo/src/lib.rs", "pub fn foo() {}")
+ .publish();
+
+ let p = project("local")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "local"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ foo = "*"
+ bar = "*"
+ "#)
+ .file("src/lib.rs", r#"
+ extern crate foo;
+ extern crate bar;
+ pub fn local() {
+ foo::foo();
+ bar::bar();
+ }
+ "#)
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr(&format!("\
+[UNPACKING] [..]
+[UNPACKING] [..]
+[COMPILING] foo v0.0.1
+[COMPILING] bar v0.1.0
+[COMPILING] local v0.0.1 ({dir})
+[FINISHED] [..]
+",
+ dir = p.url())));
+}
+
+#[test]
+fn invalid_dir_bad() {
+ setup();
+ let p = project("local")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "local"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ foo = "*"
+ "#)
+ .file("src/lib.rs", "")
+ .file(".cargo/config", r#"
+ [source.crates-io]
+ registry = 'https://wut'
+ replace-with = 'my-awesome-local-directory'
+
+ [source.my-awesome-local-directory]
+ local-registry = '/path/to/nowhere'
+ "#)
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101).with_stderr("\
+[ERROR] failed to load source for a dependency on `foo`
+
+Caused by:
+ Unable to update registry `https://[..]`
+
+Caused by:
+ failed to update replaced source registry `https://[..]`
+
+Caused by:
+ local registry path is not a directory: [..]path[..]to[..]nowhere
+"));
+}
+
+#[test]
+fn different_directory_replacing_the_registry_is_bad() {
+ setup();
+
+ // Move our test's .cargo/config to a temporary location and publish a
+ // registry package we're going to use first.
+ let config = paths::root().join(".cargo");
+ let config_tmp = paths::root().join(".cargo-old");
+ t!(fs::rename(&config, &config_tmp));
+
+ let p = project("local")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "local"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ foo = "*"
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+
+ // Generate a lock file against the crates.io registry
+ Package::new("foo", "0.0.1").publish();
+ assert_that(p.cargo("build"), execs().with_status(0));
+
+ // Switch back to our directory source, and now that we're replacing
+ // crates.io make sure that this fails because we're replacing with a
+ // different checksum
+ config.rm_rf();
+ t!(fs::rename(&config_tmp, &config));
+ Package::new("foo", "0.0.1")
+ .file("src/lib.rs", "invalid")
+ .local(true)
+ .publish();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101).with_stderr("\
+[ERROR] checksum for `foo v0.0.1` 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 `foo v0.0.1` is the same as when the lockfile was generated
+
+"));
+}
+
+#[test]
+fn crates_io_registry_url_is_optional() {
+ let root = paths::root();
+ t!(fs::create_dir(&root.join(".cargo")));
+ t!(t!(File::create(root.join(".cargo/config"))).write_all(br#"
+ [source.crates-io]
+ replace-with = 'my-awesome-local-registry'
+
+ [source.my-awesome-local-registry]
+ local-registry = 'registry'
+ "#));
+
+ Package::new("foo", "0.0.1")
+ .local(true)
+ .file("src/lib.rs", "pub fn foo() {}")
+ .publish();
+
+ let p = project("bar")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ foo = "0.0.1"
+ "#)
+ .file("src/lib.rs", r#"
+ extern crate foo;
+ pub fn bar() {
+ foo::foo();
+ }
+ "#)
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr(&format!("\
+[UNPACKING] foo v0.0.1 ([..])
+[COMPILING] foo v0.0.1
+[COMPILING] bar v0.0.1 ({dir})
+[FINISHED] [..]
+",
+ dir = p.url())));
+ assert_that(p.cargo("build"), execs().with_status(0).with_stderr("\
+[FINISHED] [..]
+"));
+ assert_that(p.cargo("test"), execs().with_status(0));
+}
--- /dev/null
+use cargotest::support::git;
+use cargotest::support::registry::Package;
+use cargotest::support::{execs, project, lines_match};
+use hamcrest::assert_that;
+
+#[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("foo", "0.1.0").publish();
+
+ let expected_lockfile =
+r#"[[package]]
+name = "foo"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "zzz"
+version = "0.0.1"
+dependencies = [
+ "foo 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[metadata]
+"checksum foo 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "[..]"
+"#;
+
+ let old_lockfile =
+r#"[root]
+name = "zzz"
+version = "0.0.1"
+dependencies = [
+ "foo 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "foo"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+"#;
+
+ let p = project("bar")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "zzz"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ foo = "0.1.0"
+ "#)
+ .file("src/lib.rs", "")
+ .file("Cargo.lock", old_lockfile)
+ .build();
+
+ assert_that(p.cargo(cargo_command),
+ execs().with_status(0));
+
+ let lock = p.read_lockfile();
+ for (l, r) in expected_lockfile.lines().zip(lock.lines()) {
+ assert!(lines_match(l, r), "Lines differ:\n{}\n\n{}", l, r);
+ }
+
+ assert_eq!(lock.lines().count(), expected_lockfile.lines().count());
+}
+
+
+#[test]
+fn frozen_flag_preserves_old_lockfile() {
+ let cksum = Package::new("foo", "0.1.0").publish();
+
+ let old_lockfile = format!(
+ r#"[root]
+name = "zzz"
+version = "0.0.1"
+dependencies = [
+ "foo 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "foo"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[metadata]
+"checksum foo 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "{}"
+"#,
+ cksum,
+ );
+
+ let p = project("bar")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "zzz"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ foo = "0.1.0"
+ "#)
+ .file("src/lib.rs", "")
+ .file("Cargo.lock", &old_lockfile)
+ .build();
+
+ assert_that(p.cargo("build").arg("--locked"),
+ execs().with_status(0));
+
+ let lock = p.read_lockfile();
+ for (l, r) in old_lockfile.lines().zip(lock.lines()) {
+ assert!(lines_match(l, r), "Lines differ:\n{}\n\n{}", l, r);
+ }
+
+ assert_eq!(lock.lines().count(), old_lockfile.lines().count());
+}
+
+
+#[test]
+fn totally_wild_checksums_works() {
+ Package::new("foo", "0.1.0").publish();
+
+ let p = project("bar")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ foo = "0.1.0"
+ "#)
+ .file("src/lib.rs", "")
+ .file("Cargo.lock", r#"
+[[package]]
+name = "bar"
+version = "0.0.1"
+dependencies = [
+ "foo 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "foo"
+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 foo 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "checksum"
+"#);
+
+ let p = p.build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0));
+
+ let lock = p.read_lockfile();
+ assert!(lock.starts_with(r#"
+[[package]]
+name = "bar"
+version = "0.0.1"
+dependencies = [
+ "foo 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "foo"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[metadata]
+"#.trim()));
+}
+
+#[test]
+fn wrong_checksum_is_an_error() {
+ Package::new("foo", "0.1.0").publish();
+
+ let p = project("bar")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ foo = "0.1.0"
+ "#)
+ .file("src/lib.rs", "")
+ .file("Cargo.lock", r#"
+[[package]]
+name = "bar"
+version = "0.0.1"
+dependencies = [
+ "foo 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "foo"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[metadata]
+"checksum foo 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "checksum"
+"#);
+
+ let p = p.build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101).with_stderr("\
+[UPDATING] registry `[..]`
+error: checksum for `foo 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 `foo v0.1.0` is the same as when the lockfile was generated
+
+"));
+}
+
+// If the checksum is unlisted in the lockfile (e.g. <none>) yet we can
+// calculate it (e.g. it's a registry dep), then we should in theory just fill
+// it in.
+#[test]
+fn unlisted_checksum_is_bad_if_we_calculate() {
+ Package::new("foo", "0.1.0").publish();
+
+ let p = project("bar")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ foo = "0.1.0"
+ "#)
+ .file("src/lib.rs", "")
+ .file("Cargo.lock", r#"
+[[package]]
+name = "bar"
+version = "0.0.1"
+dependencies = [
+ "foo 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "foo"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[metadata]
+"checksum foo 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "<none>"
+"#);
+ let p = p.build();
+
+ assert_that(p.cargo("fetch"),
+ execs().with_status(101).with_stderr("\
+[UPDATING] registry `[..]`
+error: checksum for `foo 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
+
+"));
+}
+
+// If the checksum is listed in the lockfile yet we cannot calculate it (e.g.
+// git dependencies as of today), then make sure we choke.
+#[test]
+fn listed_checksum_bad_if_we_cannot_compute() {
+ let git = git::new("foo", |p| {
+ p.file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("src/lib.rs", "")
+ }).unwrap();
+
+ let p = project("bar")
+ .file("Cargo.toml", &format!(r#"
+ [project]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ foo = {{ git = '{}' }}
+ "#, git.url()))
+ .file("src/lib.rs", "")
+ .file("Cargo.lock", &format!(r#"
+[[package]]
+name = "bar"
+version = "0.0.1"
+dependencies = [
+ "foo 0.1.0 (git+{0})"
+]
+
+[[package]]
+name = "foo"
+version = "0.1.0"
+source = "git+{0}"
+
+[metadata]
+"checksum foo 0.1.0 (git+{0})" = "checksum"
+"#, git.url()));
+
+ let p = p.build();
+
+ assert_that(p.cargo("fetch"),
+ execs().with_status(101).with_stderr("\
+[UPDATING] git repository `[..]`
+error: checksum for `foo 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 `foo v0.1.0 ([..])` is the same as when the lockfile was generated
+
+"));
+}
+
+#[test]
+fn current_lockfile_format() {
+ Package::new("foo", "0.1.0").publish();
+
+ let p = project("bar")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ foo = "0.1.0"
+ "#)
+ .file("src/lib.rs", "");
+ let p = p.build();
+
+ assert_that(p.cargo("build"), execs().with_status(0));
+
+ let actual = p.read_lockfile();
+
+ let expected = "\
+[[package]]
+name = \"bar\"
+version = \"0.0.1\"
+dependencies = [
+ \"foo 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)\",
+]
+
+[[package]]
+name = \"foo\"
+version = \"0.1.0\"
+source = \"registry+https://github.com/rust-lang/crates.io-index\"
+
+[metadata]
+\"checksum foo 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)\" = \"[..]\"";
+
+ for (l, r) in expected.lines().zip(actual.lines()) {
+ assert!(lines_match(l, r), "Lines differ:\n{}\n\n{}", l, r);
+ }
+
+ assert_eq!(actual.lines().count(), expected.lines().count());
+}
+
+#[test]
+fn lockfile_without_root() {
+ Package::new("foo", "0.1.0").publish();
+
+ let lockfile = r#"[[package]]
+name = "bar"
+version = "0.0.1"
+dependencies = [
+ "foo 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "foo"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+"#;
+
+ let p = project("bar")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ foo = "0.1.0"
+ "#)
+ .file("src/lib.rs", "")
+ .file("Cargo.lock", lockfile);
+
+ let p = p.build();
+
+ assert_that(p.cargo("build"), execs().with_status(0));
+
+ let lock = p.read_lockfile();
+ assert!(lock.starts_with(lockfile.trim()));
+}
+
+#[test]
+fn locked_correct_error() {
+ Package::new("foo", "0.1.0").publish();
+
+ let p = project("bar")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ foo = "0.1.0"
+ "#)
+ .file("src/lib.rs", "");
+ let p = p.build();
+
+ assert_that(p.cargo("build").arg("--locked"),
+ execs().with_status(101).with_stderr("\
+[UPDATING] registry `[..]`
+error: the lock file needs to be updated but --locked was passed to prevent this
+"));
+}
--- /dev/null
+use std::io::prelude::*;
+use std::fs::{self, File};
+
+use toml;
+use cargotest::{ChannelChanger, cargo_process};
+use cargotest::support::execs;
+use cargotest::support::registry::registry;
+use cargotest::install::cargo_home;
+use cargo::util::config::Config;
+use cargo::core::Shell;
+use hamcrest::{assert_that, existing_file, is_not};
+
+const TOKEN: &str = "test-token";
+const ORIGINAL_TOKEN: &str = "api-token";
+const CONFIG_FILE: &str = r#"
+ [registry]
+ token = "api-token"
+
+ [registries.test-reg]
+ index = "http://dummy_index/"
+"#;
+
+fn setup_old_credentials() {
+ let config = cargo_home().join("config");
+ t!(fs::create_dir_all(config.parent().unwrap()));
+ t!(t!(File::create(&config)).write_all(CONFIG_FILE.as_bytes()));
+}
+
+fn setup_new_credentials() {
+ let config = cargo_home().join("credentials");
+ t!(fs::create_dir_all(config.parent().unwrap()));
+ t!(t!(File::create(&config)).write_all(format!(r#"
+ token = "{token}"
+ "#, token = ORIGINAL_TOKEN)
+ .as_bytes()));
+}
+
+fn check_token(expected_token: &str, registry: Option<&str>) -> bool {
+
+ let credentials = cargo_home().join("credentials");
+ assert_that(&credentials, existing_file());
+
+ let mut contents = String::new();
+ File::open(&credentials).unwrap().read_to_string(&mut contents).unwrap();
+ let toml: toml::Value = contents.parse().unwrap();
+
+ let token = match (registry, toml) {
+ // A registry has been provided, so check that the token exists in a
+ // table for the registry.
+ (Some(registry), toml::Value::Table(table)) => {
+ table.get("registries")
+ .and_then(|registries_table| registries_table.get(registry))
+ .and_then(|registry_table| {
+ match registry_table.get("token") {
+ Some(&toml::Value::String(ref token)) => Some(token.as_str().to_string()),
+ _ => None,
+ }
+ })
+ },
+ // There is no registry provided, so check the global token instead.
+ (None, toml::Value::Table(table)) => {
+ table.get("registry")
+ .and_then(|registry_table| registry_table.get("token"))
+ .and_then(|v| {
+ match v {
+ &toml::Value::String(ref token) => Some(token.as_str().to_string()),
+ _ => None,
+ }
+ })
+ }
+ _ => None
+ };
+
+ if let Some(token_val) = token {
+ token_val == expected_token
+ } else {
+ false
+ }
+}
+
+#[test]
+fn login_with_old_credentials() {
+ setup_old_credentials();
+
+ assert_that(cargo_process().arg("login")
+ .arg("--host").arg(registry().to_string()).arg(TOKEN),
+ execs().with_status(0));
+
+ let config = cargo_home().join("config");
+ assert_that(&config, existing_file());
+
+ let mut contents = String::new();
+ File::open(&config).unwrap().read_to_string(&mut contents).unwrap();
+ assert_eq!(CONFIG_FILE, contents);
+
+ // Ensure that we get the new token for the registry
+ assert!(check_token(TOKEN, None));
+}
+
+#[test]
+fn login_with_new_credentials() {
+ setup_new_credentials();
+
+ assert_that(cargo_process().arg("login")
+ .arg("--host").arg(registry().to_string()).arg(TOKEN),
+ execs().with_status(0));
+
+ let config = cargo_home().join("config");
+ assert_that(&config, is_not(existing_file()));
+
+ // Ensure that we get the new token for the registry
+ assert!(check_token(TOKEN, None));
+}
+
+#[test]
+fn login_with_old_and_new_credentials() {
+ setup_new_credentials();
+ login_with_old_credentials();
+}
+
+#[test]
+fn login_without_credentials() {
+ assert_that(cargo_process().arg("login")
+ .arg("--host").arg(registry().to_string()).arg(TOKEN),
+ execs().with_status(0));
+
+ let config = cargo_home().join("config");
+ assert_that(&config, is_not(existing_file()));
+
+ // Ensure that we get the new token for the registry
+ assert!(check_token(TOKEN, None));
+}
+
+#[test]
+fn new_credentials_is_used_instead_old() {
+ setup_old_credentials();
+ setup_new_credentials();
+
+ assert_that(cargo_process().arg("login")
+ .arg("--host").arg(registry().to_string()).arg(TOKEN),
+ execs().with_status(0));
+
+ let config = Config::new(Shell::new(), cargo_home(), cargo_home());
+
+ let token = config.get_string("registry.token").unwrap().map(|p| p.val);
+ assert_eq!(token.unwrap(), TOKEN);
+}
+
+#[test]
+fn registry_credentials() {
+ setup_old_credentials();
+ setup_new_credentials();
+
+ let reg = "test-reg";
+
+ assert_that(cargo_process().arg("login").masquerade_as_nightly_cargo()
+ .arg("--registry").arg(reg).arg(TOKEN).arg("-Zunstable-options"),
+ execs().with_status(0));
+
+ // Ensure that we have not updated the default token
+ assert!(check_token(ORIGINAL_TOKEN, None));
+
+ // Also ensure that we get the new token for the registry
+ assert!(check_token(TOKEN, Some(reg)));
+}
--- /dev/null
+use hamcrest::assert_that;
+use cargotest::support::registry::Package;
+use cargotest::support::{project, execs, basic_bin_manifest, basic_lib_manifest, main_file};
+
+#[test]
+fn cargo_metadata_simple() {
+ let p = project("foo")
+ .file("src/foo.rs", "")
+ .file("Cargo.toml", &basic_bin_manifest("foo"))
+ .build();
+
+ assert_that(p.cargo("metadata"), execs().with_json(r#"
+ {
+ "packages": [
+ {
+ "name": "foo",
+ "version": "0.5.0",
+ "id": "foo[..]",
+ "source": null,
+ "dependencies": [],
+ "license": null,
+ "license_file": null,
+ "description": null,
+ "targets": [
+ {
+ "kind": [
+ "bin"
+ ],
+ "crate_types": [
+ "bin"
+ ],
+ "name": "foo",
+ "src_path": "[..][/]foo[/]src[/]foo.rs"
+ }
+ ],
+ "features": {},
+ "manifest_path": "[..]Cargo.toml"
+ }
+ ],
+ "workspace_members": ["foo 0.5.0 (path+file:[..]foo)"],
+ "resolve": {
+ "nodes": [
+ {
+ "dependencies": [],
+ "id": "foo 0.5.0 (path+file:[..]foo)"
+ }
+ ],
+ "root": "foo 0.5.0 (path+file:[..]foo)"
+ },
+ "target_directory": "[..]foo[/]target",
+ "version": 1,
+ "workspace_root": "[..][/]foo"
+ }"#));
+}
+
+#[test]
+fn cargo_metadata_warns_on_implicit_version() {
+ let p = project("foo")
+ .file("src/foo.rs", "")
+ .file("Cargo.toml", &basic_bin_manifest("foo"))
+ .build();
+
+ assert_that(p.cargo("metadata"),
+ execs().with_stderr("\
+[WARNING] please specify `--format-version` flag explicitly to avoid compatibility problems"));
+
+ assert_that(p.cargo("metadata").arg("--format-version").arg("1"),
+ execs().with_stderr(""));
+}
+
+#[test]
+fn library_with_several_crate_types() {
+ let p = project("foo")
+ .file("src/lib.rs", "")
+ .file("Cargo.toml", r#"
+[package]
+name = "foo"
+version = "0.5.0"
+
+[lib]
+crate-type = ["lib", "staticlib"]
+ "#)
+ .build();
+
+ assert_that(p.cargo("metadata"), execs().with_json(r#"
+ {
+ "packages": [
+ {
+ "name": "foo",
+ "version": "0.5.0",
+ "id": "foo[..]",
+ "source": null,
+ "dependencies": [],
+ "license": null,
+ "license_file": null,
+ "description": null,
+ "targets": [
+ {
+ "kind": [
+ "lib",
+ "staticlib"
+ ],
+ "crate_types": [
+ "lib",
+ "staticlib"
+ ],
+ "name": "foo",
+ "src_path": "[..][/]foo[/]src[/]lib.rs"
+ }
+ ],
+ "features": {},
+ "manifest_path": "[..]Cargo.toml"
+ }
+ ],
+ "workspace_members": ["foo 0.5.0 (path+file:[..]foo)"],
+ "resolve": {
+ "nodes": [
+ {
+ "dependencies": [],
+ "id": "foo 0.5.0 (path+file:[..]foo)"
+ }
+ ],
+ "root": "foo 0.5.0 (path+file:[..]foo)"
+ },
+ "target_directory": "[..]foo[/]target",
+ "version": 1,
+ "workspace_root": "[..][/]foo"
+ }"#));
+}
+
+#[test]
+fn cargo_metadata_with_deps_and_version() {
+ let p = project("foo")
+ .file("src/foo.rs", "")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+ authors = []
+ license = "MIT"
+ description = "foo"
+
+ [[bin]]
+ name = "foo"
+
+ [dependencies]
+ bar = "*"
+ "#)
+ .build();
+ Package::new("baz", "0.0.1").publish();
+ Package::new("bar", "0.0.1").dep("baz", "0.0.1").publish();
+
+ assert_that(p.cargo("metadata")
+ .arg("-q")
+ .arg("--format-version").arg("1"),
+ execs().with_json(r#"
+ {
+ "packages": [
+ {
+ "dependencies": [],
+ "features": {},
+ "id": "baz 0.0.1 (registry+[..])",
+ "manifest_path": "[..]Cargo.toml",
+ "name": "baz",
+ "source": "registry+[..]",
+ "license": null,
+ "license_file": null,
+ "description": null,
+ "targets": [
+ {
+ "kind": [
+ "lib"
+ ],
+ "crate_types": [
+ "lib"
+ ],
+ "name": "baz",
+ "src_path": "[..]lib.rs"
+ }
+ ],
+ "version": "0.0.1"
+ },
+ {
+ "dependencies": [
+ {
+ "features": [],
+ "kind": null,
+ "name": "baz",
+ "optional": false,
+ "req": "^0.0.1",
+ "source": "registry+[..]",
+ "target": null,
+ "uses_default_features": true,
+ "rename": null
+ }
+ ],
+ "features": {},
+ "id": "bar 0.0.1 (registry+[..])",
+ "manifest_path": "[..]Cargo.toml",
+ "name": "bar",
+ "source": "registry+[..]",
+ "license": null,
+ "license_file": null,
+ "description": null,
+ "targets": [
+ {
+ "kind": [
+ "lib"
+ ],
+ "crate_types": [
+ "lib"
+ ],
+ "name": "bar",
+ "src_path": "[..]lib.rs"
+ }
+ ],
+ "version": "0.0.1"
+ },
+ {
+ "dependencies": [
+ {
+ "features": [],
+ "kind": null,
+ "name": "bar",
+ "optional": false,
+ "req": "*",
+ "source": "registry+[..]",
+ "target": null,
+ "uses_default_features": true,
+ "rename": null
+ }
+ ],
+ "features": {},
+ "id": "foo 0.5.0 (path+file:[..]foo)",
+ "manifest_path": "[..]Cargo.toml",
+ "name": "foo",
+ "source": null,
+ "license": "MIT",
+ "license_file": null,
+ "description": "foo",
+ "targets": [
+ {
+ "kind": [
+ "bin"
+ ],
+ "crate_types": [
+ "bin"
+ ],
+ "name": "foo",
+ "src_path": "[..]foo.rs"
+ }
+ ],
+ "version": "0.5.0"
+ }
+ ],
+ "workspace_members": ["foo 0.5.0 (path+file:[..]foo)"],
+ "resolve": {
+ "nodes": [
+ {
+ "dependencies": [
+ "bar 0.0.1 (registry+[..])"
+ ],
+ "id": "foo 0.5.0 (path+file:[..]foo)"
+ },
+ {
+ "dependencies": [
+ "baz 0.0.1 (registry+[..])"
+ ],
+ "id": "bar 0.0.1 (registry+[..])"
+ },
+ {
+ "dependencies": [],
+ "id": "baz 0.0.1 (registry+[..])"
+ }
+ ],
+ "root": "foo 0.5.0 (path+file:[..]foo)"
+ },
+ "target_directory": "[..]foo[/]target",
+ "version": 1,
+ "workspace_root": "[..][/]foo"
+ }"#));
+}
+
+#[test]
+fn example() {
+ let p = project("foo")
+ .file("src/lib.rs", "")
+ .file("examples/ex.rs", "")
+ .file("Cargo.toml", r#"
+[package]
+name = "foo"
+version = "0.1.0"
+
+[[example]]
+name = "ex"
+ "#)
+ .build();
+
+ assert_that(p.cargo("metadata"), execs().with_json(r#"
+ {
+ "packages": [
+ {
+ "name": "foo",
+ "version": "0.1.0",
+ "id": "foo[..]",
+ "license": null,
+ "license_file": null,
+ "description": null,
+ "source": null,
+ "dependencies": [],
+ "targets": [
+ {
+ "kind": [ "lib" ],
+ "crate_types": [ "lib" ],
+ "name": "foo",
+ "src_path": "[..][/]foo[/]src[/]lib.rs"
+ },
+ {
+ "kind": [ "example" ],
+ "crate_types": [ "bin" ],
+ "name": "ex",
+ "src_path": "[..][/]foo[/]examples[/]ex.rs"
+ }
+ ],
+ "features": {},
+ "manifest_path": "[..]Cargo.toml"
+ }
+ ],
+ "workspace_members": [
+ "foo 0.1.0 (path+file:[..]foo)"
+ ],
+ "resolve": {
+ "root": "foo 0.1.0 (path+file://[..]foo)",
+ "nodes": [
+ {
+ "id": "foo 0.1.0 (path+file:[..]foo)",
+ "dependencies": []
+ }
+ ]
+ },
+ "target_directory": "[..]foo[/]target",
+ "version": 1,
+ "workspace_root": "[..][/]foo"
+ }"#));
+}
+
+#[test]
+fn example_lib() {
+ let p = project("foo")
+ .file("src/lib.rs", "")
+ .file("examples/ex.rs", "")
+ .file("Cargo.toml", r#"
+[package]
+name = "foo"
+version = "0.1.0"
+
+[[example]]
+name = "ex"
+crate-type = ["rlib", "dylib"]
+ "#)
+ .build();
+
+ assert_that(p.cargo("metadata"), execs().with_json(r#"
+ {
+ "packages": [
+ {
+ "name": "foo",
+ "version": "0.1.0",
+ "id": "foo[..]",
+ "license": null,
+ "license_file": null,
+ "description": null,
+ "source": null,
+ "dependencies": [],
+ "targets": [
+ {
+ "kind": [ "lib" ],
+ "crate_types": [ "lib" ],
+ "name": "foo",
+ "src_path": "[..][/]foo[/]src[/]lib.rs"
+ },
+ {
+ "kind": [ "example" ],
+ "crate_types": [ "rlib", "dylib" ],
+ "name": "ex",
+ "src_path": "[..][/]foo[/]examples[/]ex.rs"
+ }
+ ],
+ "features": {},
+ "manifest_path": "[..]Cargo.toml"
+ }
+ ],
+ "workspace_members": [
+ "foo 0.1.0 (path+file:[..]foo)"
+ ],
+ "resolve": {
+ "root": "foo 0.1.0 (path+file://[..]foo)",
+ "nodes": [
+ {
+ "id": "foo 0.1.0 (path+file:[..]foo)",
+ "dependencies": []
+ }
+ ]
+ },
+ "target_directory": "[..]foo[/]target",
+ "version": 1,
+ "workspace_root": "[..][/]foo"
+ }"#));
+}
+
+#[test]
+fn workspace_metadata() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [workspace]
+ members = ["bar", "baz"]
+ "#)
+ .file("bar/Cargo.toml", &basic_lib_manifest("bar"))
+ .file("bar/src/lib.rs", "")
+ .file("baz/Cargo.toml", &basic_lib_manifest("baz"))
+ .file("baz/src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("metadata"), execs().with_status(0).with_json(r#"
+ {
+ "packages": [
+ {
+ "name": "bar",
+ "version": "0.5.0",
+ "id": "bar[..]",
+ "source": null,
+ "dependencies": [],
+ "license": null,
+ "license_file": null,
+ "description": null,
+ "targets": [
+ {
+ "kind": [ "lib" ],
+ "crate_types": [ "lib" ],
+ "name": "bar",
+ "src_path": "[..]bar[/]src[/]lib.rs"
+ }
+ ],
+ "features": {},
+ "manifest_path": "[..]bar[/]Cargo.toml"
+ },
+ {
+ "name": "baz",
+ "version": "0.5.0",
+ "id": "baz[..]",
+ "source": null,
+ "dependencies": [],
+ "license": null,
+ "license_file": null,
+ "description": null,
+ "targets": [
+ {
+ "kind": [ "lib" ],
+ "crate_types": [ "lib" ],
+ "name": "baz",
+ "src_path": "[..]baz[/]src[/]lib.rs"
+ }
+ ],
+ "features": {},
+ "manifest_path": "[..]baz[/]Cargo.toml"
+ }
+ ],
+ "workspace_members": ["baz 0.5.0 (path+file:[..]baz)", "bar 0.5.0 (path+file:[..]bar)"],
+ "resolve": {
+ "nodes": [
+ {
+ "dependencies": [],
+ "id": "baz 0.5.0 (path+file:[..]baz)"
+ },
+ {
+ "dependencies": [],
+ "id": "bar 0.5.0 (path+file:[..]bar)"
+ }
+ ],
+ "root": null
+ },
+ "target_directory": "[..]foo[/]target",
+ "version": 1,
+ "workspace_root": "[..][/]foo"
+ }"#))
+}
+
+#[test]
+fn workspace_metadata_no_deps() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [workspace]
+ members = ["bar", "baz"]
+ "#)
+ .file("bar/Cargo.toml", &basic_lib_manifest("bar"))
+ .file("bar/src/lib.rs", "")
+ .file("baz/Cargo.toml", &basic_lib_manifest("baz"))
+ .file("baz/src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("metadata").arg("--no-deps"), execs().with_status(0).with_json(r#"
+ {
+ "packages": [
+ {
+ "name": "bar",
+ "version": "0.5.0",
+ "id": "bar[..]",
+ "source": null,
+ "dependencies": [],
+ "license": null,
+ "license_file": null,
+ "description": null,
+ "targets": [
+ {
+ "kind": [ "lib" ],
+ "crate_types": [ "lib" ],
+ "name": "bar",
+ "src_path": "[..]bar[/]src[/]lib.rs"
+ }
+ ],
+ "features": {},
+ "manifest_path": "[..]bar[/]Cargo.toml"
+ },
+ {
+ "name": "baz",
+ "version": "0.5.0",
+ "id": "baz[..]",
+ "source": null,
+ "dependencies": [],
+ "license": null,
+ "license_file": null,
+ "description": null,
+ "targets": [
+ {
+ "kind": [ "lib" ],
+ "crate_types": ["lib"],
+ "name": "baz",
+ "src_path": "[..]baz[/]src[/]lib.rs"
+ }
+ ],
+ "features": {},
+ "manifest_path": "[..]baz[/]Cargo.toml"
+ }
+ ],
+ "workspace_members": ["baz 0.5.0 (path+file:[..]baz)", "bar 0.5.0 (path+file:[..]bar)"],
+ "resolve": null,
+ "target_directory": "[..]foo[/]target",
+ "version": 1,
+ "workspace_root": "[..][/]foo"
+ }"#))
+}
+
+#[test]
+fn cargo_metadata_with_invalid_manifest() {
+ let p = project("foo")
+ .file("Cargo.toml", "")
+ .build();
+
+ assert_that(p.cargo("metadata").arg("--format-version").arg("1"),
+ execs().with_status(101).with_stderr("\
+[ERROR] failed to parse manifest at `[..]`
+
+Caused by:
+ virtual manifests must be configured with [workspace]"))
+}
+
+const MANIFEST_OUTPUT: &'static str=
+ r#"
+{
+ "packages": [{
+ "name":"foo",
+ "version":"0.5.0",
+ "id":"foo[..]0.5.0[..](path+file://[..]/foo)",
+ "source":null,
+ "dependencies":[],
+ "license": null,
+ "license_file": null,
+ "description": null,
+ "targets":[{
+ "kind":["bin"],
+ "crate_types":["bin"],
+ "name":"foo",
+ "src_path":"[..][/]foo[/]src[/]foo.rs"
+ }],
+ "features":{},
+ "manifest_path":"[..]Cargo.toml"
+ }],
+ "workspace_members": [ "foo 0.5.0 (path+file:[..]foo)" ],
+ "resolve": null,
+ "target_directory": "[..]foo[/]target",
+ "version": 1,
+ "workspace_root": "[..][/]foo"
+}"#;
+
+#[test]
+fn cargo_metadata_no_deps_path_to_cargo_toml_relative() {
+ let p = project("foo")
+ .file("Cargo.toml", &basic_bin_manifest("foo"))
+ .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
+ .build();
+
+ assert_that(p.cargo("metadata").arg("--no-deps")
+ .arg("--manifest-path").arg("foo/Cargo.toml")
+ .cwd(p.root().parent().unwrap()),
+ execs().with_status(0)
+ .with_json(MANIFEST_OUTPUT));
+}
+
+#[test]
+fn cargo_metadata_no_deps_path_to_cargo_toml_absolute() {
+ let p = project("foo")
+ .file("Cargo.toml", &basic_bin_manifest("foo"))
+ .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
+ .build();
+
+ assert_that(p.cargo("metadata").arg("--no-deps")
+ .arg("--manifest-path").arg(p.root().join("Cargo.toml"))
+ .cwd(p.root().parent().unwrap()),
+ execs().with_status(0)
+ .with_json(MANIFEST_OUTPUT));
+}
+
+#[test]
+fn cargo_metadata_no_deps_path_to_cargo_toml_parent_relative() {
+ let p = project("foo")
+ .file("Cargo.toml", &basic_bin_manifest("foo"))
+ .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
+ .build();
+
+ assert_that(p.cargo("metadata").arg("--no-deps")
+ .arg("--manifest-path").arg("foo")
+ .cwd(p.root().parent().unwrap()),
+ execs().with_status(101)
+ .with_stderr("[ERROR] the manifest-path must be \
+ a path to a Cargo.toml file"));
+}
+
+#[test]
+fn cargo_metadata_no_deps_path_to_cargo_toml_parent_absolute() {
+ let p = project("foo")
+ .file("Cargo.toml", &basic_bin_manifest("foo"))
+ .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
+ .build();
+
+ assert_that(p.cargo("metadata").arg("--no-deps")
+ .arg("--manifest-path").arg(p.root())
+ .cwd(p.root().parent().unwrap()),
+ execs().with_status(101)
+ .with_stderr("[ERROR] the manifest-path must be \
+ a path to a Cargo.toml file"));
+}
+
+#[test]
+fn cargo_metadata_no_deps_cwd() {
+ let p = project("foo")
+ .file("Cargo.toml", &basic_bin_manifest("foo"))
+ .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
+ .build();
+
+ assert_that(p.cargo("metadata").arg("--no-deps")
+ .cwd(p.root()),
+ execs().with_status(0)
+ .with_json(MANIFEST_OUTPUT));
+}
+
+#[test]
+fn cargo_metadata_bad_version() {
+ let p = project("foo")
+ .file("Cargo.toml", &basic_bin_manifest("foo"))
+ .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
+ .build();
+
+ assert_that(p.cargo("metadata").arg("--no-deps")
+ .arg("--format-version").arg("2")
+ .cwd(p.root()),
+ execs().with_status(101)
+ .with_stderr("[ERROR] metadata version 2 not supported, only 1 is currently supported"));
+}
+
+#[test]
+fn multiple_features() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+
+ [features]
+ a = []
+ b = []
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("metadata")
+ .arg("--features").arg("a b"),
+ execs().with_status(0));
+}
--- /dev/null
+use cargotest::support::{project, execs};
+use hamcrest::assert_that;
+
+#[test]
+fn net_retry_loads_from_config() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.bar]
+ git = "https://127.0.0.1:11/foo/bar"
+ "#)
+ .file("src/main.rs", "").file(".cargo/config", r#"
+ [net]
+ retry=1
+ [http]
+ timeout=1
+ "#)
+ .build();
+
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(101)
+ .with_stderr_contains("[WARNING] spurious network error \
+(1 tries remaining): [..]"));
+}
+
+#[test]
+fn net_retry_git_outputs_warning() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.bar]
+ git = "https://127.0.0.1:11/foo/bar"
+ "#)
+ .file(".cargo/config", r#"
+ [http]
+ timeout=1
+ "#)
+ .file("src/main.rs", "")
+ .build();
+
+ assert_that(p.cargo("build").arg("-v").arg("-j").arg("1"),
+ execs().with_status(101)
+ .with_stderr_contains("[WARNING] spurious network error \
+(2 tries remaining): [..]")
+ .with_stderr_contains("\
+[WARNING] spurious network error (1 tries remaining): [..]"));
+}
--- /dev/null
+use std::fs::{self, File};
+use std::io::prelude::*;
+use std::env;
+
+use cargotest;
+use cargo::util::ProcessBuilder;
+use cargotest::process;
+use cargotest::support::{execs, paths};
+use hamcrest::{assert_that, existing_file, existing_dir, is_not};
+use tempdir::TempDir;
+
+fn cargo_process(s: &str) -> ProcessBuilder {
+ let mut p = cargotest::cargo_process();
+ p.arg(s);
+ p
+}
+
+fn create_empty_gitconfig() {
+ // This helps on Windows where libgit2 is very aggressive in attempting to
+ // find a git config file.
+ let gitconfig = paths::home().join(".gitconfig");
+ File::create(gitconfig).unwrap();
+}
+
+
+#[test]
+fn simple_lib() {
+ assert_that(cargo_process("new").arg("--lib").arg("foo").arg("--vcs").arg("none")
+ .env("USER", "foo"),
+ execs().with_status(0).with_stderr("\
+[CREATED] library `foo` project
+"));
+
+ assert_that(&paths::root().join("foo"), existing_dir());
+ assert_that(&paths::root().join("foo/Cargo.toml"), existing_file());
+ assert_that(&paths::root().join("foo/src/lib.rs"), existing_file());
+ assert_that(&paths::root().join("foo/.gitignore"), is_not(existing_file()));
+
+ let lib = paths::root().join("foo/src/lib.rs");
+ let mut contents = String::new();
+ File::open(&lib).unwrap().read_to_string(&mut contents).unwrap();
+ assert_eq!(contents, r#"#[cfg(test)]
+mod tests {
+ #[test]
+ fn it_works() {
+ assert_eq!(2 + 2, 4);
+ }
+}
+"#);
+
+ assert_that(cargo_process("build").cwd(&paths::root().join("foo")),
+ execs().with_status(0));
+}
+
+#[test]
+fn simple_bin() {
+ assert_that(cargo_process("new").arg("--bin").arg("foo")
+ .env("USER", "foo"),
+ execs().with_status(0).with_stderr("\
+[CREATED] binary (application) `foo` project
+"));
+
+ assert_that(&paths::root().join("foo"), existing_dir());
+ assert_that(&paths::root().join("foo/Cargo.toml"), existing_file());
+ assert_that(&paths::root().join("foo/src/main.rs"), existing_file());
+
+ assert_that(cargo_process("build").cwd(&paths::root().join("foo")),
+ execs().with_status(0));
+ assert_that(&paths::root().join(&format!("foo/target/debug/foo{}",
+ env::consts::EXE_SUFFIX)),
+ existing_file());
+}
+
+#[test]
+fn both_lib_and_bin() {
+ assert_that(cargo_process("new").arg("--lib").arg("--bin").arg("foo")
+ .env("USER", "foo"),
+ execs().with_status(101).with_stderr(
+ "[ERROR] can't specify both lib and binary outputs"));
+}
+
+#[test]
+fn simple_git() {
+ // Run inside a temp directory so that cargo will initialize a git repo.
+ // If this ran inside paths::root() it would detect that we are already
+ // inside a git repo and skip the initialization.
+ let td = TempDir::new("cargo").unwrap();
+ assert_that(cargo_process("new").arg("--lib").arg("foo").cwd(td.path())
+ .env("USER", "foo"),
+ execs().with_status(0));
+
+ assert_that(td.path(), existing_dir());
+ assert_that(&td.path().join("foo/Cargo.toml"), existing_file());
+ assert_that(&td.path().join("foo/src/lib.rs"), existing_file());
+ assert_that(&td.path().join("foo/.git"), existing_dir());
+ assert_that(&td.path().join("foo/.gitignore"), existing_file());
+
+ assert_that(cargo_process("build").cwd(&td.path().join("foo")),
+ execs().with_status(0));
+}
+
+#[test]
+fn no_argument() {
+ assert_that(cargo_process("new"),
+ execs().with_status(1)
+ .with_stderr("\
+[ERROR] Invalid arguments.
+
+Usage:
+ cargo new [options] <path>
+ cargo new -h | --help
+"));
+}
+
+#[test]
+fn existing() {
+ let dst = paths::root().join("foo");
+ fs::create_dir(&dst).unwrap();
+ assert_that(cargo_process("new").arg("foo"),
+ execs().with_status(101)
+ .with_stderr(format!("[ERROR] destination `{}` already exists\n\n\
+ Use `cargo init` to initialize the directory",
+ dst.display())));
+}
+
+#[test]
+fn invalid_characters() {
+ assert_that(cargo_process("new").arg("foo.rs"),
+ execs().with_status(101)
+ .with_stderr("\
+[ERROR] Invalid character `.` in crate name: `foo.rs`
+use --name to override crate name"));
+}
+
+#[test]
+fn reserved_name() {
+ assert_that(cargo_process("new").arg("test"),
+ execs().with_status(101)
+ .with_stderr("\
+[ERROR] The name `test` cannot be used as a crate name\n\
+use --name to override crate name"));
+}
+
+#[test]
+fn reserved_binary_name() {
+ assert_that(cargo_process("new").arg("--bin").arg("incremental"),
+ execs().with_status(101)
+ .with_stderr("\
+[ERROR] The name `incremental` cannot be used as a crate name\n\
+use --name to override crate name"));
+}
+
+#[test]
+fn keyword_name() {
+ assert_that(cargo_process("new").arg("pub"),
+ execs().with_status(101)
+ .with_stderr("\
+[ERROR] The name `pub` cannot be used as a crate name\n\
+use --name to override crate name"));
+}
+
+#[test]
+fn finds_author_user() {
+ create_empty_gitconfig();
+ assert_that(cargo_process("new").arg("foo").env("USER", "foo"),
+ execs().with_status(0));
+
+ let toml = paths::root().join("foo/Cargo.toml");
+ let mut contents = String::new();
+ File::open(&toml).unwrap().read_to_string(&mut contents).unwrap();
+ assert!(contents.contains(r#"authors = ["foo"]"#));
+}
+
+#[test]
+fn finds_author_user_escaped() {
+ create_empty_gitconfig();
+ assert_that(cargo_process("new").arg("foo").env("USER", "foo \"bar\""),
+ execs().with_status(0));
+
+ let toml = paths::root().join("foo/Cargo.toml");
+ let mut contents = String::new();
+ File::open(&toml).unwrap().read_to_string(&mut contents).unwrap();
+ assert!(contents.contains(r#"authors = ["foo \"bar\""]"#));
+}
+
+#[test]
+fn finds_author_username() {
+ create_empty_gitconfig();
+ assert_that(cargo_process("new").arg("foo")
+ .env_remove("USER")
+ .env("USERNAME", "foo"),
+ execs().with_status(0));
+
+ let toml = paths::root().join("foo/Cargo.toml");
+ let mut contents = String::new();
+ File::open(&toml).unwrap().read_to_string(&mut contents).unwrap();
+ assert!(contents.contains(r#"authors = ["foo"]"#));
+}
+
+#[test]
+fn finds_author_priority() {
+ assert_that(cargo_process("new").arg("foo")
+ .env("USER", "bar2")
+ .env("EMAIL", "baz2")
+ .env("CARGO_NAME", "bar")
+ .env("CARGO_EMAIL", "baz"),
+ execs().with_status(0));
+
+ let toml = paths::root().join("foo/Cargo.toml");
+ let mut contents = String::new();
+ File::open(&toml).unwrap().read_to_string(&mut contents).unwrap();
+ assert!(contents.contains(r#"authors = ["bar <baz>"]"#));
+}
+
+#[test]
+fn finds_author_email() {
+ create_empty_gitconfig();
+ assert_that(cargo_process("new").arg("foo")
+ .env("USER", "bar")
+ .env("EMAIL", "baz"),
+ execs().with_status(0));
+
+ let toml = paths::root().join("foo/Cargo.toml");
+ let mut contents = String::new();
+ File::open(&toml).unwrap().read_to_string(&mut contents).unwrap();
+ assert!(contents.contains(r#"authors = ["bar <baz>"]"#));
+}
+
+#[test]
+fn finds_author_git() {
+ process("git").args(&["config", "--global", "user.name", "bar"])
+ .exec().unwrap();
+ process("git").args(&["config", "--global", "user.email", "baz"])
+ .exec().unwrap();
+ assert_that(cargo_process("new").arg("foo").env("USER", "foo"),
+ execs().with_status(0));
+
+ let toml = paths::root().join("foo/Cargo.toml");
+ let mut contents = String::new();
+ File::open(&toml).unwrap().read_to_string(&mut contents).unwrap();
+ assert!(contents.contains(r#"authors = ["bar <baz>"]"#));
+}
+
+#[test]
+fn finds_local_author_git() {
+ process("git").args(&["init"])
+ .exec().unwrap();
+ process("git").args(&["config", "--global", "user.name", "foo"])
+ .exec().unwrap();
+ process("git").args(&["config", "--global", "user.email", "foo@bar"])
+ .exec().unwrap();
+
+ // Set local git user config
+ process("git").args(&["config", "user.name", "bar"])
+ .exec().unwrap();
+ process("git").args(&["config", "user.email", "baz"])
+ .exec().unwrap();
+ assert_that(cargo_process("init").env("USER", "foo"),
+ execs().with_status(0));
+
+ let toml = paths::root().join("Cargo.toml");
+ let mut contents = String::new();
+ File::open(&toml).unwrap().read_to_string(&mut contents).unwrap();
+ assert!(contents.contains(r#"authors = ["bar <baz>"]"#));
+}
+
+#[test]
+fn finds_git_email() {
+ assert_that(cargo_process("new").arg("foo")
+ .env("GIT_AUTHOR_NAME", "foo")
+ .env("GIT_AUTHOR_EMAIL", "gitfoo"),
+ execs().with_status(0));
+
+ let toml = paths::root().join("foo/Cargo.toml");
+ let mut contents = String::new();
+ File::open(&toml).unwrap().read_to_string(&mut contents).unwrap();
+ assert!(contents.contains(r#"authors = ["foo <gitfoo>"]"#), contents);
+}
+
+
+#[test]
+fn finds_git_author() {
+ create_empty_gitconfig();
+ assert_that(cargo_process("new").arg("foo")
+ .env_remove("USER")
+ .env("GIT_COMMITTER_NAME", "gitfoo"),
+ execs().with_status(0));
+
+ let toml = paths::root().join("foo/Cargo.toml");
+ let mut contents = String::new();
+ File::open(&toml).unwrap().read_to_string(&mut contents).unwrap();
+ assert!(contents.contains(r#"authors = ["gitfoo"]"#));
+}
+
+#[test]
+fn author_prefers_cargo() {
+ process("git").args(&["config", "--global", "user.name", "foo"])
+ .exec().unwrap();
+ process("git").args(&["config", "--global", "user.email", "bar"])
+ .exec().unwrap();
+ let root = paths::root();
+ fs::create_dir(&root.join(".cargo")).unwrap();
+ File::create(&root.join(".cargo/config")).unwrap().write_all(br#"
+ [cargo-new]
+ name = "new-foo"
+ email = "new-bar"
+ vcs = "none"
+ "#).unwrap();
+
+ assert_that(cargo_process("new").arg("foo").env("USER", "foo"),
+ execs().with_status(0));
+
+ let toml = paths::root().join("foo/Cargo.toml");
+ let mut contents = String::new();
+ File::open(&toml).unwrap().read_to_string(&mut contents).unwrap();
+ assert!(contents.contains(r#"authors = ["new-foo <new-bar>"]"#));
+ assert!(!root.join("foo/.gitignore").exists());
+}
+
+#[test]
+fn git_prefers_command_line() {
+ let root = paths::root();
+ fs::create_dir(&root.join(".cargo")).unwrap();
+ File::create(&root.join(".cargo/config")).unwrap().write_all(br#"
+ [cargo-new]
+ vcs = "none"
+ name = "foo"
+ email = "bar"
+ "#).unwrap();
+
+ assert_that(cargo_process("new").arg("foo").arg("--vcs").arg("git")
+ .env("USER", "foo"),
+ execs().with_status(0));
+ assert!(paths::root().join("foo/.gitignore").exists());
+}
+
+#[test]
+fn subpackage_no_git() {
+ assert_that(cargo_process("new").arg("foo").env("USER", "foo"),
+ execs().with_status(0));
+
+ let subpackage = paths::root().join("foo").join("components");
+ fs::create_dir(&subpackage).unwrap();
+ assert_that(cargo_process("new").arg("foo/components/subcomponent")
+ .env("USER", "foo"),
+ execs().with_status(0));
+
+ assert_that(&paths::root().join("foo/components/subcomponent/.git"),
+ is_not(existing_file()));
+ assert_that(&paths::root().join("foo/components/subcomponent/.gitignore"),
+ is_not(existing_file()));
+}
+
+#[test]
+fn subpackage_git_with_vcs_arg() {
+ assert_that(cargo_process("new").arg("foo").env("USER", "foo"),
+ execs().with_status(0));
+
+ let subpackage = paths::root().join("foo").join("components");
+ fs::create_dir(&subpackage).unwrap();
+ assert_that(cargo_process("new").arg("foo/components/subcomponent")
+ .arg("--vcs").arg("git")
+ .env("USER", "foo"),
+ execs().with_status(0));
+
+ assert_that(&paths::root().join("foo/components/subcomponent/.git"),
+ existing_dir());
+ assert_that(&paths::root().join("foo/components/subcomponent/.gitignore"),
+ existing_file());
+}
+
+#[test]
+fn unknown_flags() {
+ assert_that(cargo_process("new").arg("foo").arg("--flag"),
+ execs().with_status(1)
+ .with_stderr("\
+[ERROR] Unknown flag: '--flag'
+
+Usage:
+ cargo new [..]
+ cargo new [..]
+"));
+}
+
+#[test]
+fn explicit_invalid_name_not_suggested() {
+ assert_that(cargo_process("new").arg("--name").arg("10-invalid").arg("a"),
+ execs().with_status(101)
+ .with_stderr("\
+[ERROR] Package names starting with a digit cannot be used as a crate name"));
+}
--- /dev/null
+use cargotest::support::git;
+use cargotest::support::paths;
+use cargotest::support::registry::Package;
+use cargotest::support::{execs, project};
+use hamcrest::assert_that;
+
+#[test]
+fn override_simple() {
+ Package::new("foo", "0.1.0").publish();
+
+ let foo = git::repo(&paths::root().join("override"))
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("src/lib.rs", "pub fn foo() {}")
+ .build();
+
+ let p = project("local")
+ .file("Cargo.toml", &format!(r#"
+ [package]
+ name = "local"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ foo = "0.1.0"
+
+ [replace]
+ "foo:0.1.0" = {{ git = '{}' }}
+ "#, foo.url()))
+ .file("src/lib.rs", "
+ extern crate foo;
+ pub fn bar() {
+ foo::foo();
+ }
+ ")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr("\
+[UPDATING] registry `file://[..]`
+[UPDATING] git repository `[..]`
+[COMPILING] foo v0.1.0 (file://[..])
+[COMPILING] local v0.0.1 (file://[..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+}
+
+#[test]
+fn missing_version() {
+ let p = project("local")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "local"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ foo = "0.1.0"
+
+ [replace]
+ foo = { git = 'https://example.com' }
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101).with_stderr("\
+error: failed to parse manifest at `[..]`
+
+Caused by:
+ replacements must specify a version to replace, but `[..]foo` does not
+"));
+}
+
+#[test]
+fn invalid_semver_version() {
+ let p = project("local")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "local"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ foo = "*"
+
+ [replace]
+ "foo:*" = { git = 'https://example.com' }
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101).with_stderr_contains("\
+error: failed to parse manifest at `[..]`
+
+Caused by:
+ replacements must specify a valid semver version to replace, but `foo:*` does not
+"));
+}
+
+#[test]
+fn different_version() {
+ Package::new("foo", "0.2.0").publish();
+ Package::new("foo", "0.1.0").publish();
+
+ let p = project("local")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "local"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ foo = "0.1.0"
+
+ [replace]
+ "foo:0.1.0" = "0.2.0"
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101).with_stderr("\
+error: failed to parse manifest at `[..]`
+
+Caused by:
+ replacements cannot specify a version requirement, but found one for [..]
+"));
+}
+
+#[test]
+fn transitive() {
+ Package::new("foo", "0.1.0").publish();
+ Package::new("bar", "0.2.0")
+ .dep("foo", "0.1.0")
+ .file("src/lib.rs", "extern crate foo; fn bar() { foo::foo(); }")
+ .publish();
+
+ let foo = git::repo(&paths::root().join("override"))
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("src/lib.rs", "pub fn foo() {}")
+ .build();
+
+ let p = project("local")
+ .file("Cargo.toml", &format!(r#"
+ [package]
+ name = "local"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ bar = "0.2.0"
+
+ [replace]
+ "foo:0.1.0" = {{ git = '{}' }}
+ "#, foo.url()))
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr("\
+[UPDATING] registry `file://[..]`
+[UPDATING] git repository `[..]`
+[DOWNLOADING] bar v0.2.0 (registry [..])
+[COMPILING] foo v0.1.0 (file://[..])
+[COMPILING] bar v0.2.0
+[COMPILING] local v0.0.1 (file://[..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+
+ assert_that(p.cargo("build"), execs().with_status(0).with_stdout(""));
+}
+
+#[test]
+fn persists_across_rebuilds() {
+ Package::new("foo", "0.1.0").publish();
+
+ let foo = git::repo(&paths::root().join("override"))
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("src/lib.rs", "pub fn foo() {}")
+ .build();
+
+ let p = project("local")
+ .file("Cargo.toml", &format!(r#"
+ [package]
+ name = "local"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ foo = "0.1.0"
+
+ [replace]
+ "foo:0.1.0" = {{ git = '{}' }}
+ "#, foo.url()))
+ .file("src/lib.rs", "
+ extern crate foo;
+ pub fn bar() {
+ foo::foo();
+ }
+ ")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr("\
+[UPDATING] registry `file://[..]`
+[UPDATING] git repository `file://[..]`
+[COMPILING] foo v0.1.0 (file://[..])
+[COMPILING] local v0.0.1 (file://[..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stdout(""));
+}
+
+#[test]
+fn replace_registry_with_path() {
+ Package::new("foo", "0.1.0").publish();
+
+ let _ = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("src/lib.rs", "pub fn foo() {}")
+ .build();
+
+ let p = project("local")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "local"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ foo = "0.1.0"
+
+ [replace]
+ "foo:0.1.0" = { path = "../foo" }
+ "#)
+ .file("src/lib.rs", "
+ extern crate foo;
+ pub fn bar() {
+ foo::foo();
+ }
+ ")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr("\
+[UPDATING] registry `file://[..]`
+[COMPILING] foo v0.1.0 (file://[..])
+[COMPILING] local v0.0.1 (file://[..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+}
+
+#[test]
+fn use_a_spec_to_select() {
+ Package::new("foo", "0.1.1")
+ .file("src/lib.rs", "pub fn foo1() {}")
+ .publish();
+ Package::new("foo", "0.2.0").publish();
+ Package::new("bar", "0.1.1")
+ .dep("foo", "0.2")
+ .file("src/lib.rs", "
+ extern crate foo;
+ pub fn bar() { foo::foo3(); }
+ ")
+ .publish();
+
+ let foo = git::repo(&paths::root().join("override"))
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.2.0"
+ authors = []
+ "#)
+ .file("src/lib.rs", "pub fn foo3() {}")
+ .build();
+
+ let p = project("local")
+ .file("Cargo.toml", &format!(r#"
+ [package]
+ name = "local"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ bar = "0.1"
+ foo = "0.1"
+
+ [replace]
+ "foo:0.2.0" = {{ git = '{}' }}
+ "#, foo.url()))
+ .file("src/lib.rs", "
+ extern crate foo;
+ extern crate bar;
+
+ pub fn local() {
+ foo::foo1();
+ bar::bar();
+ }
+ ")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr("\
+[UPDATING] registry `file://[..]`
+[UPDATING] git repository `[..]`
+[DOWNLOADING] [..]
+[DOWNLOADING] [..]
+[COMPILING] [..]
+[COMPILING] [..]
+[COMPILING] [..]
+[COMPILING] local v0.0.1 (file://[..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+}
+
+#[test]
+fn override_adds_some_deps() {
+ Package::new("foo", "0.1.1").publish();
+ Package::new("bar", "0.1.0").publish();
+
+ let foo = git::repo(&paths::root().join("override"))
+ .file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+
+ [dependencies]
+ foo = "0.1"
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+
+ let p = project("local")
+ .file("Cargo.toml", &format!(r#"
+ [package]
+ name = "local"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ bar = "0.1"
+
+ [replace]
+ "bar:0.1.0" = {{ git = '{}' }}
+ "#, foo.url()))
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr("\
+[UPDATING] registry `file://[..]`
+[UPDATING] git repository `[..]`
+[DOWNLOADING] foo v0.1.1 (registry [..])
+[COMPILING] foo v0.1.1
+[COMPILING] bar v0.1.0 ([..])
+[COMPILING] local v0.0.1 (file://[..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+
+ assert_that(p.cargo("build"), execs().with_status(0).with_stdout(""));
+
+ Package::new("foo", "0.1.2").publish();
+ assert_that(p.cargo("update").arg("-p").arg(&format!("{}#bar", foo.url())),
+ execs().with_status(0).with_stderr("\
+[UPDATING] git repository `file://[..]`
+"));
+ assert_that(p.cargo("update")
+ .arg("-p")
+ .arg("https://github.com/rust-lang/crates.io-index#bar"),
+ execs().with_status(0).with_stderr("\
+[UPDATING] registry `file://[..]`
+"));
+
+ assert_that(p.cargo("build"), execs().with_status(0).with_stdout(""));
+}
+
+#[test]
+fn locked_means_locked_yes_no_seriously_i_mean_locked() {
+ // this in theory exercises #2041
+ Package::new("foo", "0.1.0").publish();
+ Package::new("foo", "0.2.0").publish();
+ Package::new("bar", "0.1.0").publish();
+
+ let foo = git::repo(&paths::root().join("override"))
+ .file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+
+ [dependencies]
+ foo = "*"
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+
+ let p = project("local")
+ .file("Cargo.toml", &format!(r#"
+ [package]
+ name = "local"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ foo = "0.1"
+ bar = "0.1"
+
+ [replace]
+ "bar:0.1.0" = {{ git = '{}' }}
+ "#, foo.url()))
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0));
+
+ assert_that(p.cargo("build"), execs().with_status(0).with_stdout(""));
+ assert_that(p.cargo("build"), execs().with_status(0).with_stdout(""));
+}
+
+#[test]
+fn override_wrong_name() {
+ Package::new("foo", "0.1.0").publish();
+
+ let foo = git::repo(&paths::root().join("override"))
+ .file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+
+ let p = project("local")
+ .file("Cargo.toml", &format!(r#"
+ [package]
+ name = "local"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ foo = "0.1"
+
+ [replace]
+ "foo:0.1.0" = {{ git = '{}' }}
+ "#, foo.url()))
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101).with_stderr("\
+[UPDATING] registry [..]
+[UPDATING] git repository [..]
+error: no matching package for override `[..]foo:0.1.0` found
+location searched: file://[..]
+version required: = 0.1.0
+"));
+}
+
+#[test]
+fn override_with_nothing() {
+ Package::new("foo", "0.1.0").publish();
+
+ let foo = git::repo(&paths::root().join("override"))
+ .file("src/lib.rs", "")
+ .build();
+
+ let p = project("local")
+ .file("Cargo.toml", &format!(r#"
+ [package]
+ name = "local"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ foo = "0.1"
+
+ [replace]
+ "foo:0.1.0" = {{ git = '{}' }}
+ "#, foo.url()))
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101).with_stderr("\
+[UPDATING] registry [..]
+[UPDATING] git repository [..]
+[ERROR] failed to load source for a dependency on `foo`
+
+Caused by:
+ Unable to update file://[..]
+
+Caused by:
+ Could not find Cargo.toml in `[..]`
+"));
+}
+
+#[test]
+fn override_wrong_version() {
+ let p = project("local")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "local"
+ version = "0.0.1"
+ authors = []
+
+ [replace]
+ "foo:0.1.0" = { git = 'https://example.com', version = '0.2.0' }
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101).with_stderr("\
+error: failed to parse manifest at `[..]`
+
+Caused by:
+ replacements cannot specify a version requirement, but found one for `[..]foo:0.1.0`
+"));
+}
+
+#[test]
+fn multiple_specs() {
+ Package::new("foo", "0.1.0").publish();
+
+ let foo = git::repo(&paths::root().join("override"))
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("src/lib.rs", "pub fn foo() {}")
+ .build();
+
+ let p = project("local")
+ .file("Cargo.toml", &format!(r#"
+ [package]
+ name = "local"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ foo = "0.1.0"
+
+ [replace]
+ "foo:0.1.0" = {{ git = '{0}' }}
+
+ [replace."https://github.com/rust-lang/crates.io-index#foo:0.1.0"]
+ git = '{0}'
+ "#, foo.url()))
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101).with_stderr("\
+[UPDATING] registry [..]
+[UPDATING] git repository [..]
+error: overlapping replacement specifications found:
+
+ * [..]
+ * [..]
+
+both specifications match: foo v0.1.0
+"));
+}
+
+#[test]
+fn test_override_dep() {
+ Package::new("foo", "0.1.0").publish();
+
+ let foo = git::repo(&paths::root().join("override"))
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("src/lib.rs", "pub fn foo() {}")
+ .build();
+
+ let p = project("local")
+ .file("Cargo.toml", &format!(r#"
+ [package]
+ name = "local"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ foo = "0.1.0"
+
+ [replace]
+ "foo:0.1.0" = {{ git = '{0}' }}
+ "#, foo.url()))
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("test").arg("-p").arg("foo"),
+ execs().with_status(101)
+ .with_stderr_contains("\
+error: There are multiple `foo` packages in your project, and the [..]
+Please re-run this command with [..]
+ [..]#foo:0.1.0
+ [..]#foo:0.1.0
+"));
+}
+
+#[test]
+fn update() {
+ Package::new("foo", "0.1.0").publish();
+
+ let foo = git::repo(&paths::root().join("override"))
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("src/lib.rs", "pub fn foo() {}")
+ .build();
+
+ let p = project("local")
+ .file("Cargo.toml", &format!(r#"
+ [package]
+ name = "local"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ foo = "0.1.0"
+
+ [replace]
+ "foo:0.1.0" = {{ git = '{0}' }}
+ "#, foo.url()))
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("generate-lockfile"),
+ execs().with_status(0));
+ assert_that(p.cargo("update"),
+ execs().with_status(0)
+ .with_stderr("\
+[UPDATING] registry `[..]`
+[UPDATING] git repository `[..]`
+"));
+}
+
+// local -> near -> far
+// near is overridden with itself
+#[test]
+fn no_override_self() {
+ let deps = git::repo(&paths::root().join("override"))
+
+ .file("far/Cargo.toml", r#"
+ [package]
+ name = "far"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("far/src/lib.rs", "")
+
+ .file("near/Cargo.toml", r#"
+ [package]
+ name = "near"
+ version = "0.1.0"
+ authors = []
+
+ [dependencies]
+ far = { path = "../far" }
+ "#)
+ .file("near/src/lib.rs", r#"
+ #![no_std]
+ pub extern crate far;
+ "#)
+ .build();
+
+ let p = project("local")
+ .file("Cargo.toml", &format!(r#"
+ [package]
+ name = "local"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ near = {{ git = '{0}' }}
+
+ [replace]
+ "near:0.1.0" = {{ git = '{0}' }}
+ "#, deps.url()))
+ .file("src/lib.rs", r#"
+ #![no_std]
+ pub extern crate near;
+ "#)
+ .build();
+
+ assert_that(p.cargo("build").arg("--verbose"),
+ execs().with_status(0));
+}
+
+#[test]
+fn broken_path_override_warns() {
+ Package::new("foo", "0.1.0").publish();
+ Package::new("foo", "0.2.0").publish();
+
+ let p = project("local")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "local"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ a = { path = "a1" }
+ "#)
+ .file("src/lib.rs", "")
+ .file("a1/Cargo.toml", r#"
+ [package]
+ name = "a"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ foo = "0.1"
+ "#)
+ .file("a1/src/lib.rs", "")
+ .file("a2/Cargo.toml", r#"
+ [package]
+ name = "a"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ foo = "0.2"
+ "#)
+ .file("a2/src/lib.rs", "")
+ .file(".cargo/config", r#"
+ paths = ["a2"]
+ "#)
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0)
+ .with_stderr("\
+[UPDATING] [..]
+warning: path override for crate `a` has altered the original list of
+dependencies; the dependency on `foo` was either added or
+modified to not match the previously resolved version
+
+This is currently allowed but is known to produce buggy behavior with spurious
+recompiles and changes to the crate graph. Path overrides unfortunately were
+never intended to support this feature, so for now this message is just a
+warning. In the future, however, this message will become a hard error.
+
+To change the dependency graph via an override it's recommended to use the
+`[replace]` feature of Cargo instead of the path override feature. This is
+documented online at the url below for more information.
+
+http://doc.crates.io/specifying-dependencies.html#overriding-dependencies
+
+[DOWNLOADING] [..]
+[COMPILING] [..]
+[COMPILING] [..]
+[COMPILING] [..]
+[FINISHED] [..]
+"));
+}
+
+#[test]
+fn override_an_override() {
+ Package::new("chrono", "0.2.0").dep("serde", "< 0.9").publish();
+ Package::new("serde", "0.7.0")
+ .file("src/lib.rs", "pub fn serde07() {}")
+ .publish();
+ Package::new("serde", "0.8.0")
+ .file("src/lib.rs", "pub fn serde08() {}")
+ .publish();
+
+ let p = project("local")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "local"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ chrono = "0.2"
+ serde = "0.8"
+
+ [replace]
+ "chrono:0.2.0" = { path = "chrono" }
+ "serde:0.8.0" = { path = "serde" }
+ "#)
+ .file("Cargo.lock", r#"
+ [[package]]
+ name = "local"
+ version = "0.0.1"
+ dependencies = [
+ "chrono 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ ]
+
+ [[package]]
+ name = "chrono"
+ version = "0.2.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+ replace = "chrono 0.2.0"
+
+ [[package]]
+ name = "chrono"
+ version = "0.2.0"
+ dependencies = [
+ "serde 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ ]
+
+ [[package]]
+ name = "serde"
+ version = "0.7.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+
+ [[package]]
+ name = "serde"
+ version = "0.8.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+ replace = "serde 0.8.0"
+
+ [[package]]
+ name = "serde"
+ version = "0.8.0"
+ "#)
+ .file("src/lib.rs", "
+ extern crate chrono;
+ extern crate serde;
+
+ pub fn local() {
+ chrono::chrono();
+ serde::serde08_override();
+ }
+ ")
+ .file("chrono/Cargo.toml", r#"
+ [package]
+ name = "chrono"
+ version = "0.2.0"
+ authors = []
+
+ [dependencies]
+ serde = "< 0.9"
+ "#)
+ .file("chrono/src/lib.rs", "
+ extern crate serde;
+ pub fn chrono() {
+ serde::serde07();
+ }
+ ")
+ .file("serde/Cargo.toml", r#"
+ [package]
+ name = "serde"
+ version = "0.8.0"
+ authors = []
+ "#)
+ .file("serde/src/lib.rs", "
+ pub fn serde08_override() {}
+ ")
+ .build();
+
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(0));
+}
+
+#[test]
+fn overriding_nonexistent_no_spurious() {
+ Package::new("foo", "0.1.0").dep("bar", "0.1").publish();
+ Package::new("bar", "0.1.0").publish();
+
+ let foo = git::repo(&paths::root().join("override"))
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+
+ [dependencies]
+ bar = { path = "bar" }
+ "#)
+ .file("src/lib.rs", "pub fn foo() {}")
+ .file("bar/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("bar/src/lib.rs", "pub fn foo() {}")
+ .build();
+
+
+ let p = project("local")
+ .file("Cargo.toml", &format!(r#"
+ [package]
+ name = "local"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ foo = "0.1.0"
+
+ [replace]
+ "foo:0.1.0" = {{ git = '{url}' }}
+ "bar:0.1.0" = {{ git = '{url}' }}
+ "#, url = foo.url()))
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0));
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr("\
+[WARNING] package replacement is not used: [..]bar:0.1.0
+[FINISHED] [..]
+").with_stdout(""));
+}
+
+#[test]
+fn no_warnings_when_replace_is_used_in_another_workspace_member() {
+ Package::new("foo", "0.1.0").publish();
+ Package::new("bar", "0.1.0").publish();
+
+ let p = project("ws")
+ .file("Cargo.toml", r#"
+ [workspace]
+ members = [ "first_crate", "second_crate"]
+
+ [replace]
+ "foo:0.1.0" = { path = "local_foo" }"#)
+ .file("first_crate/Cargo.toml", r#"
+ [package]
+ name = "first_crate"
+ version = "0.1.0"
+
+ [dependencies]
+ foo = "0.1.0"
+ "#)
+ .file("first_crate/src/lib.rs", "")
+ .file("second_crate/Cargo.toml", r#"
+ [package]
+ name = "second_crate"
+ version = "0.1.0"
+ "#)
+ .file("second_crate/src/lib.rs", "")
+ .file("local_foo/Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ "#)
+ .file("local_foo/src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build").cwd(p.root().join("first_crate")),
+ execs().with_status(0)
+ .with_stdout("")
+ .with_stderr("\
+[UPDATING] registry `[..]`
+[COMPILING] foo v0.1.0 ([..])
+[COMPILING] first_crate v0.1.0 ([..])
+[FINISHED] [..]"));
+
+ assert_that(p.cargo("build").cwd(p.root().join("second_crate")),
+ execs().with_status(0)
+ .with_stdout("")
+ .with_stderr("\
+[COMPILING] second_crate v0.1.0 ([..])
+[FINISHED] [..]"));
+}
+
+
+#[test]
+fn override_to_path_dep() {
+ Package::new("foo", "0.1.0").dep("bar", "0.1").publish();
+ Package::new("bar", "0.1.0").publish();
+
+ let p = project("local")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "local"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ foo = "0.1.0"
+ "#)
+ .file("src/lib.rs", "")
+ .file("foo/Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ bar = { path = "bar" }
+ "#)
+ .file("foo/src/lib.rs", "")
+ .file("foo/bar/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("foo/bar/src/lib.rs", "")
+ .file(".cargo/config", r#"
+ paths = ["foo"]
+ "#)
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0));
+}
+
+#[test]
+fn replace_to_path_dep() {
+ Package::new("foo", "0.1.0").dep("bar", "0.1").publish();
+ Package::new("bar", "0.1.0").publish();
+
+ let p = project("local")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "local"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ foo = "0.1.0"
+
+ [replace]
+ "foo:0.1.0" = { path = "foo" }
+ "#)
+ .file("src/lib.rs", "extern crate foo;")
+ .file("foo/Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+
+ [dependencies]
+ bar = { path = "bar" }
+ "#)
+ .file("foo/src/lib.rs", "
+ extern crate bar;
+
+ pub fn foo() {
+ bar::bar();
+ }
+ ")
+ .file("foo/bar/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("foo/bar/src/lib.rs", "pub fn bar() {}")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0));
+}
+
+#[test]
+fn paths_ok_with_optional() {
+ Package::new("bar", "0.1.0").publish();
+
+ let p = project("local")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "local"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ foo = { path = "foo" }
+ "#)
+ .file("src/lib.rs", "")
+ .file("foo/Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+
+ [dependencies]
+ bar = { version = "0.1", optional = true }
+ "#)
+ .file("foo/src/lib.rs", "")
+ .file("foo2/Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+
+ [dependencies]
+ bar = { version = "0.1", optional = true }
+ "#)
+ .file("foo2/src/lib.rs", "")
+ .file(".cargo/config", r#"
+ paths = ["foo2"]
+ "#)
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr("\
+[COMPILING] foo v0.1.0 ([..]foo2)
+[COMPILING] local v0.0.1 ([..])
+[FINISHED] [..]
+"));
+}
+
+#[test]
+fn paths_add_optional_bad() {
+ Package::new("bar", "0.1.0").publish();
+
+ let p = project("local")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "local"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ foo = { path = "foo" }
+ "#)
+ .file("src/lib.rs", "")
+ .file("foo/Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("foo/src/lib.rs", "")
+ .file("foo2/Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+
+ [dependencies]
+ bar = { version = "0.1", optional = true }
+ "#)
+ .file("foo2/src/lib.rs", "")
+ .file(".cargo/config", r#"
+ paths = ["foo2"]
+ "#)
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr_contains("\
+warning: path override for crate `foo` has altered the original list of
+dependencies; the dependency on `bar` was either added or\
+"));
+}
+
+#[test]
+fn override_with_default_feature() {
+ Package::new("another", "0.1.0").publish();
+ Package::new("another", "0.1.1")
+ .dep("bar", "0.1")
+ .publish();
+ Package::new("bar", "0.1.0").publish();
+
+ let p = project("local")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "local"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ bar = { path = "bar", default-features = false }
+ another = "0.1"
+ another2 = { path = "another2" }
+
+ [replace]
+ 'bar:0.1.0' = { path = "bar" }
+ "#)
+ .file("src/main.rs", r#"
+ extern crate bar;
+
+ fn main() {
+ bar::bar();
+ }
+ "#)
+ .file("bar/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+
+ [features]
+ default = []
+ "#)
+ .file("bar/src/lib.rs", r#"
+ #[cfg(feature = "default")]
+ pub fn bar() {}
+ "#)
+ .file("another2/Cargo.toml", r#"
+ [package]
+ name = "another2"
+ version = "0.1.0"
+ authors = []
+
+ [dependencies]
+ bar = { version = "0.1", default-features = false }
+ "#)
+ .file("another2/src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("run"),
+ execs().with_status(0));
+}
+
+#[test]
+fn override_plus_dep() {
+ Package::new("bar", "0.1.0").publish();
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ bar = "0.1"
+
+ [replace]
+ 'bar:0.1.0' = { path = "bar" }
+ "#)
+ .file("src/lib.rs", "")
+ .file("bar/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+
+ [dependencies]
+ foo = { path = ".." }
+ "#)
+ .file("bar/src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101).with_stderr_contains("\
+error: cyclic package dependency: [..]
+"));
+}
--- /dev/null
+use std;
+use std::fs::File;
+use std::io::prelude::*;
+use std::path::{Path, PathBuf};
+
+use git2;
+use cargotest::{cargo_process, process, ChannelChanger};
+use cargotest::support::{project, execs, paths, git, path2url, cargo_exe, registry};
+use cargotest::support::registry::Package;
+use flate2::read::GzDecoder;
+use hamcrest::{assert_that, existing_file, contains, equal_to};
+use tar::Archive;
+
+#[test]
+fn simple() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ exclude = ["*.txt"]
+ license = "MIT"
+ description = "foo"
+ "#)
+ .file("src/main.rs", r#"
+ fn main() { println!("hello"); }
+ "#)
+ .file("src/bar.txt", "") // should be ignored when packaging
+ .build();
+
+ assert_that(p.cargo("package"),
+ execs().with_status(0).with_stderr(&format!("\
+[WARNING] manifest has no documentation[..]
+See [..]
+[PACKAGING] foo v0.0.1 ({dir})
+[VERIFYING] foo v0.0.1 ({dir})
+[COMPILING] foo v0.0.1 ({dir}[..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+",
+ dir = p.url())));
+ assert_that(&p.root().join("target/package/foo-0.0.1.crate"), existing_file());
+ assert_that(p.cargo("package").arg("-l"),
+ execs().with_status(0).with_stdout("\
+Cargo.toml
+src[/]main.rs
+"));
+ assert_that(p.cargo("package"),
+ execs().with_status(0).with_stdout(""));
+
+ let f = File::open(&p.root().join("target/package/foo-0.0.1.crate")).unwrap();
+ let mut rdr = GzDecoder::new(f);
+ let mut contents = Vec::new();
+ rdr.read_to_end(&mut contents).unwrap();
+ let mut ar = Archive::new(&contents[..]);
+ for f in ar.entries().unwrap() {
+ let f = f.unwrap();
+ let fname = f.header().path_bytes();
+ let fname = &*fname;
+ assert!(fname == b"foo-0.0.1/Cargo.toml" ||
+ fname == b"foo-0.0.1/Cargo.toml.orig" ||
+ fname == b"foo-0.0.1/src/main.rs",
+ "unexpected filename: {:?}", f.header().path())
+ }
+}
+
+#[test]
+fn metadata_warning() {
+ let p = project("all")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/main.rs", r#"
+ fn main() {}
+ "#)
+ .build();
+ assert_that(p.cargo("package"),
+ execs().with_status(0).with_stderr(&format!("\
+warning: manifest has no description, license, license-file, documentation, \
+homepage or repository.
+See http://doc.crates.io/manifest.html#package-metadata for more info.
+[PACKAGING] foo v0.0.1 ({dir})
+[VERIFYING] foo v0.0.1 ({dir})
+[COMPILING] foo v0.0.1 ({dir}[..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+",
+ dir = p.url())));
+
+ let p = project("one")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ license = "MIT"
+ "#)
+ .file("src/main.rs", r#"
+ fn main() {}
+ "#)
+ .build();
+ assert_that(p.cargo("package"),
+ execs().with_status(0).with_stderr(&format!("\
+warning: manifest has no description, documentation, homepage or repository.
+See http://doc.crates.io/manifest.html#package-metadata for more info.
+[PACKAGING] foo v0.0.1 ({dir})
+[VERIFYING] foo v0.0.1 ({dir})
+[COMPILING] foo v0.0.1 ({dir}[..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+",
+ dir = p.url())));
+
+ let p = project("all")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ license = "MIT"
+ description = "foo"
+ repository = "bar"
+ "#)
+ .file("src/main.rs", r#"
+ fn main() {}
+ "#)
+ .build();
+ assert_that(p.cargo("package"),
+ execs().with_status(0).with_stderr(&format!("\
+[PACKAGING] foo v0.0.1 ({dir})
+[VERIFYING] foo v0.0.1 ({dir})
+[COMPILING] foo v0.0.1 ({dir}[..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+",
+ dir = p.url())));
+}
+
+#[test]
+fn package_verbose() {
+ let root = paths::root().join("all");
+ let p = git::repo(&root)
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/main.rs", r#"
+ fn main() {}
+ "#)
+ .file("a/Cargo.toml", r#"
+ [project]
+ name = "a"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("a/src/lib.rs", "")
+ .build();
+ let mut cargo = cargo_process();
+ cargo.cwd(p.root());
+ assert_that(cargo.clone().arg("build"), execs().with_status(0));
+
+ println!("package main repo");
+ assert_that(cargo.clone().arg("package").arg("-v").arg("--no-verify"),
+ execs().with_status(0).with_stderr("\
+[WARNING] manifest has no description[..]
+See http://doc.crates.io/manifest.html#package-metadata for more info.
+[PACKAGING] foo v0.0.1 ([..])
+[ARCHIVING] [..]
+[ARCHIVING] [..]
+"));
+
+ println!("package sub-repo");
+ assert_that(cargo.arg("package").arg("-v").arg("--no-verify")
+ .cwd(p.root().join("a")),
+ execs().with_status(0).with_stderr("\
+[WARNING] manifest has no description[..]
+See http://doc.crates.io/manifest.html#package-metadata for more info.
+[PACKAGING] a v0.0.1 ([..])
+[ARCHIVING] [..]
+[ARCHIVING] [..]
+"));
+}
+
+#[test]
+fn package_verification() {
+ let p = project("all")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/main.rs", r#"
+ fn main() {}
+ "#)
+ .build();
+ assert_that(p.cargo("build"),
+ execs().with_status(0));
+ assert_that(p.cargo("package"),
+ execs().with_status(0).with_stderr(&format!("\
+[WARNING] manifest has no description[..]
+See http://doc.crates.io/manifest.html#package-metadata for more info.
+[PACKAGING] foo v0.0.1 ({dir})
+[VERIFYING] foo v0.0.1 ({dir})
+[COMPILING] foo v0.0.1 ({dir}[..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+",
+ dir = p.url())));
+}
+
+#[test]
+fn path_dependency_no_version() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ license = "MIT"
+ description = "foo"
+
+ [dependencies.bar]
+ path = "bar"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .file("bar/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("bar/src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("package"),
+ execs().with_status(101).with_stderr("\
+[WARNING] manifest has no documentation, homepage or repository.
+See http://doc.crates.io/manifest.html#package-metadata for more info.
+[ERROR] all path dependencies must have a version specified when packaging.
+dependency `bar` does not specify a version.
+"));
+}
+
+#[test]
+fn exclude() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ exclude = [
+ "*.txt",
+ # file in root
+ "file_root_1", # NO_CHANGE (ignored)
+ "/file_root_2", # CHANGING (packaged -> ignored)
+ "file_root_3/", # NO_CHANGE (packaged)
+ "file_root_4/*", # NO_CHANGE (packaged)
+ "file_root_5/**", # NO_CHANGE (packaged)
+ # file in sub-dir
+ "file_deep_1", # CHANGING (packaged -> ignored)
+ "/file_deep_2", # NO_CHANGE (packaged)
+ "file_deep_3/", # NO_CHANGE (packaged)
+ "file_deep_4/*", # NO_CHANGE (packaged)
+ "file_deep_5/**", # NO_CHANGE (packaged)
+ # dir in root
+ "dir_root_1", # CHANGING (packaged -> ignored)
+ "/dir_root_2", # CHANGING (packaged -> ignored)
+ "dir_root_3/", # CHANGING (packaged -> ignored)
+ "dir_root_4/*", # NO_CHANGE (ignored)
+ "dir_root_5/**", # NO_CHANGE (ignored)
+ # dir in sub-dir
+ "dir_deep_1", # CHANGING (packaged -> ignored)
+ "/dir_deep_2", # NO_CHANGE
+ "dir_deep_3/", # CHANGING (packaged -> ignored)
+ "dir_deep_4/*", # CHANGING (packaged -> ignored)
+ "dir_deep_5/**", # CHANGING (packaged -> ignored)
+ ]
+ "#)
+ .file("src/main.rs", r#"
+ fn main() { println!("hello"); }
+ "#)
+ .file("bar.txt", "")
+ .file("src/bar.txt", "")
+ // file in root
+ .file("file_root_1", "")
+ .file("file_root_2", "")
+ .file("file_root_3", "")
+ .file("file_root_4", "")
+ .file("file_root_5", "")
+ // file in sub-dir
+ .file("some_dir/file_deep_1", "")
+ .file("some_dir/file_deep_2", "")
+ .file("some_dir/file_deep_3", "")
+ .file("some_dir/file_deep_4", "")
+ .file("some_dir/file_deep_5", "")
+ // dir in root
+ .file("dir_root_1/some_dir/file", "")
+ .file("dir_root_2/some_dir/file", "")
+ .file("dir_root_3/some_dir/file", "")
+ .file("dir_root_4/some_dir/file", "")
+ .file("dir_root_5/some_dir/file", "")
+ // dir in sub-dir
+ .file("some_dir/dir_deep_1/some_dir/file", "")
+ .file("some_dir/dir_deep_2/some_dir/file", "")
+ .file("some_dir/dir_deep_3/some_dir/file", "")
+ .file("some_dir/dir_deep_4/some_dir/file", "")
+ .file("some_dir/dir_deep_5/some_dir/file", "")
+ .build();
+
+ assert_that(p.cargo("package").arg("--no-verify").arg("-v"),
+ execs().with_status(0).with_stdout("").with_stderr("\
+[WARNING] manifest has no description[..]
+See http://doc.crates.io/manifest.html#package-metadata for more info.
+[PACKAGING] foo v0.0.1 ([..])
+[WARNING] [..] file `dir_root_1[/]some_dir[/]file` WILL be excluded [..]
+See [..]
+[WARNING] [..] file `dir_root_2[/]some_dir[/]file` WILL be excluded [..]
+See [..]
+[WARNING] [..] file `dir_root_3[/]some_dir[/]file` WILL be excluded [..]
+See [..]
+[WARNING] [..] file `some_dir[/]dir_deep_1[/]some_dir[/]file` WILL be excluded [..]
+See [..]
+[WARNING] [..] file `some_dir[/]dir_deep_3[/]some_dir[/]file` WILL be excluded [..]
+See [..]
+[WARNING] [..] file `some_dir[/]file_deep_1` WILL be excluded [..]
+See [..]
+[ARCHIVING] [..]
+[ARCHIVING] [..]
+[ARCHIVING] [..]
+[ARCHIVING] [..]
+[ARCHIVING] [..]
+[ARCHIVING] [..]
+[ARCHIVING] [..]
+[ARCHIVING] [..]
+[ARCHIVING] [..]
+[ARCHIVING] [..]
+[ARCHIVING] [..]
+[ARCHIVING] [..]
+[ARCHIVING] [..]
+[ARCHIVING] [..]
+[ARCHIVING] [..]
+[ARCHIVING] [..]
+[ARCHIVING] [..]
+[ARCHIVING] [..]
+"));
+
+ assert_that(&p.root().join("target/package/foo-0.0.1.crate"), existing_file());
+
+ assert_that(p.cargo("package").arg("-l"),
+ execs().with_status(0).with_stdout("\
+Cargo.toml
+dir_root_1[/]some_dir[/]file
+dir_root_2[/]some_dir[/]file
+dir_root_3[/]some_dir[/]file
+file_root_3
+file_root_4
+file_root_5
+some_dir[/]dir_deep_1[/]some_dir[/]file
+some_dir[/]dir_deep_2[/]some_dir[/]file
+some_dir[/]dir_deep_3[/]some_dir[/]file
+some_dir[/]dir_deep_4[/]some_dir[/]file
+some_dir[/]dir_deep_5[/]some_dir[/]file
+some_dir[/]file_deep_1
+some_dir[/]file_deep_2
+some_dir[/]file_deep_3
+some_dir[/]file_deep_4
+some_dir[/]file_deep_5
+src[/]main.rs
+"));
+}
+
+#[test]
+fn include() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ exclude = ["*.txt"]
+ include = ["foo.txt", "**/*.rs", "Cargo.toml"]
+ "#)
+ .file("foo.txt", "")
+ .file("src/main.rs", r#"
+ fn main() { println!("hello"); }
+ "#)
+ .file("src/bar.txt", "") // should be ignored when packaging
+ .build();
+
+ assert_that(p.cargo("package").arg("--no-verify").arg("-v"),
+ execs().with_status(0).with_stderr("\
+[WARNING] manifest has no description[..]
+See http://doc.crates.io/manifest.html#package-metadata for more info.
+[PACKAGING] foo v0.0.1 ([..])
+[ARCHIVING] [..]
+[ARCHIVING] [..]
+[ARCHIVING] [..]
+"));
+}
+
+#[test]
+fn package_lib_with_bin() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/main.rs", r#"
+ extern crate foo;
+ fn main() {}
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("package").arg("-v"),
+ execs().with_status(0));
+}
+
+#[test]
+fn package_git_submodule() {
+ let project = git::new("foo", |project| {
+ project.file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = ["foo@example.com"]
+ license = "MIT"
+ description = "foo"
+ repository = "foo"
+ "#)
+ .file("src/lib.rs", "pub fn foo() {}")
+ }).unwrap();
+ let library = git::new("bar", |library| {
+ library.file("Makefile", "all:")
+ }).unwrap();
+
+ let repository = git2::Repository::open(&project.root()).unwrap();
+ let url = path2url(library.root()).to_string();
+ git::add_submodule(&repository, &url, Path::new("bar"));
+ git::commit(&repository);
+
+ let repository = git2::Repository::open(&project.root().join("bar")).unwrap();
+ repository.reset(&repository.revparse_single("HEAD").unwrap(),
+ git2::ResetType::Hard, None).unwrap();
+
+ assert_that(cargo_process().arg("package").cwd(project.root())
+ .arg("--no-verify").arg("-v"),
+ execs().with_status(0).with_stderr_contains("[ARCHIVING] bar/Makefile"));
+}
+
+#[test]
+fn no_duplicates_from_modified_tracked_files() {
+ let root = paths::root().join("all");
+ let p = git::repo(&root)
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/main.rs", r#"
+ fn main() {}
+ "#)
+ .build();
+ File::create(p.root().join("src/main.rs")).unwrap().write_all(br#"
+ fn main() { println!("A change!"); }
+ "#).unwrap();
+ let mut cargo = cargo_process();
+ cargo.cwd(p.root());
+ assert_that(cargo.clone().arg("build"), execs().with_status(0));
+ assert_that(cargo.arg("package").arg("--list"),
+ execs().with_status(0).with_stdout("\
+Cargo.toml
+src/main.rs
+"));
+}
+
+#[test]
+fn ignore_nested() {
+ let cargo_toml = r#"
+ [project]
+ name = "nested"
+ version = "0.0.1"
+ authors = []
+ license = "MIT"
+ description = "nested"
+ "#;
+ let main_rs = r#"
+ fn main() { println!("hello"); }
+ "#;
+ let p = project("nested")
+ .file("Cargo.toml", cargo_toml)
+ .file("src/main.rs", main_rs)
+ // If a project happens to contain a copy of itself, we should
+ // ignore it.
+ .file("a_dir/nested/Cargo.toml", cargo_toml)
+ .file("a_dir/nested/src/main.rs", main_rs)
+ .build();
+
+ assert_that(p.cargo("package"),
+ execs().with_status(0).with_stderr(&format!("\
+[WARNING] manifest has no documentation[..]
+See http://doc.crates.io/manifest.html#package-metadata for more info.
+[PACKAGING] nested v0.0.1 ({dir})
+[VERIFYING] nested v0.0.1 ({dir})
+[COMPILING] nested v0.0.1 ({dir}[..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+",
+ dir = p.url())));
+ assert_that(&p.root().join("target/package/nested-0.0.1.crate"), existing_file());
+ assert_that(p.cargo("package").arg("-l"),
+ execs().with_status(0).with_stdout("\
+Cargo.toml
+src[..]main.rs
+"));
+ assert_that(p.cargo("package"),
+ execs().with_status(0).with_stdout(""));
+
+ let f = File::open(&p.root().join("target/package/nested-0.0.1.crate")).unwrap();
+ let mut rdr = GzDecoder::new(f);
+ let mut contents = Vec::new();
+ rdr.read_to_end(&mut contents).unwrap();
+ let mut ar = Archive::new(&contents[..]);
+ for f in ar.entries().unwrap() {
+ let f = f.unwrap();
+ let fname = f.header().path_bytes();
+ let fname = &*fname;
+ assert!(fname == b"nested-0.0.1/Cargo.toml" ||
+ fname == b"nested-0.0.1/Cargo.toml.orig" ||
+ fname == b"nested-0.0.1/src/main.rs",
+ "unexpected filename: {:?}", f.header().path())
+ }
+}
+
+#[cfg(unix)] // windows doesn't allow these characters in filenames
+#[test]
+fn package_weird_characters() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/main.rs", r#"
+ fn main() { println!("hello"); }
+ "#)
+ .file("src/:foo", "")
+ .build();
+
+ assert_that(p.cargo("package"),
+ execs().with_status(101).with_stderr("\
+warning: [..]
+See [..]
+[PACKAGING] foo [..]
+[ERROR] failed to prepare local package for uploading
+
+Caused by:
+ cannot package a filename with a special character `:`: src/:foo
+"));
+}
+
+#[test]
+fn repackage_on_source_change() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/main.rs", r#"
+ fn main() { println!("hello"); }
+ "#)
+ .build();
+
+ assert_that(p.cargo("package"),
+ execs().with_status(0));
+
+ // Add another source file
+ let mut file = File::create(p.root().join("src").join("foo.rs")).unwrap_or_else(|e| {
+ panic!("could not create file {}: {}", p.root().join("src/foo.rs").display(), e)
+ });
+
+ file.write_all(br#"
+ fn main() { println!("foo"); }
+ "#).unwrap();
+ std::mem::drop(file);
+
+ let mut pro = process(&cargo_exe());
+ pro.arg("package").cwd(p.root());
+
+ // Check that cargo rebuilds the tarball
+ assert_that(pro, execs().with_status(0).with_stderr(&format!("\
+[WARNING] [..]
+See [..]
+[PACKAGING] foo v0.0.1 ({dir})
+[VERIFYING] foo v0.0.1 ({dir})
+[COMPILING] foo v0.0.1 ({dir}[..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+",
+ dir = p.url())));
+
+ // Check that the tarball contains the added file
+ let f = File::open(&p.root().join("target/package/foo-0.0.1.crate")).unwrap();
+ let mut rdr = GzDecoder::new(f);
+ let mut contents = Vec::new();
+ rdr.read_to_end(&mut contents).unwrap();
+ let mut ar = Archive::new(&contents[..]);
+ let entries = ar.entries().unwrap();
+ let entry_paths = entries.map(|entry| {
+ entry.unwrap().path().unwrap().into_owned()
+ }).collect::<Vec<PathBuf>>();
+ assert_that(&entry_paths, contains(vec![PathBuf::from("foo-0.0.1/src/foo.rs")]));
+}
+
+#[test]
+#[cfg(unix)]
+fn broken_symlink() {
+ use std::os::unix::fs;
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ license = "MIT"
+ description = 'foo'
+ documentation = 'foo'
+ homepage = 'foo'
+ repository = 'foo'
+ "#)
+ .file("src/main.rs", r#"
+ fn main() { println!("hello"); }
+ "#)
+ .build();
+ t!(fs::symlink("nowhere", &p.root().join("src/foo.rs")));
+
+ assert_that(p.cargo("package").arg("-v"),
+ execs().with_status(101)
+ .with_stderr_contains("\
+error: failed to prepare local package for uploading
+
+Caused by:
+ failed to open for archiving: `[..]foo.rs`
+
+Caused by:
+ [..]
+"));
+}
+
+#[test]
+fn do_not_package_if_repository_is_dirty() {
+ let p = project("foo").build();
+
+ // Create a Git repository containing a minimal Rust project.
+ let _ = git::repo(&paths::root().join("foo"))
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ license = "MIT"
+ description = "foo"
+ documentation = "foo"
+ homepage = "foo"
+ repository = "foo"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ // Modify Cargo.toml without committing the change.
+ p.change_file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ license = "MIT"
+ description = "foo"
+ documentation = "foo"
+ homepage = "foo"
+ repository = "foo"
+ # change
+ "#);
+
+ assert_that(p.cargo("package"),
+ execs().with_status(101)
+ .with_stderr("\
+error: 1 files in the working directory contain changes that were not yet \
+committed into git:
+
+Cargo.toml
+
+to proceed despite this, pass the `--allow-dirty` flag
+"));
+}
+
+#[test]
+fn generated_manifest() {
+ Package::new("abc", "1.0.0").publish();
+ Package::new("def", "1.0.0").publish();
+ Package::new("ghi", "1.0.0").publish();
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ cargo-features = ["alternative-registries"]
+
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ exclude = ["*.txt"]
+ license = "MIT"
+ description = "foo"
+
+ [project.metadata]
+ foo = 'bar'
+
+ [workspace]
+
+ [dependencies]
+ bar = { path = "bar", version = "0.1" }
+ def = { version = "1.0", registry = "alternative" }
+ ghi = "1.0"
+ abc = "1.0"
+ "#)
+ .file("src/main.rs", "")
+ .file("bar/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("bar/src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("package")
+ .masquerade_as_nightly_cargo()
+ .arg("--no-verify"),
+ execs().with_status(0));
+
+ let f = File::open(&p.root().join("target/package/foo-0.0.1.crate")).unwrap();
+ let mut rdr = GzDecoder::new(f);
+ let mut contents = Vec::new();
+ rdr.read_to_end(&mut contents).unwrap();
+ let mut ar = Archive::new(&contents[..]);
+ let mut entry = ar.entries().unwrap()
+ .map(|f| f.unwrap())
+ .find(|e| e.path().unwrap().ends_with("Cargo.toml"))
+ .unwrap();
+ let mut contents = String::new();
+ entry.read_to_string(&mut contents).unwrap();
+ // BTreeMap makes the order of dependencies in the generated file deterministic
+ // by sorting alphabetically
+ assert_that(&contents[..], equal_to(
+&*format!(
+r#"# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g. crates.io) dependencies
+#
+# If you believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
+cargo-features = ["alternative-registries"]
+
+[package]
+name = "foo"
+version = "0.0.1"
+authors = []
+exclude = ["*.txt"]
+description = "foo"
+license = "MIT"
+
+[package.metadata]
+foo = "bar"
+[dependencies.abc]
+version = "1.0"
+
+[dependencies.bar]
+version = "0.1"
+
+[dependencies.def]
+version = "1.0"
+registry-index = "{}"
+
+[dependencies.ghi]
+version = "1.0"
+"#,
+ registry::alt_registry())));
+}
+
+#[test]
+fn ignore_workspace_specifier() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+
+ authors = []
+
+ [workspace]
+
+ [dependencies]
+ bar = { path = "bar", version = "0.1" }
+ "#)
+ .file("src/main.rs", "")
+ .file("bar/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+ workspace = ".."
+ "#)
+ .file("bar/src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("package").arg("--no-verify").cwd(p.root().join("bar")),
+ execs().with_status(0));
+
+ let f = File::open(&p.root().join("target/package/bar-0.1.0.crate")).unwrap();
+ let mut rdr = GzDecoder::new(f);
+ let mut contents = Vec::new();
+ rdr.read_to_end(&mut contents).unwrap();
+ let mut ar = Archive::new(&contents[..]);
+ let mut entry = ar.entries().unwrap()
+ .map(|f| f.unwrap())
+ .find(|e| e.path().unwrap().ends_with("Cargo.toml"))
+ .unwrap();
+ let mut contents = String::new();
+ entry.read_to_string(&mut contents).unwrap();
+ assert_that(&contents[..], equal_to(
+r#"# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g. crates.io) dependencies
+#
+# If you believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
+[package]
+name = "bar"
+version = "0.1.0"
+authors = []
+"#));
+}
+
+#[test]
+fn package_two_kinds_of_deps() {
+ Package::new("other", "1.0.0").publish();
+ Package::new("other1", "1.0.0").publish();
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ other = "1.0"
+ other1 = { version = "1.0" }
+ "#)
+ .file("src/main.rs", "")
+ .build();
+
+ assert_that(p.cargo("package").arg("--no-verify"),
+ execs().with_status(0));
+}
+
+#[test]
+fn test_epoch() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ cargo-features = ["epoch"]
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ rust = "2018"
+ "#)
+ .file("src/lib.rs", r#" "#)
+ .build();
+
+ assert_that(p.cargo("build").arg("-v")
+ .masquerade_as_nightly_cargo(),
+ execs()
+ // -Zepoch is still in flux and we're not passing -Zunstable-options
+ // from Cargo so it will probably error. Only partially match the output
+ // until stuff stabilizes
+ .with_stderr_contains(format!("\
+[COMPILING] foo v0.0.1 ({url})
+[RUNNING] `rustc --crate-name foo src[/]lib.rs --crate-type lib \
+ --emit=dep-info,link -Zepoch=2018 -C debuginfo=2 \
+ -C metadata=[..] \
+ --out-dir [..] \
+ -L dependency={dir}[/]target[/]debug[/]deps`
+", dir = p.root().display(), url = p.url())));
+}
+
+#[test]
+fn test_epoch_missing() {
+ // no epoch = 2015
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ cargo-features = ["epoch"]
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/lib.rs", r#" "#)
+ .build();
+
+ assert_that(p.cargo("build").arg("-v")
+ .masquerade_as_nightly_cargo(),
+ execs()
+ // -Zepoch is still in flux and we're not passing -Zunstable-options
+ // from Cargo so it will probably error. Only partially match the output
+ // until stuff stabilizes
+ .with_stderr_contains(format!("\
+[COMPILING] foo v0.0.1 ({url})
+[RUNNING] `rustc --crate-name foo src[/]lib.rs --crate-type lib \
+ --emit=dep-info,link -Zepoch=2015 -C debuginfo=2 \
+ -C metadata=[..] \
+ --out-dir [..] \
+ -L dependency={dir}[/]target[/]debug[/]deps`
+", dir = p.root().display(), url = p.url())));
+}
+
+#[test]
+fn test_epoch_malformed() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ cargo-features = ["epoch"]
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ rust = "chicken"
+ "#)
+ .file("src/lib.rs", r#" "#)
+ .build();
+
+ assert_that(p.cargo("build").arg("-v")
+ .masquerade_as_nightly_cargo(),
+ execs()
+ .with_status(101)
+ .with_stderr(format!("\
+error: failed to parse manifest at `[..]`
+
+Caused by:
+ the `rust` key must be one of: `2015`, `2018`
+")));
+}
+
+
+#[test]
+fn test_epoch_nightly() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ rust = "2015"
+ "#)
+ .file("src/lib.rs", r#" "#)
+ .build();
+
+ assert_that(p.cargo("build").arg("-v")
+ .masquerade_as_nightly_cargo(),
+ execs()
+ .with_status(101)
+ .with_stderr(format!("\
+error: failed to parse manifest at `[..]`
+
+Caused by:
+ epoches are unstable
+
+Caused by:
+ feature `epoch` is required
+
+consider adding `cargo-features = [\"epoch\"]` to the manifest
+")));
+}
--- /dev/null
+use std::fs::{self, File};
+use std::io::{Read, Write};
+
+use toml;
+use cargotest::support::git;
+use cargotest::support::paths;
+use cargotest::support::registry::Package;
+use cargotest::support::{execs, project};
+use hamcrest::assert_that;
+
+#[test]
+fn replace() {
+ Package::new("foo", "0.1.0").publish();
+ Package::new("deep-foo", "0.1.0")
+ .file("src/lib.rs", r#"
+ extern crate foo;
+ pub fn deep() {
+ foo::foo();
+ }
+ "#)
+ .dep("foo", "0.1.0")
+ .publish();
+
+ let p = project("bar")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ foo = "0.1.0"
+ deep-foo = "0.1.0"
+
+ [patch.crates-io]
+ foo = { path = "foo" }
+ "#)
+ .file("src/lib.rs", "
+ extern crate foo;
+ extern crate deep_foo;
+ pub fn bar() {
+ foo::foo();
+ deep_foo::deep();
+ }
+ ")
+ .file("foo/Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("foo/src/lib.rs", r#"
+ pub fn foo() {}
+ "#)
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr("\
+[UPDATING] registry `file://[..]`
+[DOWNLOADING] deep-foo v0.1.0 ([..])
+[COMPILING] foo v0.1.0 (file://[..])
+[COMPILING] deep-foo v0.1.0
+[COMPILING] bar v0.0.1 (file://[..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+
+ assert_that(p.cargo("build"),//.env("RUST_LOG", "trace"),
+ execs().with_status(0).with_stderr("[FINISHED] [..]"));
+}
+
+#[test]
+fn nonexistent() {
+ Package::new("baz", "0.1.0").publish();
+
+ let p = project("bar")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ foo = "0.1.0"
+
+ [patch.crates-io]
+ foo = { path = "foo" }
+ "#)
+ .file("src/lib.rs", "
+ extern crate foo;
+ pub fn bar() {
+ foo::foo();
+ }
+ ")
+ .file("foo/Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("foo/src/lib.rs", r#"
+ pub fn foo() {}
+ "#)
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr("\
+[UPDATING] registry `file://[..]`
+[COMPILING] foo v0.1.0 (file://[..])
+[COMPILING] bar v0.0.1 (file://[..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr("[FINISHED] [..]"));
+}
+
+#[test]
+fn patch_git() {
+ let foo = git::repo(&paths::root().join("override"))
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+
+ let p = project("bar")
+ .file("Cargo.toml", &format!(r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ foo = {{ git = '{}' }}
+
+ [patch.'{0}']
+ foo = {{ path = "foo" }}
+ "#, foo.url()))
+ .file("src/lib.rs", "
+ extern crate foo;
+ pub fn bar() {
+ foo::foo();
+ }
+ ")
+ .file("foo/Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("foo/src/lib.rs", r#"
+ pub fn foo() {}
+ "#)
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr("\
+[UPDATING] git repository `file://[..]`
+[COMPILING] foo v0.1.0 (file://[..])
+[COMPILING] bar v0.0.1 (file://[..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr("[FINISHED] [..]"));
+}
+
+#[test]
+fn patch_to_git() {
+ let foo = git::repo(&paths::root().join("override"))
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("src/lib.rs", "pub fn foo() {}")
+ .build();
+
+ Package::new("foo", "0.1.0").publish();
+
+ let p = project("bar")
+ .file("Cargo.toml", &format!(r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ foo = "0.1"
+
+ [patch.crates-io]
+ foo = {{ git = '{}' }}
+ "#, foo.url()))
+ .file("src/lib.rs", "
+ extern crate foo;
+ pub fn bar() {
+ foo::foo();
+ }
+ ")
+ .build();
+
+ assert_that(p.cargo("build"),//.env("RUST_LOG", "cargo=trace"),
+ execs().with_status(0).with_stderr("\
+[UPDATING] git repository `file://[..]`
+[UPDATING] registry `file://[..]`
+[COMPILING] foo v0.1.0 (file://[..])
+[COMPILING] bar v0.0.1 (file://[..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr("[FINISHED] [..]"));
+}
+
+#[test]
+fn unused() {
+ Package::new("foo", "0.1.0").publish();
+
+ let p = project("bar")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ foo = "0.1.0"
+
+ [patch.crates-io]
+ foo = { path = "foo" }
+ "#)
+ .file("src/lib.rs", "")
+ .file("foo/Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.2.0"
+ authors = []
+ "#)
+ .file("foo/src/lib.rs", r#"
+ not rust code
+ "#)
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr("\
+[UPDATING] registry `file://[..]`
+[DOWNLOADING] foo v0.1.0 [..]
+[COMPILING] foo v0.1.0
+[COMPILING] bar v0.0.1 (file://[..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr("[FINISHED] [..]"));
+
+ // unused patch should be in the lock file
+ let mut lock = String::new();
+ File::open(p.root().join("Cargo.lock")).unwrap()
+ .read_to_string(&mut lock).unwrap();
+ let toml: toml::Value = toml::from_str(&lock).unwrap();
+ assert_eq!(toml["patch"]["unused"].as_array().unwrap().len(), 1);
+ assert_eq!(toml["patch"]["unused"][0]["name"].as_str(), Some("foo"));
+ assert_eq!(toml["patch"]["unused"][0]["version"].as_str(), Some("0.2.0"));
+}
+
+#[test]
+fn unused_git() {
+ Package::new("foo", "0.1.0").publish();
+
+ let foo = git::repo(&paths::root().join("override"))
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.2.0"
+ authors = []
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+
+ let p = project("bar")
+ .file("Cargo.toml", &format!(r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ foo = "0.1"
+
+ [patch.crates-io]
+ foo = {{ git = '{}' }}
+ "#, foo.url()))
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr("\
+[UPDATING] git repository `file://[..]`
+[UPDATING] registry `file://[..]`
+[DOWNLOADING] foo v0.1.0 [..]
+[COMPILING] foo v0.1.0
+[COMPILING] bar v0.0.1 (file://[..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr("[FINISHED] [..]"));
+}
+
+#[test]
+fn add_patch() {
+ Package::new("foo", "0.1.0").publish();
+
+ let p = project("bar")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ foo = "0.1.0"
+ "#)
+ .file("src/lib.rs", "")
+ .file("foo/Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("foo/src/lib.rs", r#""#)
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr("\
+[UPDATING] registry `file://[..]`
+[DOWNLOADING] foo v0.1.0 [..]
+[COMPILING] foo v0.1.0
+[COMPILING] bar v0.0.1 (file://[..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr("[FINISHED] [..]"));
+
+ t!(t!(File::create(p.root().join("Cargo.toml"))).write_all(br#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ foo = "0.1.0"
+
+ [patch.crates-io]
+ foo = { path = 'foo' }
+ "#));
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr("\
+[COMPILING] foo v0.1.0 (file://[..])
+[COMPILING] bar v0.0.1 (file://[..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr("[FINISHED] [..]"));
+}
+
+#[test]
+fn add_ignored_patch() {
+ Package::new("foo", "0.1.0").publish();
+
+ let p = project("bar")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ foo = "0.1.0"
+ "#)
+ .file("src/lib.rs", "")
+ .file("foo/Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.1"
+ authors = []
+ "#)
+ .file("foo/src/lib.rs", r#""#)
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr("\
+[UPDATING] registry `file://[..]`
+[DOWNLOADING] foo v0.1.0 [..]
+[COMPILING] foo v0.1.0
+[COMPILING] bar v0.0.1 (file://[..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr("[FINISHED] [..]"));
+
+ t!(t!(File::create(p.root().join("Cargo.toml"))).write_all(br#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ foo = "0.1.0"
+
+ [patch.crates-io]
+ foo = { path = 'foo' }
+ "#));
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr("\
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr("[FINISHED] [..]"));
+}
+
+#[test]
+fn new_minor() {
+ Package::new("foo", "0.1.0").publish();
+
+ let p = project("bar")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ foo = "0.1.0"
+
+ [patch.crates-io]
+ foo = { path = 'foo' }
+ "#)
+ .file("src/lib.rs", "")
+ .file("foo/Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.1"
+ authors = []
+ "#)
+ .file("foo/src/lib.rs", r#""#)
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr("\
+[UPDATING] registry `file://[..]`
+[COMPILING] foo v0.1.1 [..]
+[COMPILING] bar v0.0.1 (file://[..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+}
+
+#[test]
+fn transitive_new_minor() {
+ Package::new("foo", "0.1.0").publish();
+
+ let p = project("bar")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ subdir = { path = 'subdir' }
+
+ [patch.crates-io]
+ foo = { path = 'foo' }
+ "#)
+ .file("src/lib.rs", "")
+ .file("subdir/Cargo.toml", r#"
+ [package]
+ name = "subdir"
+ version = "0.1.0"
+ authors = []
+
+ [dependencies]
+ foo = '0.1.0'
+ "#)
+ .file("subdir/src/lib.rs", r#""#)
+ .file("foo/Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.1"
+ authors = []
+ "#)
+ .file("foo/src/lib.rs", r#""#)
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr("\
+[UPDATING] registry `file://[..]`
+[COMPILING] foo v0.1.1 [..]
+[COMPILING] subdir v0.1.0 [..]
+[COMPILING] bar v0.0.1 (file://[..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+}
+
+#[test]
+fn new_major() {
+ Package::new("foo", "0.1.0").publish();
+
+ let p = project("bar")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ foo = "0.2.0"
+
+ [patch.crates-io]
+ foo = { path = 'foo' }
+ "#)
+ .file("src/lib.rs", "")
+ .file("foo/Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.2.0"
+ authors = []
+ "#)
+ .file("foo/src/lib.rs", r#""#)
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr("\
+[UPDATING] registry `file://[..]`
+[COMPILING] foo v0.2.0 [..]
+[COMPILING] bar v0.0.1 (file://[..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+
+ Package::new("foo", "0.2.0").publish();
+ assert_that(p.cargo("update"),
+ execs().with_status(0));
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr("\
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+
+ t!(t!(File::create(p.root().join("Cargo.toml"))).write_all(br#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ foo = "0.2.0"
+ "#));
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr("\
+[UPDATING] registry `file://[..]`
+[DOWNLOADING] foo v0.2.0 [..]
+[COMPILING] foo v0.2.0
+[COMPILING] bar v0.0.1 (file://[..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+}
+
+#[test]
+fn transitive_new_major() {
+ Package::new("foo", "0.1.0").publish();
+
+ let p = project("bar")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ subdir = { path = 'subdir' }
+
+ [patch.crates-io]
+ foo = { path = 'foo' }
+ "#)
+ .file("src/lib.rs", "")
+ .file("subdir/Cargo.toml", r#"
+ [package]
+ name = "subdir"
+ version = "0.1.0"
+ authors = []
+
+ [dependencies]
+ foo = '0.2.0'
+ "#)
+ .file("subdir/src/lib.rs", r#""#)
+ .file("foo/Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.2.0"
+ authors = []
+ "#)
+ .file("foo/src/lib.rs", r#""#)
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr("\
+[UPDATING] registry `file://[..]`
+[COMPILING] foo v0.2.0 [..]
+[COMPILING] subdir v0.1.0 [..]
+[COMPILING] bar v0.0.1 (file://[..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+}
+
+#[test]
+fn remove_patch() {
+ Package::new("foo", "0.1.0").publish();
+ Package::new("bar", "0.1.0").publish();
+
+ let p = project("bar")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ foo = "0.1"
+
+ [patch.crates-io]
+ foo = { path = 'foo' }
+ bar = { path = 'bar' }
+ "#)
+ .file("src/lib.rs", "")
+ .file("foo/Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("foo/src/lib.rs", r#""#)
+ .file("bar/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("bar/src/lib.rs", r#""#)
+ .build();
+
+ // Generate a lock file where `bar` is unused
+ assert_that(p.cargo("build"), execs().with_status(0));
+ let mut lock_file1 = String::new();
+ File::open(p.root().join("Cargo.lock")).unwrap()
+ .read_to_string(&mut lock_file1).unwrap();
+
+ // Remove `bar` and generate a new lock file form the old one
+ File::create(p.root().join("Cargo.toml")).unwrap().write_all(r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ foo = "0.1"
+
+ [patch.crates-io]
+ foo = { path = 'foo' }
+ "#.as_bytes()).unwrap();
+ assert_that(p.cargo("build"), execs().with_status(0));
+ let mut lock_file2 = String::new();
+ File::open(p.root().join("Cargo.lock")).unwrap()
+ .read_to_string(&mut lock_file2).unwrap();
+
+ // Remove the lock file and build from scratch
+ fs::remove_file(p.root().join("Cargo.lock")).unwrap();
+ assert_that(p.cargo("build"), execs().with_status(0));
+ let mut lock_file3 = String::new();
+ File::open(p.root().join("Cargo.lock")).unwrap()
+ .read_to_string(&mut lock_file3).unwrap();
+
+ assert!(lock_file1.contains("bar"));
+ assert_eq!(lock_file2, lock_file3);
+ assert!(lock_file1 != lock_file2);
+}
+
+#[test]
+fn non_crates_io() {
+ Package::new("foo", "0.1.0").publish();
+
+ let p = project("bar")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+
+ [patch.some-other-source]
+ foo = { path = 'foo' }
+ "#)
+ .file("src/lib.rs", "")
+ .file("foo/Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("foo/src/lib.rs", r#""#)
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101)
+ .with_stderr("\
+error: failed to parse manifest at `[..]`
+
+Caused by:
+ invalid url `some-other-source`: relative URL without a base
+"));
+}
+
+#[test]
+fn replace_with_crates_io() {
+ Package::new("foo", "0.1.0").publish();
+
+ let p = project("bar")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+
+ [patch.crates-io]
+ foo = "0.1"
+ "#)
+ .file("src/lib.rs", "")
+ .file("foo/Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("foo/src/lib.rs", r#""#)
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101)
+ .with_stderr("\
+[UPDATING] [..]
+error: failed to resolve patches for `[..]`
+
+Caused by:
+ patch for `foo` in `[..]` points to the same source, but patches must point \
+ to different sources
+"));
+}
+
+#[test]
+fn patch_in_virtual() {
+ Package::new("foo", "0.1.0").publish();
+
+ let p = project("bar")
+ .file("Cargo.toml", r#"
+ [workspace]
+ members = ["bar"]
+
+ [patch.crates-io]
+ foo = { path = "foo" }
+ "#)
+ .file("foo/Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("foo/src/lib.rs", r#""#)
+ .file("bar/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+
+ [dependencies]
+ foo = "0.1"
+ "#)
+ .file("bar/src/lib.rs", r#""#)
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0));
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr("\
+[FINISHED] [..]
+"));
+}
+
+#[test]
+fn patch_depends_on_another_patch() {
+ Package::new("foo", "0.1.0")
+ .file("src/lib.rs", "broken code")
+ .publish();
+
+ Package::new("bar", "0.1.0")
+ .dep("foo", "0.1")
+ .file("src/lib.rs", "broken code")
+ .publish();
+
+ let p = project("p")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "p"
+ authors = []
+ version = "0.1.0"
+
+ [dependencies]
+ foo = "0.1"
+ bar = "0.1"
+
+ [patch.crates-io]
+ foo = { path = "foo" }
+ bar = { path = "bar" }
+ "#)
+ .file("src/lib.rs", "")
+ .file("foo/Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.1"
+ authors = []
+ "#)
+ .file("foo/src/lib.rs", r#""#)
+ .file("bar/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.1.1"
+ authors = []
+
+ [dependencies]
+ foo = "0.1"
+ "#)
+ .file("bar/src/lib.rs", r#""#)
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0));
+
+ // Nothing should be rebuilt, no registry should be updated.
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr("\
+[FINISHED] [..]
+"));
+}
--- /dev/null
+use std::fs::{self, File};
+use std::io::prelude::*;
+
+use cargo::util::process;
+use cargotest;
+use cargotest::sleep_ms;
+use cargotest::support::paths::{self, CargoPathExt};
+use cargotest::support::{project, execs, main_file};
+use cargotest::support::registry::Package;
+use hamcrest::{assert_that, existing_file};
+
+#[test]
+#[cfg(not(windows))] // I have no idea why this is failing spuriously on
+ // Windows, for more info see #3466.
+fn cargo_compile_with_nested_deps_shorthand() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+
+ name = "foo"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+
+ [dependencies.bar]
+
+ version = "0.5.0"
+ path = "bar"
+ "#)
+ .file("src/main.rs",
+ &main_file(r#""{}", bar::gimme()"#, &["bar"]))
+ .file("bar/Cargo.toml", r#"
+ [project]
+
+ name = "bar"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+
+ [dependencies.baz]
+
+ version = "0.5.0"
+ path = "baz"
+
+ [lib]
+
+ name = "bar"
+ "#)
+ .file("bar/src/bar.rs", r#"
+ extern crate baz;
+
+ pub fn gimme() -> String {
+ baz::gimme()
+ }
+ "#)
+ .file("bar/baz/Cargo.toml", r#"
+ [project]
+
+ name = "baz"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+
+ [lib]
+
+ name = "baz"
+ "#)
+ .file("bar/baz/src/baz.rs", r#"
+ pub fn gimme() -> String {
+ "test passed".to_string()
+ }
+ "#)
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0)
+ .with_stderr(&format!("[COMPILING] baz v0.5.0 ({}/bar/baz)\n\
+ [COMPILING] bar v0.5.0 ({}/bar)\n\
+ [COMPILING] foo v0.5.0 ({})\n\
+ [FINISHED] dev [unoptimized + debuginfo] target(s) \
+ in [..]\n",
+ p.url(),
+ p.url(),
+ p.url())));
+
+ assert_that(&p.bin("foo"), existing_file());
+
+ assert_that(process(&p.bin("foo")),
+ execs().with_stdout("test passed\n").with_status(0));
+
+ println!("cleaning");
+ assert_that(p.cargo("clean").arg("-v"),
+ execs().with_stdout("").with_status(0));
+ println!("building baz");
+ assert_that(p.cargo("build").arg("-p").arg("baz"),
+ execs().with_status(0)
+ .with_stderr(&format!("[COMPILING] baz v0.5.0 ({}/bar/baz)\n\
+ [FINISHED] dev [unoptimized + debuginfo] target(s) \
+ in [..]\n",
+ p.url())));
+ println!("building foo");
+ assert_that(p.cargo("build")
+ .arg("-p").arg("foo"),
+ execs().with_status(0)
+ .with_stderr(&format!("[COMPILING] bar v0.5.0 ({}/bar)\n\
+ [COMPILING] foo v0.5.0 ({})\n\
+ [FINISHED] dev [unoptimized + debuginfo] target(s) \
+ in [..]\n",
+ p.url(),
+ p.url())));
+}
+
+#[test]
+fn cargo_compile_with_root_dev_deps() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+
+ name = "foo"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+
+ [dev-dependencies.bar]
+
+ version = "0.5.0"
+ path = "../bar"
+
+ [[bin]]
+ name = "foo"
+ "#)
+ .file("src/main.rs",
+ &main_file(r#""{}", bar::gimme()"#, &["bar"]))
+ .build();
+ let _p2 = project("bar")
+ .file("Cargo.toml", r#"
+ [package]
+
+ name = "bar"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+ "#)
+ .file("src/lib.rs", r#"
+ pub fn gimme() -> &'static str {
+ "zoidberg"
+ }
+ "#)
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101))
+}
+
+#[test]
+fn cargo_compile_with_root_dev_deps_with_testing() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+
+ name = "foo"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+
+ [dev-dependencies.bar]
+
+ version = "0.5.0"
+ path = "../bar"
+
+ [[bin]]
+ name = "foo"
+ "#)
+ .file("src/main.rs",
+ &main_file(r#""{}", bar::gimme()"#, &["bar"]))
+ .build();
+ let _p2 = project("bar")
+ .file("Cargo.toml", r#"
+ [package]
+
+ name = "bar"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+ "#)
+ .file("src/lib.rs", r#"
+ pub fn gimme() -> &'static str {
+ "zoidberg"
+ }
+ "#)
+ .build();
+
+ assert_that(p.cargo("test"),
+ execs().with_stderr("\
+[COMPILING] [..] v0.5.0 ([..])
+[COMPILING] [..] v0.5.0 ([..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] target[/]debug[/]deps[/]foo-[..][EXE]")
+ .with_stdout_contains("running 0 tests"));
+}
+
+#[test]
+fn cargo_compile_with_transitive_dev_deps() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+
+ name = "foo"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+
+ [dependencies.bar]
+
+ version = "0.5.0"
+ path = "bar"
+ "#)
+ .file("src/main.rs",
+ &main_file(r#""{}", bar::gimme()"#, &["bar"]))
+ .file("bar/Cargo.toml", r#"
+ [project]
+
+ name = "bar"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+
+ [dev-dependencies.baz]
+
+ git = "git://example.com/path/to/nowhere"
+
+ [lib]
+
+ name = "bar"
+ "#)
+ .file("bar/src/bar.rs", r#"
+ pub fn gimme() -> &'static str {
+ "zoidberg"
+ }
+ "#)
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_stderr(&format!("[COMPILING] bar v0.5.0 ({}/bar)\n\
+ [COMPILING] foo v0.5.0 ({})\n\
+ [FINISHED] dev [unoptimized + debuginfo] target(s) in \
+ [..]\n",
+ p.url(),
+ p.url())));
+
+ assert_that(&p.bin("foo"), existing_file());
+
+ assert_that(process(&p.bin("foo")),
+ execs().with_stdout("zoidberg\n"));
+}
+
+#[test]
+fn no_rebuild_dependency() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+
+ name = "foo"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+
+ [dependencies.bar]
+ path = "bar"
+ "#)
+ .file("src/main.rs", r#"
+ extern crate bar;
+ fn main() { bar::bar() }
+ "#)
+ .file("bar/Cargo.toml", r#"
+ [project]
+
+ name = "bar"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+
+ [lib]
+ name = "bar"
+ "#)
+ .file("bar/src/bar.rs", r#"
+ pub fn bar() {}
+ "#)
+ .build();
+ // First time around we should compile both foo and bar
+ assert_that(p.cargo("build"),
+ execs().with_stderr(&format!("[COMPILING] bar v0.5.0 ({}/bar)\n\
+ [COMPILING] foo v0.5.0 ({})\n\
+ [FINISHED] dev [unoptimized + debuginfo] target(s) \
+ in [..]\n",
+ p.url(),
+ p.url())));
+
+ sleep_ms(1000);
+ p.change_file("src/main.rs", r#"
+ extern crate bar;
+ fn main() { bar::bar(); }
+ "#);
+ // Don't compile bar, but do recompile foo.
+ assert_that(p.cargo("build"),
+ execs().with_stderr("\
+ [COMPILING] foo v0.5.0 ([..])\n\
+ [FINISHED] dev [unoptimized + debuginfo] target(s) \
+ in [..]\n"));
+}
+
+#[test]
+fn deep_dependencies_trigger_rebuild() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+
+ name = "foo"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+
+ [dependencies.bar]
+ path = "bar"
+ "#)
+ .file("src/main.rs", r#"
+ extern crate bar;
+ fn main() { bar::bar() }
+ "#)
+ .file("bar/Cargo.toml", r#"
+ [project]
+
+ name = "bar"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+
+ [lib]
+ name = "bar"
+ [dependencies.baz]
+ path = "../baz"
+ "#)
+ .file("bar/src/bar.rs", r#"
+ extern crate baz;
+ pub fn bar() { baz::baz() }
+ "#)
+ .file("baz/Cargo.toml", r#"
+ [project]
+
+ name = "baz"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+
+ [lib]
+ name = "baz"
+ "#)
+ .file("baz/src/baz.rs", r#"
+ pub fn baz() {}
+ "#)
+ .build();
+ assert_that(p.cargo("build"),
+ execs().with_stderr(&format!("[COMPILING] baz v0.5.0 ({}/baz)\n\
+ [COMPILING] bar v0.5.0 ({}/bar)\n\
+ [COMPILING] foo v0.5.0 ({})\n\
+ [FINISHED] dev [unoptimized + debuginfo] target(s) \
+ in [..]\n",
+ p.url(),
+ p.url(),
+ p.url())));
+ assert_that(p.cargo("build"),
+ execs().with_stdout(""));
+
+ // Make sure an update to baz triggers a rebuild of bar
+ //
+ // We base recompilation off mtime, so sleep for at least a second to ensure
+ // that this write will change the mtime.
+ sleep_ms(1000);
+ File::create(&p.root().join("baz/src/baz.rs")).unwrap().write_all(br#"
+ pub fn baz() { println!("hello!"); }
+ "#).unwrap();
+ assert_that(p.cargo("build"),
+ execs().with_stderr(&format!("[COMPILING] baz v0.5.0 ({}/baz)\n\
+ [COMPILING] bar v0.5.0 ({}/bar)\n\
+ [COMPILING] foo v0.5.0 ({})\n\
+ [FINISHED] dev [unoptimized + debuginfo] target(s) \
+ in [..]\n",
+ p.url(),
+ p.url(),
+ p.url())));
+
+ // Make sure an update to bar doesn't trigger baz
+ sleep_ms(1000);
+ File::create(&p.root().join("bar/src/bar.rs")).unwrap().write_all(br#"
+ extern crate baz;
+ pub fn bar() { println!("hello!"); baz::baz(); }
+ "#).unwrap();
+ assert_that(p.cargo("build"),
+ execs().with_stderr(&format!("[COMPILING] bar v0.5.0 ({}/bar)\n\
+ [COMPILING] foo v0.5.0 ({})\n\
+ [FINISHED] dev [unoptimized + debuginfo] target(s) \
+ in [..]\n",
+ p.url(),
+ p.url())));
+
+}
+
+#[test]
+fn no_rebuild_two_deps() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+
+ name = "foo"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+
+ [dependencies.bar]
+ path = "bar"
+ [dependencies.baz]
+ path = "baz"
+ "#)
+ .file("src/main.rs", r#"
+ extern crate bar;
+ fn main() { bar::bar() }
+ "#)
+ .file("bar/Cargo.toml", r#"
+ [project]
+
+ name = "bar"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+
+ [lib]
+ name = "bar"
+ [dependencies.baz]
+ path = "../baz"
+ "#)
+ .file("bar/src/bar.rs", r#"
+ pub fn bar() {}
+ "#)
+ .file("baz/Cargo.toml", r#"
+ [project]
+
+ name = "baz"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+
+ [lib]
+ name = "baz"
+ "#)
+ .file("baz/src/baz.rs", r#"
+ pub fn baz() {}
+ "#)
+ .build();
+ assert_that(p.cargo("build"),
+ execs().with_stderr(&format!("[COMPILING] baz v0.5.0 ({}/baz)\n\
+ [COMPILING] bar v0.5.0 ({}/bar)\n\
+ [COMPILING] foo v0.5.0 ({})\n\
+ [FINISHED] dev [unoptimized + debuginfo] target(s) \
+ in [..]\n",
+ p.url(),
+ p.url(),
+ p.url())));
+ assert_that(&p.bin("foo"), existing_file());
+ assert_that(p.cargo("build"),
+ execs().with_stdout(""));
+ assert_that(&p.bin("foo"), existing_file());
+}
+
+#[test]
+fn nested_deps_recompile() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+
+ name = "foo"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+
+ [dependencies.bar]
+
+ version = "0.5.0"
+ path = "src/bar"
+ "#)
+ .file("src/main.rs",
+ &main_file(r#""{}", bar::gimme()"#, &["bar"]))
+ .file("src/bar/Cargo.toml", r#"
+ [project]
+
+ name = "bar"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+
+ [lib]
+
+ name = "bar"
+ "#)
+ .file("src/bar/src/bar.rs", "pub fn gimme() -> i32 { 92 }")
+ .build();
+ let bar = p.url();
+
+ assert_that(p.cargo("build"),
+ execs().with_stderr(&format!("[COMPILING] bar v0.5.0 ({}/src/bar)\n\
+ [COMPILING] foo v0.5.0 ({})\n\
+ [FINISHED] dev [unoptimized + debuginfo] target(s) \
+ in [..]\n",
+ bar,
+ p.url())));
+ sleep_ms(1000);
+
+ File::create(&p.root().join("src/main.rs")).unwrap().write_all(br#"
+ fn main() {}
+ "#).unwrap();
+
+ // This shouldn't recompile `bar`
+ assert_that(p.cargo("build"),
+ execs().with_stderr(&format!("[COMPILING] foo v0.5.0 ({})\n\
+ [FINISHED] dev [unoptimized + debuginfo] target(s) \
+ in [..]\n",
+ p.url())));
+}
+
+#[test]
+fn error_message_for_missing_manifest() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+
+ name = "foo"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+
+ [dependencies.bar]
+
+ path = "src/bar"
+ "#)
+ .file("src/lib.rs", "")
+ .file("src/bar/not-a-manifest", "")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101)
+ .with_stderr("\
+[ERROR] failed to load source for a dependency on `bar`
+
+Caused by:
+ Unable to update file://[..]
+
+Caused by:
+ failed to read `[..]bar[/]Cargo.toml`
+
+Caused by:
+ [..] (os error [..])
+"));
+
+}
+
+#[test]
+fn override_relative() {
+ let bar = project("bar")
+ .file("Cargo.toml", r#"
+ [package]
+
+ name = "bar"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+
+ fs::create_dir(&paths::root().join(".cargo")).unwrap();
+ File::create(&paths::root().join(".cargo/config")).unwrap()
+ .write_all(br#"paths = ["bar"]"#).unwrap();
+
+ let p = project("foo")
+ .file("Cargo.toml", &format!(r#"
+ [package]
+
+ name = "foo"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+
+ [dependencies.bar]
+ path = '{}'
+ "#, bar.root().display()))
+ .file("src/lib.rs", "")
+ .build();
+ assert_that(p.cargo("build").arg("-v"), execs().with_status(0));
+
+}
+
+#[test]
+fn override_self() {
+ let bar = project("bar")
+ .file("Cargo.toml", r#"
+ [package]
+
+ name = "bar"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+
+ let p = project("foo");
+ let root = p.root().clone();
+ let p = p
+ .file(".cargo/config", &format!(r#"
+ paths = ['{}']
+ "#, root.display()))
+ .file("Cargo.toml", &format!(r#"
+ [package]
+
+ name = "foo"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+
+ [dependencies.bar]
+ path = '{}'
+
+ "#, bar.root().display()))
+ .file("src/lib.rs", "")
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("build"), execs().with_status(0));
+}
+
+#[test]
+fn override_path_dep() {
+ let bar = project("bar")
+ .file("p1/Cargo.toml", r#"
+ [package]
+ name = "p1"
+ version = "0.5.0"
+ authors = []
+
+ [dependencies.p2]
+ path = "../p2"
+ "#)
+ .file("p1/src/lib.rs", "")
+ .file("p2/Cargo.toml", r#"
+ [package]
+ name = "p2"
+ version = "0.5.0"
+ authors = []
+ "#)
+ .file("p2/src/lib.rs", "")
+ .build();
+
+ let p = project("foo")
+ .file(".cargo/config", &format!(r#"
+ paths = ['{}', '{}']
+ "#, bar.root().join("p1").display(),
+ bar.root().join("p2").display()))
+ .file("Cargo.toml", &format!(r#"
+ [package]
+
+ name = "foo"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+
+ [dependencies.p2]
+ path = '{}'
+
+ "#, bar.root().join("p2").display()))
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(0));
+
+}
+
+#[test]
+fn path_dep_build_cmd() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+
+ name = "foo"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+
+ [dependencies.bar]
+
+ version = "0.5.0"
+ path = "bar"
+ "#)
+ .file("src/main.rs",
+ &main_file(r#""{}", bar::gimme()"#, &["bar"]))
+ .file("bar/Cargo.toml", r#"
+ [project]
+
+ name = "bar"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+ build = "build.rs"
+
+ [lib]
+ name = "bar"
+ path = "src/bar.rs"
+ "#)
+ .file("bar/build.rs", r#"
+ use std::fs;
+ fn main() {
+ fs::copy("src/bar.rs.in", "src/bar.rs").unwrap();
+ }
+ "#)
+ .file("bar/src/bar.rs.in", r#"
+ pub fn gimme() -> i32 { 0 }
+ "#).build();
+ p.root().join("bar").move_into_the_past();
+
+ assert_that(p.cargo("build"),
+ execs().with_stderr(&format!("[COMPILING] bar v0.5.0 ({}/bar)\n\
+ [COMPILING] foo v0.5.0 ({})\n\
+ [FINISHED] dev [unoptimized + debuginfo] target(s) in \
+ [..]\n",
+ p.url(),
+ p.url())));
+
+ assert_that(&p.bin("foo"), existing_file());
+
+ assert_that(process(&p.bin("foo")),
+ execs().with_stdout("0\n"));
+
+ // Touching bar.rs.in should cause the `build` command to run again.
+ {
+ let file = fs::File::create(&p.root().join("bar/src/bar.rs.in"));
+ file.unwrap().write_all(br#"pub fn gimme() -> i32 { 1 }"#).unwrap();
+ }
+
+ assert_that(p.cargo("build"),
+ execs().with_stderr(&format!("[COMPILING] bar v0.5.0 ({}/bar)\n\
+ [COMPILING] foo v0.5.0 ({})\n\
+ [FINISHED] dev [unoptimized + debuginfo] target(s) in \
+ [..]\n",
+ p.url(),
+ p.url())));
+
+ assert_that(process(&p.bin("foo")),
+ execs().with_stdout("1\n"));
+}
+
+#[test]
+fn dev_deps_no_rebuild_lib() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+ authors = []
+
+ [dev-dependencies.bar]
+ path = "bar"
+
+ [lib]
+ name = "foo"
+ doctest = false
+ "#)
+ .file("src/lib.rs", r#"
+ #[cfg(test)] #[allow(unused_extern_crates)] extern crate bar;
+ #[cfg(not(test))] pub fn foo() { env!("FOO"); }
+ "#)
+ .file("bar/Cargo.toml", r#"
+ [package]
+
+ name = "bar"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+ "#)
+ .file("bar/src/lib.rs", "pub fn bar() {}")
+ .build();
+ assert_that(p.cargo("build")
+ .env("FOO", "bar"),
+ execs().with_status(0)
+ .with_stderr(&format!("[COMPILING] foo v0.5.0 ({})\n\
+ [FINISHED] dev [unoptimized + debuginfo] target(s) \
+ in [..]\n",
+ p.url())));
+
+ assert_that(p.cargo("test"),
+ execs().with_status(0)
+ .with_stderr(&format!("\
+[COMPILING] [..] v0.5.0 ({url}[..])
+[COMPILING] [..] v0.5.0 ({url}[..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] target[/]debug[/]deps[/]foo-[..][EXE]", url = p.url()))
+ .with_stdout_contains("running 0 tests"));
+}
+
+#[test]
+fn custom_target_no_rebuild() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+ authors = []
+ [dependencies]
+ a = { path = "a" }
+ [workspace]
+ members = ["a", "b"]
+ "#)
+ .file("src/lib.rs", "")
+ .file("a/Cargo.toml", r#"
+ [project]
+ name = "a"
+ version = "0.5.0"
+ authors = []
+ "#)
+ .file("a/src/lib.rs", "")
+ .file("b/Cargo.toml", r#"
+ [project]
+ name = "b"
+ version = "0.5.0"
+ authors = []
+ [dependencies]
+ a = { path = "../a" }
+ "#)
+ .file("b/src/lib.rs", "")
+ .build();
+ assert_that(p.cargo("build"),
+ execs().with_status(0)
+ .with_stderr("\
+[COMPILING] a v0.5.0 ([..])
+[COMPILING] foo v0.5.0 ([..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+
+ t!(fs::rename(p.root().join("target"), p.root().join("target_moved")));
+ assert_that(p.cargo("build")
+ .arg("--manifest-path=b/Cargo.toml")
+ .env("CARGO_TARGET_DIR", "target_moved"),
+ execs().with_status(0)
+ .with_stderr("\
+[COMPILING] b v0.5.0 ([..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+}
+
+#[test]
+fn override_and_depend() {
+ let p = project("foo")
+ .file("a/a1/Cargo.toml", r#"
+ [project]
+ name = "a1"
+ version = "0.5.0"
+ authors = []
+ [dependencies]
+ a2 = { path = "../a2" }
+ "#)
+ .file("a/a1/src/lib.rs", "")
+ .file("a/a2/Cargo.toml", r#"
+ [project]
+ name = "a2"
+ version = "0.5.0"
+ authors = []
+ "#)
+ .file("a/a2/src/lib.rs", "")
+ .file("b/Cargo.toml", r#"
+ [project]
+ name = "b"
+ version = "0.5.0"
+ authors = []
+ [dependencies]
+ a1 = { path = "../a/a1" }
+ a2 = { path = "../a/a2" }
+ "#)
+ .file("b/src/lib.rs", "")
+ .file("b/.cargo/config", r#"
+ paths = ["../a"]
+ "#)
+ .build();
+ assert_that(p.cargo("build").cwd(p.root().join("b")),
+ execs().with_status(0)
+ .with_stderr("\
+[COMPILING] a2 v0.5.0 ([..])
+[COMPILING] a1 v0.5.0 ([..])
+[COMPILING] b v0.5.0 ([..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+}
+
+#[test]
+fn missing_path_dependency() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "a"
+ version = "0.5.0"
+ authors = []
+ "#)
+ .file("src/lib.rs", "")
+ .file(".cargo/config", r#"
+ paths = ["../whoa-this-does-not-exist"]
+ "#)
+ .build();
+ assert_that(p.cargo("build"),
+ execs().with_status(101)
+ .with_stderr("\
+[ERROR] failed to update path override `[..]../whoa-this-does-not-exist` \
+(defined in `[..]`)
+
+Caused by:
+ failed to read directory `[..]`
+
+Caused by:
+ [..] (os error [..])
+"));
+}
+
+#[test]
+fn invalid_path_dep_in_workspace_with_lockfile() {
+ Package::new("bar", "1.0.0").publish();
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "top"
+ version = "0.5.0"
+ authors = []
+
+ [workspace]
+
+ [dependencies]
+ foo = { path = "foo" }
+ "#)
+ .file("src/lib.rs", "")
+ .file("foo/Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+ authors = []
+
+ [dependencies]
+ bar = "*"
+ "#)
+ .file("foo/src/lib.rs", "")
+ .build();
+
+ // Generate a lock file
+ assert_that(p.cargo("build"), execs().with_status(0));
+
+ // Change the dependency on `bar` to an invalid path
+ File::create(&p.root().join("foo/Cargo.toml")).unwrap().write_all(br#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+ authors = []
+
+ [dependencies]
+ bar = { path = "" }
+ "#).unwrap();
+
+ // Make sure we get a nice error. In the past this actually stack
+ // overflowed!
+ assert_that(p.cargo("build"),
+ execs().with_status(101)
+ .with_stderr("\
+error: no matching package named `bar` found
+location searched: [..]
+required by package `foo v0.5.0 ([..])`
+"));
+}
+
+#[test]
+fn workspace_produces_rlib() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "top"
+ version = "0.5.0"
+ authors = []
+
+ [workspace]
+
+ [dependencies]
+ foo = { path = "foo" }
+ "#)
+ .file("src/lib.rs", "")
+ .file("foo/Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+ authors = []
+ "#)
+ .file("foo/src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"), execs().with_status(0));
+
+ assert_that(&p.root().join("target/debug/libtop.rlib"), existing_file());
+ assert_that(&p.root().join("target/debug/libfoo.rlib"), existing_file());
+
+}
+
+#[test]
+fn thin_lto_works() {
+ if !cargotest::is_nightly() {
+ return
+ }
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "top"
+ version = "0.5.0"
+ authors = []
+
+ [profile.release]
+ lto = 'thin'
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("build").arg("--release").arg("-v"),
+ execs().with_stderr("\
+[COMPILING] top [..]
+[RUNNING] `rustc [..] -C lto=thin [..]`
+[FINISHED] [..]
+"));
+}
--- /dev/null
+use std::fs;
+use std::env;
+
+use cargotest::{is_nightly, rustc_host};
+use cargotest::support::{project, execs};
+use hamcrest::assert_that;
+
+#[test]
+fn plugin_to_the_max() {
+ if !is_nightly() { return }
+
+ let foo = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [lib]
+ name = "foo_lib"
+
+ [dependencies.bar]
+ path = "../bar"
+ "#)
+ .file("src/main.rs", r#"
+ #![feature(plugin)]
+ #![plugin(bar)]
+ extern crate foo_lib;
+
+ fn main() { foo_lib::foo(); }
+ "#)
+ .file("src/foo_lib.rs", r#"
+ #![feature(plugin)]
+ #![plugin(bar)]
+
+ pub fn foo() {}
+ "#)
+ .build();
+ let _bar = project("bar")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+
+ [lib]
+ name = "bar"
+ plugin = true
+
+ [dependencies.baz]
+ path = "../baz"
+ "#)
+ .file("src/lib.rs", r#"
+ #![feature(plugin_registrar, rustc_private)]
+
+ extern crate rustc_plugin;
+ extern crate baz;
+
+ use rustc_plugin::Registry;
+
+ #[plugin_registrar]
+ pub fn foo(_reg: &mut Registry) {
+ println!("{}", baz::baz());
+ }
+ "#)
+ .build();
+ let _baz = project("baz")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "baz"
+ version = "0.0.1"
+ authors = []
+
+ [lib]
+ name = "baz"
+ crate_type = ["dylib"]
+ "#)
+ .file("src/lib.rs", "pub fn baz() -> i32 { 1 }")
+ .build();
+
+ assert_that(foo.cargo("build"),
+ execs().with_status(0));
+ assert_that(foo.cargo("doc"),
+ execs().with_status(0));
+}
+
+#[test]
+fn plugin_with_dynamic_native_dependency() {
+ if !is_nightly() { return }
+
+ let workspace = project("ws")
+ .file("Cargo.toml", r#"
+ [workspace]
+ members = ["builder", "foo"]
+ "#)
+ .build();
+
+ let build = project("ws/builder")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "builder"
+ version = "0.0.1"
+ authors = []
+
+ [lib]
+ name = "builder"
+ crate-type = ["dylib"]
+ "#)
+ .file("src/lib.rs", r#"
+ #[no_mangle]
+ pub extern fn foo() {}
+ "#)
+ .build();
+
+ let foo = project("ws/foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.bar]
+ path = "bar"
+ "#)
+ .file("src/main.rs", r#"
+ #![feature(plugin)]
+ #![plugin(bar)]
+
+ fn main() {}
+ "#)
+ .file("bar/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+ build = 'build.rs'
+
+ [lib]
+ name = "bar"
+ plugin = true
+ "#)
+ .file("bar/build.rs", r#"
+ use std::path::PathBuf;
+ use std::env;
+
+ fn main() {
+ let src = PathBuf::from(env::var("SRC").unwrap());
+ println!("cargo:rustc-flags=-L {}/deps", src.parent().unwrap().display());
+ }
+ "#)
+ .file("bar/src/lib.rs", r#"
+ #![feature(plugin_registrar, rustc_private)]
+ extern crate rustc_plugin;
+
+ use rustc_plugin::Registry;
+
+ #[cfg_attr(not(target_env = "msvc"), link(name = "builder"))]
+ #[cfg_attr(target_env = "msvc", link(name = "builder.dll"))]
+ extern { fn foo(); }
+
+ #[plugin_registrar]
+ pub fn bar(_reg: &mut Registry) {
+ unsafe { foo() }
+ }
+ "#)
+ .build();
+
+ assert_that(build.cargo("build"),
+ execs().with_status(0));
+
+ let src = workspace.root().join("target/debug");
+ let lib = fs::read_dir(&src).unwrap().map(|s| s.unwrap().path()).find(|lib| {
+ let lib = lib.file_name().unwrap().to_str().unwrap();
+ lib.starts_with(env::consts::DLL_PREFIX) &&
+ lib.ends_with(env::consts::DLL_SUFFIX)
+ }).unwrap();
+
+ assert_that(foo.cargo("build").env("SRC", &lib).arg("-v"),
+ execs().with_status(0));
+}
+
+#[test]
+fn plugin_integration() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ build = "build.rs"
+
+ [lib]
+ name = "foo"
+ plugin = true
+ doctest = false
+ "#)
+ .file("build.rs", "fn main() {}")
+ .file("src/lib.rs", "")
+ .file("tests/it_works.rs", "")
+ .build();
+
+ assert_that(p.cargo("test").arg("-v"),
+ execs().with_status(0));
+}
+
+#[test]
+fn doctest_a_plugin() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ bar = { path = "bar" }
+ "#)
+ .file("src/lib.rs", r#"
+ #[macro_use]
+ extern crate bar;
+ "#)
+ .file("bar/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+
+ [lib]
+ name = "bar"
+ plugin = true
+ "#)
+ .file("bar/src/lib.rs", r#"
+ pub fn bar() {}
+ "#)
+ .build();
+
+ assert_that(p.cargo("test").arg("-v"),
+ execs().with_status(0));
+}
+
+// See #1515
+#[test]
+fn native_plugin_dependency_with_custom_ar_linker() {
+ let target = rustc_host();
+
+ let _foo = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [lib]
+ plugin = true
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+
+ let bar = project("bar")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.foo]
+ path = "../foo"
+ "#)
+ .file("src/lib.rs", "")
+ .file(".cargo/config", &format!(r#"
+ [target.{}]
+ ar = "nonexistent-ar"
+ linker = "nonexistent-linker"
+ "#, target))
+ .build();
+
+ assert_that(bar.cargo("build").arg("--verbose"),
+ execs().with_stderr_contains("\
+[COMPILING] foo v0.0.1 ([..])
+[RUNNING] `rustc [..] -C ar=nonexistent-ar -C linker=nonexistent-linker [..]`
+[ERROR] [..]linker[..]
+"));
+}
+
+#[test]
+fn panic_abort_plugins() {
+ if !is_nightly() {
+ return
+ }
+
+ let p = project("bar")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+
+ [profile.dev]
+ panic = 'abort'
+
+ [dependencies]
+ foo = { path = "foo" }
+ "#)
+ .file("src/lib.rs", "")
+ .file("foo/Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [lib]
+ plugin = true
+ "#)
+ .file("foo/src/lib.rs", r#"
+ #![feature(rustc_private)]
+ extern crate syntax;
+ "#)
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0));
+}
+
+#[test]
+fn shared_panic_abort_plugins() {
+ if !is_nightly() {
+ return
+ }
+
+ let p = project("top")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "top"
+ version = "0.0.1"
+ authors = []
+
+ [profile.dev]
+ panic = 'abort'
+
+ [dependencies]
+ foo = { path = "foo" }
+ bar = { path = "bar" }
+ "#)
+ .file("src/lib.rs", "
+ extern crate bar;
+ ")
+ .file("foo/Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [lib]
+ plugin = true
+
+ [dependencies]
+ bar = { path = "../bar" }
+ "#)
+ .file("foo/src/lib.rs", r#"
+ #![feature(rustc_private)]
+ extern crate syntax;
+ extern crate bar;
+ "#)
+ .file("bar/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("bar/src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0));
+}
--- /dev/null
+use cargotest::is_nightly;
+use cargotest::support::{project, execs};
+use hamcrest::assert_that;
+
+#[test]
+fn probe_cfg_before_crate_type_discovery() {
+ if !is_nightly() {
+ return;
+ }
+
+ let client = project("client")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "client"
+ version = "0.0.1"
+ authors = []
+
+ [target.'cfg(not(stage300))'.dependencies.noop]
+ path = "../noop"
+ "#)
+ .file("src/main.rs", r#"
+ #![feature(proc_macro)]
+
+ #[macro_use]
+ extern crate noop;
+
+ #[derive(Noop)]
+ struct X;
+
+ fn main() {}
+ "#)
+ .build();
+ let _noop = project("noop")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "noop"
+ version = "0.0.1"
+ authors = []
+
+ [lib]
+ proc-macro = true
+ "#)
+ .file("src/lib.rs", r#"
+ #![feature(proc_macro, proc_macro_lib)]
+
+ extern crate proc_macro;
+ use proc_macro::TokenStream;
+
+ #[proc_macro_derive(Noop)]
+ pub fn noop(_input: TokenStream) -> TokenStream {
+ "".parse().unwrap()
+ }
+ "#)
+ .build();
+
+ assert_that(client.cargo("build"),
+ execs().with_status(0));
+}
+
+#[test]
+fn noop() {
+ if !is_nightly() {
+ return;
+ }
+
+ let client = project("client")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "client"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.noop]
+ path = "../noop"
+ "#)
+ .file("src/main.rs", r#"
+ #![feature(proc_macro)]
+
+ #[macro_use]
+ extern crate noop;
+
+ #[derive(Noop)]
+ struct X;
+
+ fn main() {}
+ "#)
+ .build();
+ let _noop = project("noop")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "noop"
+ version = "0.0.1"
+ authors = []
+
+ [lib]
+ proc-macro = true
+ "#)
+ .file("src/lib.rs", r#"
+ #![feature(proc_macro, proc_macro_lib)]
+
+ extern crate proc_macro;
+ use proc_macro::TokenStream;
+
+ #[proc_macro_derive(Noop)]
+ pub fn noop(_input: TokenStream) -> TokenStream {
+ "".parse().unwrap()
+ }
+ "#)
+ .build();
+
+ assert_that(client.cargo("build"),
+ execs().with_status(0));
+ assert_that(client.cargo("build"),
+ execs().with_status(0));
+}
+
+#[test]
+fn impl_and_derive() {
+ if !is_nightly() {
+ return;
+ }
+
+ let client = project("client")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "client"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.transmogrify]
+ path = "../transmogrify"
+ "#)
+ .file("src/main.rs", r#"
+ #![feature(proc_macro)]
+
+ #[macro_use]
+ extern crate transmogrify;
+
+ trait ImplByTransmogrify {
+ fn impl_by_transmogrify(&self) -> bool;
+ }
+
+ #[derive(Transmogrify, Debug)]
+ struct X { success: bool }
+
+ fn main() {
+ let x = X::new();
+ assert!(x.impl_by_transmogrify());
+ println!("{:?}", x);
+ }
+ "#)
+ .build();
+ let _transmogrify = project("transmogrify")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "transmogrify"
+ version = "0.0.1"
+ authors = []
+
+ [lib]
+ proc-macro = true
+ "#)
+ .file("src/lib.rs", r#"
+ #![feature(proc_macro, proc_macro_lib)]
+
+ extern crate proc_macro;
+ use proc_macro::TokenStream;
+
+ #[proc_macro_derive(Transmogrify)]
+ #[doc(hidden)]
+ pub fn transmogrify(input: TokenStream) -> TokenStream {
+ "
+ impl X {
+ fn new() -> Self {
+ X { success: true }
+ }
+ }
+
+ impl ImplByTransmogrify for X {
+ fn impl_by_transmogrify(&self) -> bool {
+ true
+ }
+ }
+ ".parse().unwrap()
+ }
+ "#)
+ .build();
+
+ assert_that(client.cargo("build"),
+ execs().with_status(0));
+ assert_that(client.cargo("run"),
+ execs().with_status(0).with_stdout("X { success: true }"));
+}
+
+#[test]
+fn plugin_and_proc_macro() {
+ if !is_nightly() {
+ return;
+ }
+
+ let questionable = project("questionable")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "questionable"
+ version = "0.0.1"
+ authors = []
+
+ [lib]
+ plugin = true
+ proc-macro = true
+ "#)
+ .file("src/lib.rs", r#"
+ #![feature(plugin_registrar, rustc_private)]
+ #![feature(proc_macro, proc_macro_lib)]
+
+ extern crate rustc_plugin;
+ use rustc_plugin::Registry;
+
+ extern crate proc_macro;
+ use proc_macro::TokenStream;
+
+ #[plugin_registrar]
+ pub fn plugin_registrar(reg: &mut Registry) {}
+
+ #[proc_macro_derive(Questionable)]
+ pub fn questionable(input: TokenStream) -> TokenStream {
+ input
+ }
+ "#)
+ .build();
+
+ let msg = " lib.plugin and lib.proc-macro cannot both be true";
+ assert_that(questionable.cargo("build"),
+ execs().with_status(101).with_stderr_contains(msg));
+}
+
+#[test]
+fn proc_macro_doctest() {
+ if !is_nightly() {
+ return
+ }
+ let foo = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ [lib]
+ proc-macro = true
+ "#)
+ .file("src/lib.rs", r#"
+#![feature(proc_macro, proc_macro_lib)]
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+/// ```
+/// assert!(true);
+/// ```
+#[proc_macro_derive(Bar)]
+pub fn derive(_input: TokenStream) -> TokenStream {
+ "".parse().unwrap()
+}
+
+#[test]
+fn a() {
+ assert!(true);
+}
+"#)
+ .build();
+
+ assert_that(foo.cargo("test"),
+ execs().with_status(0)
+ .with_stdout_contains("test a ... ok")
+ .with_stdout_contains_n("test [..] ... ok", 2));
+}
--- /dev/null
+use std::env;
+
+use cargotest::is_nightly;
+use cargotest::support::{project, execs};
+use hamcrest::assert_that;
+
+#[test]
+fn profile_overrides() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+
+ name = "test"
+ version = "0.0.0"
+ authors = []
+
+ [profile.dev]
+ opt-level = 1
+ debug = false
+ rpath = true
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(0).with_stderr(&format!("\
+[COMPILING] test v0.0.0 ({url})
+[RUNNING] `rustc --crate-name test src[/]lib.rs --crate-type lib \
+ --emit=dep-info,link \
+ -C opt-level=1 \
+ -C debug-assertions=on \
+ -C metadata=[..] \
+ -C rpath \
+ --out-dir [..] \
+ -L dependency={dir}[/]target[/]debug[/]deps`
+[FINISHED] dev [optimized] target(s) in [..]
+",
+dir = p.root().display(),
+url = p.url(),
+)));
+}
+
+#[test]
+fn opt_level_override_0() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+
+ name = "test"
+ version = "0.0.0"
+ authors = []
+
+ [profile.dev]
+ opt-level = 0
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(0).with_stderr(&format!("\
+[COMPILING] test v0.0.0 ({url})
+[RUNNING] `rustc --crate-name test src[/]lib.rs --crate-type lib \
+ --emit=dep-info,link \
+ -C debuginfo=2 \
+ -C metadata=[..] \
+ --out-dir [..] \
+ -L dependency={dir}[/]target[/]debug[/]deps`
+[FINISHED] [..] target(s) in [..]
+",
+dir = p.root().display(),
+url = p.url()
+)));
+}
+
+#[test]
+fn debug_override_1() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "test"
+ version = "0.0.0"
+ authors = []
+
+ [profile.dev]
+ debug = 1
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(0).with_stderr(&format!("\
+[COMPILING] test v0.0.0 ({url})
+[RUNNING] `rustc --crate-name test src[/]lib.rs --crate-type lib \
+ --emit=dep-info,link \
+ -C debuginfo=1 \
+ -C metadata=[..] \
+ --out-dir [..] \
+ -L dependency={dir}[/]target[/]debug[/]deps`
+[FINISHED] [..] target(s) in [..]
+",
+dir = p.root().display(),
+url = p.url()
+)));
+}
+
+fn check_opt_level_override(profile_level: &str, rustc_level: &str) {
+ let p = project("foo")
+ .file("Cargo.toml", &format!(r#"
+ [package]
+
+ name = "test"
+ version = "0.0.0"
+ authors = []
+
+ [profile.dev]
+ opt-level = {level}
+ "#, level = profile_level))
+ .file("src/lib.rs", "")
+ .build();
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(0).with_stderr(&format!("\
+[COMPILING] test v0.0.0 ({url})
+[RUNNING] `rustc --crate-name test src[/]lib.rs --crate-type lib \
+ --emit=dep-info,link \
+ -C opt-level={level} \
+ -C debuginfo=2 \
+ -C debug-assertions=on \
+ -C metadata=[..] \
+ --out-dir [..] \
+ -L dependency={dir}[/]target[/]debug[/]deps`
+[FINISHED] [..] target(s) in [..]
+",
+dir = p.root().display(),
+url = p.url(),
+level = rustc_level
+)));
+}
+
+#[test]
+fn opt_level_overrides() {
+ if !is_nightly() { return }
+
+ for &(profile_level, rustc_level) in &[
+ ("1", "1"),
+ ("2", "2"),
+ ("3", "3"),
+ ("\"s\"", "s"),
+ ("\"z\"", "z"),
+ ] {
+ check_opt_level_override(profile_level, rustc_level)
+ }
+}
+
+#[test]
+fn top_level_overrides_deps() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+
+ name = "test"
+ version = "0.0.0"
+ authors = []
+
+ [profile.release]
+ opt-level = 1
+ debug = true
+
+ [dependencies.foo]
+ path = "foo"
+ "#)
+ .file("src/lib.rs", "")
+ .file("foo/Cargo.toml", r#"
+ [package]
+
+ name = "foo"
+ version = "0.0.0"
+ authors = []
+
+ [profile.release]
+ opt-level = 0
+ debug = false
+
+ [lib]
+ name = "foo"
+ crate_type = ["dylib", "rlib"]
+ "#)
+ .file("foo/src/lib.rs", "")
+ .build();
+ assert_that(p.cargo("build").arg("-v").arg("--release"),
+ execs().with_status(0).with_stderr(&format!("\
+[COMPILING] foo v0.0.0 ({url}/foo)
+[RUNNING] `rustc --crate-name foo foo[/]src[/]lib.rs \
+ --crate-type dylib --crate-type rlib \
+ --emit=dep-info,link \
+ -C prefer-dynamic \
+ -C opt-level=1 \
+ -C debuginfo=2 \
+ -C metadata=[..] \
+ --out-dir {dir}[/]target[/]release[/]deps \
+ -L dependency={dir}[/]target[/]release[/]deps`
+[COMPILING] test v0.0.0 ({url})
+[RUNNING] `rustc --crate-name test src[/]lib.rs --crate-type lib \
+ --emit=dep-info,link \
+ -C opt-level=1 \
+ -C debuginfo=2 \
+ -C metadata=[..] \
+ --out-dir [..] \
+ -L dependency={dir}[/]target[/]release[/]deps \
+ --extern foo={dir}[/]target[/]release[/]deps[/]\
+ {prefix}foo[..]{suffix} \
+ --extern foo={dir}[/]target[/]release[/]deps[/]libfoo.rlib`
+[FINISHED] release [optimized + debuginfo] target(s) in [..]
+",
+ dir = p.root().display(),
+ url = p.url(),
+ prefix = env::consts::DLL_PREFIX,
+ suffix = env::consts::DLL_SUFFIX)));
+}
+
+#[test]
+fn profile_in_non_root_manifest_triggers_a_warning() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+
+ [workspace]
+ members = ["bar"]
+
+ [profile.dev]
+ debug = false
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .file("bar/Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+ workspace = ".."
+
+ [profile.dev]
+ opt-level = 1
+ "#)
+ .file("bar/src/main.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("build").cwd(p.root().join("bar")).arg("-v"),
+ execs().with_status(0).with_stderr("\
+[WARNING] profiles for the non root package will be ignored, specify profiles at the workspace root:
+package: [..]
+workspace: [..]
+[COMPILING] bar v0.1.0 ([..])
+[RUNNING] `rustc [..]`
+[FINISHED] dev [unoptimized] target(s) in [..]"));
+}
+
+#[test]
+fn profile_in_virtual_manifest_works() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [workspace]
+ members = ["bar"]
+
+ [profile.dev]
+ opt-level = 1
+ debug = false
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .file("bar/Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+ workspace = ".."
+ "#)
+ .file("bar/src/main.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("build").cwd(p.root().join("bar")).arg("-v"),
+ execs().with_status(0).with_stderr("\
+[COMPILING] bar v0.1.0 ([..])
+[RUNNING] `rustc [..]`
+[FINISHED] dev [optimized] target(s) in [..]"));
+}
--- /dev/null
+use std::io::prelude::*;
+use std::fs::{self, File};
+use std::io::SeekFrom;
+
+use cargotest::ChannelChanger;
+use cargotest::support::git::repo;
+use cargotest::support::paths;
+use cargotest::support::{project, execs, publish};
+use flate2::read::GzDecoder;
+use hamcrest::assert_that;
+use tar::Archive;
+
+#[test]
+fn simple() {
+ publish::setup();
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ license = "MIT"
+ description = "foo"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("publish").arg("--no-verify")
+ .arg("--index").arg(publish::registry().to_string()),
+ execs().with_status(0).with_stderr(&format!("\
+[UPDATING] registry `{reg}`
+[WARNING] manifest has no documentation, [..]
+See [..]
+[PACKAGING] foo v0.0.1 ({dir})
+[UPLOADING] foo v0.0.1 ({dir})
+",
+ dir = p.url(),
+ reg = publish::registry())));
+
+ let mut f = File::open(&publish::upload_path().join("api/v1/crates/new")).unwrap();
+ // Skip the metadata payload and the size of the tarball
+ let mut sz = [0; 4];
+ assert_eq!(f.read(&mut sz).unwrap(), 4);
+ let sz = ((sz[0] as u32) << 0) |
+ ((sz[1] as u32) << 8) |
+ ((sz[2] as u32) << 16) |
+ ((sz[3] as u32) << 24);
+ f.seek(SeekFrom::Current(sz as i64 + 4)).unwrap();
+
+ // Verify the tarball
+ let mut rdr = GzDecoder::new(f);
+ assert_eq!(rdr.header().unwrap().filename().unwrap(), b"foo-0.0.1.crate");
+ let mut contents = Vec::new();
+ rdr.read_to_end(&mut contents).unwrap();
+ let mut ar = Archive::new(&contents[..]);
+ for file in ar.entries().unwrap() {
+ let file = file.unwrap();
+ let fname = file.header().path_bytes();
+ let fname = &*fname;
+ assert!(fname == b"foo-0.0.1/Cargo.toml" ||
+ fname == b"foo-0.0.1/Cargo.toml.orig" ||
+ fname == b"foo-0.0.1/src/main.rs",
+ "unexpected filename: {:?}", file.header().path());
+ }
+}
+
+#[test]
+fn old_token_location() {
+ publish::setup();
+
+ // publish::setup puts a token in this file.
+ fs::remove_file(paths::root().join(".cargo/config")).unwrap();
+
+ let credentials = paths::root().join("home/.cargo/credentials");
+ File::create(credentials)
+ .unwrap()
+ .write_all(br#"
+ token = "api-token"
+ "#)
+ .unwrap();
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ license = "MIT"
+ description = "foo"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("publish").arg("--no-verify")
+ .arg("--index").arg(publish::registry().to_string()),
+ execs().with_status(0).with_stderr(&format!("\
+[UPDATING] registry `{reg}`
+[WARNING] manifest has no documentation, [..]
+See [..]
+[PACKAGING] foo v0.0.1 ({dir})
+[UPLOADING] foo v0.0.1 ({dir})
+",
+ dir = p.url(),
+ reg = publish::registry())));
+
+ let mut f = File::open(&publish::upload_path().join("api/v1/crates/new")).unwrap();
+ // Skip the metadata payload and the size of the tarball
+ let mut sz = [0; 4];
+ assert_eq!(f.read(&mut sz).unwrap(), 4);
+ let sz = ((sz[0] as u32) << 0) |
+ ((sz[1] as u32) << 8) |
+ ((sz[2] as u32) << 16) |
+ ((sz[3] as u32) << 24);
+ f.seek(SeekFrom::Current(sz as i64 + 4)).unwrap();
+
+ // Verify the tarball
+ let mut rdr = GzDecoder::new(f);
+ assert_eq!(rdr.header().unwrap().filename().unwrap(), b"foo-0.0.1.crate");
+ let mut contents = Vec::new();
+ rdr.read_to_end(&mut contents).unwrap();
+ let mut ar = Archive::new(&contents[..]);
+ for file in ar.entries().unwrap() {
+ let file = file.unwrap();
+ let fname = file.header().path_bytes();
+ let fname = &*fname;
+ assert!(fname == b"foo-0.0.1/Cargo.toml" ||
+ fname == b"foo-0.0.1/Cargo.toml.orig" ||
+ fname == b"foo-0.0.1/src/main.rs",
+ "unexpected filename: {:?}", file.header().path());
+ }
+}
+
+// TODO: Deprecated
+// remove once it has been decided --host can be removed
+#[test]
+fn simple_with_host() {
+ publish::setup();
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ license = "MIT"
+ description = "foo"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("publish").arg("--no-verify")
+ .arg("--host").arg(publish::registry().to_string()),
+ execs().with_status(0).with_stderr(&format!("\
+[WARNING] The flag '--host' is no longer valid.
+
+Previous versions of Cargo accepted this flag, but it is being
+deprecated. The flag is being renamed to 'index', as the flag
+wants the location of the index to which to publish. Please
+use '--index' instead.
+
+This will soon become a hard error, so it's either recommended
+to update to a fixed version or contact the upstream maintainer
+about this warning.
+[UPDATING] registry `{reg}`
+[WARNING] manifest has no documentation, [..]
+See [..]
+[PACKAGING] foo v0.0.1 ({dir})
+[UPLOADING] foo v0.0.1 ({dir})
+",
+ dir = p.url(),
+ reg = publish::registry())));
+
+ let mut f = File::open(&publish::upload_path().join("api/v1/crates/new")).unwrap();
+ // Skip the metadata payload and the size of the tarball
+ let mut sz = [0; 4];
+ assert_eq!(f.read(&mut sz).unwrap(), 4);
+ let sz = ((sz[0] as u32) << 0) |
+ ((sz[1] as u32) << 8) |
+ ((sz[2] as u32) << 16) |
+ ((sz[3] as u32) << 24);
+ f.seek(SeekFrom::Current(sz as i64 + 4)).unwrap();
+
+ // Verify the tarball
+ let mut rdr = GzDecoder::new(f);
+ assert_eq!(rdr.header().unwrap().filename().unwrap(), "foo-0.0.1.crate".as_bytes());
+ let mut contents = Vec::new();
+ rdr.read_to_end(&mut contents).unwrap();
+ let mut ar = Archive::new(&contents[..]);
+ for file in ar.entries().unwrap() {
+ let file = file.unwrap();
+ let fname = file.header().path_bytes();
+ let fname = &*fname;
+ assert!(fname == b"foo-0.0.1/Cargo.toml" ||
+ fname == b"foo-0.0.1/Cargo.toml.orig" ||
+ fname == b"foo-0.0.1/src/main.rs",
+ "unexpected filename: {:?}", file.header().path());
+ }
+}
+
+// TODO: Deprecated
+// remove once it has been decided --host can be removed
+#[test]
+fn simple_with_index_and_host() {
+ publish::setup();
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ license = "MIT"
+ description = "foo"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("publish").arg("--no-verify")
+ .arg("--index").arg(publish::registry().to_string())
+ .arg("--host").arg(publish::registry().to_string()),
+ execs().with_status(0).with_stderr(&format!("\
+[WARNING] The flag '--host' is no longer valid.
+
+Previous versions of Cargo accepted this flag, but it is being
+deprecated. The flag is being renamed to 'index', as the flag
+wants the location of the index to which to publish. Please
+use '--index' instead.
+
+This will soon become a hard error, so it's either recommended
+to update to a fixed version or contact the upstream maintainer
+about this warning.
+[UPDATING] registry `{reg}`
+[WARNING] manifest has no documentation, [..]
+See [..]
+[PACKAGING] foo v0.0.1 ({dir})
+[UPLOADING] foo v0.0.1 ({dir})
+",
+ dir = p.url(),
+ reg = publish::registry())));
+
+ let mut f = File::open(&publish::upload_path().join("api/v1/crates/new")).unwrap();
+ // Skip the metadata payload and the size of the tarball
+ let mut sz = [0; 4];
+ assert_eq!(f.read(&mut sz).unwrap(), 4);
+ let sz = ((sz[0] as u32) << 0) |
+ ((sz[1] as u32) << 8) |
+ ((sz[2] as u32) << 16) |
+ ((sz[3] as u32) << 24);
+ f.seek(SeekFrom::Current(sz as i64 + 4)).unwrap();
+
+ // Verify the tarball
+ let mut rdr = GzDecoder::new(f);
+ assert_eq!(rdr.header().unwrap().filename().unwrap(), "foo-0.0.1.crate".as_bytes());
+ let mut contents = Vec::new();
+ rdr.read_to_end(&mut contents).unwrap();
+ let mut ar = Archive::new(&contents[..]);
+ for file in ar.entries().unwrap() {
+ let file = file.unwrap();
+ let fname = file.header().path_bytes();
+ let fname = &*fname;
+ assert!(fname == b"foo-0.0.1/Cargo.toml" ||
+ fname == b"foo-0.0.1/Cargo.toml.orig" ||
+ fname == b"foo-0.0.1/src/main.rs",
+ "unexpected filename: {:?}", file.header().path());
+ }
+}
+
+#[test]
+fn git_deps() {
+ publish::setup();
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ license = "MIT"
+ description = "foo"
+
+ [dependencies.foo]
+ git = "git://path/to/nowhere"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("publish").arg("-v").arg("--no-verify")
+ .arg("--index").arg(publish::registry().to_string()),
+ execs().with_status(101).with_stderr("\
+[UPDATING] registry [..]
+[ERROR] crates cannot be published to crates.io with dependencies sourced from \
+a repository\neither publish `foo` as its own crate on crates.io and \
+specify a crates.io version as a dependency or pull it into this \
+repository and specify it with a path and version\n\
+(crate `foo` has repository path `git://path/to/nowhere`)\
+"));
+}
+
+#[test]
+fn path_dependency_no_version() {
+ publish::setup();
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ license = "MIT"
+ description = "foo"
+
+ [dependencies.bar]
+ path = "bar"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .file("bar/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("bar/src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("publish")
+ .arg("--index").arg(publish::registry().to_string()),
+ execs().with_status(101).with_stderr("\
+[UPDATING] registry [..]
+[ERROR] all path dependencies must have a version specified when publishing.
+dependency `bar` does not specify a version
+"));
+}
+
+#[test]
+fn unpublishable_crate() {
+ publish::setup();
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ license = "MIT"
+ description = "foo"
+ publish = false
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("publish")
+ .arg("--index").arg(publish::registry().to_string()),
+ execs().with_status(101).with_stderr("\
+[ERROR] some crates cannot be published.
+`foo` is marked as unpublishable
+"));
+}
+
+#[test]
+fn dont_publish_dirty() {
+ publish::setup();
+ let p = project("foo")
+ .file("bar", "")
+ .build();
+
+ let _ = repo(&paths::root().join("foo"))
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ license = "MIT"
+ description = "foo"
+ documentation = "foo"
+ homepage = "foo"
+ repository = "foo"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("publish")
+ .arg("--index").arg(publish::registry().to_string()),
+ execs().with_status(101).with_stderr("\
+[UPDATING] registry `[..]`
+error: 1 files in the working directory contain changes that were not yet \
+committed into git:
+
+bar
+
+to proceed despite this, pass the `--allow-dirty` flag
+"));
+}
+
+#[test]
+fn publish_clean() {
+ publish::setup();
+
+ let p = project("foo").build();
+
+ let _ = repo(&paths::root().join("foo"))
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ license = "MIT"
+ description = "foo"
+ documentation = "foo"
+ homepage = "foo"
+ repository = "foo"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("publish")
+ .arg("--index").arg(publish::registry().to_string()),
+ execs().with_status(0));
+}
+
+#[test]
+fn publish_in_sub_repo() {
+ publish::setup();
+
+ let p = project("foo")
+ .file("baz", "")
+ .build();
+
+ let _ = repo(&paths::root().join("foo"))
+ .file("bar/Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ license = "MIT"
+ description = "foo"
+ documentation = "foo"
+ homepage = "foo"
+ repository = "foo"
+ "#)
+ .file("bar/src/main.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("publish").cwd(p.root().join("bar"))
+ .arg("--index").arg(publish::registry().to_string()),
+ execs().with_status(0));
+}
+
+#[test]
+fn publish_when_ignored() {
+ publish::setup();
+
+ let p = project("foo")
+ .file("baz", "")
+ .build();
+
+ let _ = repo(&paths::root().join("foo"))
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ license = "MIT"
+ description = "foo"
+ documentation = "foo"
+ homepage = "foo"
+ repository = "foo"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .file(".gitignore", "baz")
+ .build();
+
+ assert_that(p.cargo("publish")
+ .arg("--index").arg(publish::registry().to_string()),
+ execs().with_status(0));
+}
+
+#[test]
+fn ignore_when_crate_ignored() {
+ publish::setup();
+
+ let p = project("foo")
+ .file("bar/baz", "")
+ .build();
+
+ let _ = repo(&paths::root().join("foo"))
+ .file(".gitignore", "bar")
+ .nocommit_file("bar/Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ license = "MIT"
+ description = "foo"
+ documentation = "foo"
+ homepage = "foo"
+ repository = "foo"
+ "#)
+ .nocommit_file("bar/src/main.rs", "fn main() {}");
+ assert_that(p.cargo("publish").cwd(p.root().join("bar"))
+ .arg("--index").arg(publish::registry().to_string()),
+ execs().with_status(0));
+}
+
+#[test]
+fn new_crate_rejected() {
+ publish::setup();
+
+ let p = project("foo")
+ .file("baz", "")
+ .build();
+
+ let _ = repo(&paths::root().join("foo"))
+ .nocommit_file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ license = "MIT"
+ description = "foo"
+ documentation = "foo"
+ homepage = "foo"
+ repository = "foo"
+ "#)
+ .nocommit_file("src/main.rs", "fn main() {}");
+ assert_that(p.cargo("publish")
+ .arg("--index").arg(publish::registry().to_string()),
+ execs().with_status(101));
+}
+
+#[test]
+fn dry_run() {
+ publish::setup();
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ license = "MIT"
+ description = "foo"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("publish").arg("--dry-run")
+ .arg("--index").arg(publish::registry().to_string()),
+ execs().with_status(0).with_stderr(&format!("\
+[UPDATING] registry `[..]`
+[WARNING] manifest has no documentation, [..]
+See [..]
+[PACKAGING] foo v0.0.1 ({dir})
+[VERIFYING] foo v0.0.1 ({dir})
+[COMPILING] foo v0.0.1 [..]
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[UPLOADING] foo v0.0.1 ({dir})
+[WARNING] aborting upload due to dry run
+",
+ dir = p.url())));
+
+ // Ensure the API request wasn't actually made
+ assert!(!publish::upload_path().join("api/v1/crates/new").exists());
+}
+
+#[test]
+fn block_publish_feature_not_enabled() {
+ publish::setup();
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ license = "MIT"
+ description = "foo"
+ publish = [
+ "test"
+ ]
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("publish").masquerade_as_nightly_cargo()
+ .arg("--registry").arg("alternative").arg("-Zunstable-options"),
+ execs().with_status(101).with_stderr("\
+error: failed to parse manifest at `[..]`
+
+Caused by:
+ the `publish` manifest key is unstable for anything other than a value of true or false
+
+Caused by:
+ feature `alternative-registries` is required
+
+consider adding `cargo-features = [\"alternative-registries\"]` to the manifest
+"));
+}
+
+#[test]
+fn registry_not_in_publish_list() {
+ publish::setup();
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ cargo-features = ["alternative-registries"]
+
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ license = "MIT"
+ description = "foo"
+ publish = [
+ "test"
+ ]
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("publish").masquerade_as_nightly_cargo()
+ .arg("--registry").arg("alternative").arg("-Zunstable-options"),
+ execs().with_status(101).with_stderr("\
+[ERROR] some crates cannot be published.
+`foo` is marked as unpublishable
+"));
+}
+
+#[test]
+fn publish_empty_list() {
+ publish::setup();
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ cargo-features = ["alternative-registries"]
+
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ license = "MIT"
+ description = "foo"
+ publish = []
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("publish").masquerade_as_nightly_cargo()
+ .arg("--registry").arg("alternative").arg("-Zunstable-options"),
+ execs().with_status(101).with_stderr("\
+[ERROR] some crates cannot be published.
+`foo` is marked as unpublishable
+"));
+}
+
+#[test]
+fn publish_allowed_registry() {
+ publish::setup();
+
+ let p = project("foo").build();
+
+ let _ = repo(&paths::root().join("foo"))
+ .file("Cargo.toml", r#"
+ cargo-features = ["alternative-registries"]
+
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ license = "MIT"
+ description = "foo"
+ documentation = "foo"
+ homepage = "foo"
+ publish = ["alternative"]
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("publish").masquerade_as_nightly_cargo()
+ .arg("--registry").arg("alternative").arg("-Zunstable-options"),
+ execs().with_status(0));
+}
+
+#[test]
+fn block_publish_no_registry() {
+ publish::setup();
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ cargo-features = ["alternative-registries"]
+
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ license = "MIT"
+ description = "foo"
+ publish = []
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("publish").masquerade_as_nightly_cargo()
+ .arg("--registry").arg("alternative")
+ .arg("-Zunstable-options"),
+ execs().with_status(101).with_stderr("\
+[ERROR] some crates cannot be published.
+`foo` is marked as unpublishable
+"));
+}
--- /dev/null
+use cargotest::support::{project, execs, main_file, basic_bin_manifest};
+use hamcrest::{assert_that};
+
+static MANIFEST_OUTPUT: &'static str = r#"
+{
+ "name":"foo",
+ "version":"0.5.0",
+ "id":"foo[..]0.5.0[..](path+file://[..]/foo)",
+ "license": null,
+ "license_file": null,
+ "description": null,
+ "source":null,
+ "dependencies":[],
+ "targets":[{
+ "kind":["bin"],
+ "crate_types":["bin"],
+ "name":"foo",
+ "src_path":"[..][/]foo[/]src[/]foo.rs"
+ }],
+ "features":{},
+ "manifest_path":"[..]Cargo.toml"
+}"#;
+
+#[test]
+fn cargo_read_manifest_path_to_cargo_toml_relative() {
+ let p = project("foo")
+ .file("Cargo.toml", &basic_bin_manifest("foo"))
+ .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
+ .build();
+
+ assert_that(p.cargo("read-manifest")
+ .arg("--manifest-path").arg("foo/Cargo.toml")
+ .cwd(p.root().parent().unwrap()),
+ execs().with_status(0)
+ .with_json(MANIFEST_OUTPUT));
+}
+
+#[test]
+fn cargo_read_manifest_path_to_cargo_toml_absolute() {
+ let p = project("foo")
+ .file("Cargo.toml", &basic_bin_manifest("foo"))
+ .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
+ .build();
+
+ assert_that(p.cargo("read-manifest")
+ .arg("--manifest-path").arg(p.root().join("Cargo.toml"))
+ .cwd(p.root().parent().unwrap()),
+ execs().with_status(0)
+ .with_json(MANIFEST_OUTPUT));
+}
+
+#[test]
+fn cargo_read_manifest_path_to_cargo_toml_parent_relative() {
+ let p = project("foo")
+ .file("Cargo.toml", &basic_bin_manifest("foo"))
+ .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
+ .build();
+
+ assert_that(p.cargo("read-manifest")
+ .arg("--manifest-path").arg("foo")
+ .cwd(p.root().parent().unwrap()),
+ execs().with_status(101)
+ .with_stderr("[ERROR] the manifest-path must be \
+ a path to a Cargo.toml file"));
+}
+
+#[test]
+fn cargo_read_manifest_path_to_cargo_toml_parent_absolute() {
+ let p = project("foo")
+ .file("Cargo.toml", &basic_bin_manifest("foo"))
+ .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
+ .build();
+
+ assert_that(p.cargo("read-manifest")
+ .arg("--manifest-path").arg(p.root())
+ .cwd(p.root().parent().unwrap()),
+ execs().with_status(101)
+ .with_stderr("[ERROR] the manifest-path must be \
+ a path to a Cargo.toml file"));
+}
+
+#[test]
+fn cargo_read_manifest_cwd() {
+ let p = project("foo")
+ .file("Cargo.toml", &basic_bin_manifest("foo"))
+ .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
+ .build();
+
+ assert_that(p.cargo("read-manifest")
+ .cwd(p.root()),
+ execs().with_status(0)
+ .with_json(MANIFEST_OUTPUT));
+}
--- /dev/null
+use std::fs::{self, File};
+use std::io::prelude::*;
+use std::path::PathBuf;
+
+use cargotest::cargo_process;
+use cargotest::support::git;
+use cargotest::support::paths::{self, CargoPathExt};
+use cargotest::support::registry::{self, Package};
+use cargotest::support::{project, execs};
+use hamcrest::assert_that;
+use url::Url;
+
+fn registry_path() -> PathBuf { paths::root().join("registry") }
+fn registry() -> Url { Url::from_file_path(&*registry_path()).ok().unwrap() }
+
+#[test]
+fn simple() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ bar = ">= 0.0.0"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ Package::new("bar", "0.0.1").publish();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr(&format!("\
+[UPDATING] registry `{reg}`
+[DOWNLOADING] bar v0.0.1 (registry `file://[..]`)
+[COMPILING] bar v0.0.1
+[COMPILING] foo v0.0.1 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] secs
+",
+ dir = p.url(),
+ reg = registry::registry())));
+
+ assert_that(p.cargo("clean"), execs().with_status(0));
+
+ // Don't download a second time
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr(&format!("\
+[COMPILING] bar v0.0.1
+[COMPILING] foo v0.0.1 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] secs
+",
+ dir = p.url())));
+}
+
+#[test]
+fn deps() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ bar = ">= 0.0.0"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ Package::new("baz", "0.0.1").publish();
+ Package::new("bar", "0.0.1").dep("baz", "*").publish();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr(&format!("\
+[UPDATING] registry `{reg}`
+[DOWNLOADING] [..] v0.0.1 (registry `file://[..]`)
+[DOWNLOADING] [..] v0.0.1 (registry `file://[..]`)
+[COMPILING] baz v0.0.1
+[COMPILING] bar v0.0.1
+[COMPILING] foo v0.0.1 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] secs
+",
+ dir = p.url(),
+ reg = registry::registry())));
+}
+
+#[test]
+fn nonexistent() {
+ Package::new("init", "0.0.1").publish();
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ nonexistent = ">= 0.0.0"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101).with_stderr("\
+[UPDATING] registry [..]
+error: no matching package named `nonexistent` found
+location searched: registry [..]
+required by package `foo v0.0.1 ([..])`
+"));
+}
+
+#[test]
+fn wrong_version() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ foo = ">= 1.0.0"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ Package::new("foo", "0.0.1").publish();
+ Package::new("foo", "0.0.2").publish();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101).with_stderr_contains("\
+error: no matching version `>= 1.0.0` found for package `foo`
+location searched: registry [..]
+versions found: 0.0.2, 0.0.1
+required by package `foo v0.0.1 ([..])`
+"));
+
+ Package::new("foo", "0.0.3").publish();
+ Package::new("foo", "0.0.4").publish();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101).with_stderr_contains("\
+error: no matching version `>= 1.0.0` found for package `foo`
+location searched: registry [..]
+versions found: 0.0.4, 0.0.3, 0.0.2, ...
+required by package `foo v0.0.1 ([..])`
+"));
+}
+
+#[test]
+fn bad_cksum() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ bad-cksum = ">= 0.0.0"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ let pkg = Package::new("bad-cksum", "0.0.1");
+ pkg.publish();
+ t!(File::create(&pkg.archive_dst()));
+
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(101).with_stderr("\
+[UPDATING] registry [..]
+[DOWNLOADING] bad-cksum [..]
+[ERROR] unable to get packages from source
+
+Caused by:
+ failed to download replaced source registry `https://[..]`
+
+Caused by:
+ failed to verify the checksum of `bad-cksum v0.0.1 (registry `file://[..]`)`
+"));
+}
+
+#[test]
+fn update_registry() {
+ Package::new("init", "0.0.1").publish();
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ notyet = ">= 0.0.0"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101).with_stderr_contains("\
+error: no matching package named `notyet` found
+location searched: registry `[..]`
+required by package `foo v0.0.1 ([..])`
+"));
+
+ Package::new("notyet", "0.0.1").publish();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr(&format!("\
+[UPDATING] registry `{reg}`
+[DOWNLOADING] notyet v0.0.1 (registry `file://[..]`)
+[COMPILING] notyet v0.0.1
+[COMPILING] foo v0.0.1 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] secs
+",
+ dir = p.url(),
+ reg = registry::registry())));
+}
+
+#[test]
+fn package_with_path_deps() {
+ Package::new("init", "0.0.1").publish();
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ license = "MIT"
+ description = "foo"
+ repository = "bar"
+
+ [dependencies.notyet]
+ version = "0.0.1"
+ path = "notyet"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .file("notyet/Cargo.toml", r#"
+ [package]
+ name = "notyet"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("notyet/src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("package").arg("-v"),
+ execs().with_status(101).with_stderr_contains("\
+[ERROR] failed to verify package tarball
+
+Caused by:
+ no matching package named `notyet` found
+location searched: registry [..]
+required by package `foo v0.0.1 ([..])`
+"));
+
+ Package::new("notyet", "0.0.1").publish();
+
+ assert_that(p.cargo("package"),
+ execs().with_status(0).with_stderr(format!("\
+[PACKAGING] foo v0.0.1 ({dir})
+[VERIFYING] foo v0.0.1 ({dir})
+[UPDATING] registry `[..]`
+[DOWNLOADING] notyet v0.0.1 (registry `file://[..]`)
+[COMPILING] notyet v0.0.1
+[COMPILING] foo v0.0.1 ({dir}[..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] secs
+", dir = p.url())));
+}
+
+#[test]
+fn lockfile_locks() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ bar = "*"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ Package::new("bar", "0.0.1").publish();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr(&format!("\
+[UPDATING] registry `[..]`
+[DOWNLOADING] bar v0.0.1 (registry `file://[..]`)
+[COMPILING] bar v0.0.1
+[COMPILING] foo v0.0.1 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] secs
+",
+ dir = p.url())));
+
+ p.root().move_into_the_past();
+ Package::new("bar", "0.0.2").publish();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stdout(""));
+}
+
+#[test]
+fn lockfile_locks_transitively() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ bar = "*"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ Package::new("baz", "0.0.1").publish();
+ Package::new("bar", "0.0.1").dep("baz", "*").publish();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr(&format!("\
+[UPDATING] registry `[..]`
+[DOWNLOADING] [..] v0.0.1 (registry `file://[..]`)
+[DOWNLOADING] [..] v0.0.1 (registry `file://[..]`)
+[COMPILING] baz v0.0.1
+[COMPILING] bar v0.0.1
+[COMPILING] foo v0.0.1 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] secs
+",
+ dir = p.url())));
+
+ p.root().move_into_the_past();
+ Package::new("baz", "0.0.2").publish();
+ Package::new("bar", "0.0.2").dep("baz", "*").publish();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stdout(""));
+}
+
+#[test]
+fn yanks_are_not_used() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ bar = "*"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ Package::new("baz", "0.0.1").publish();
+ Package::new("baz", "0.0.2").yanked(true).publish();
+ Package::new("bar", "0.0.1").dep("baz", "*").publish();
+ Package::new("bar", "0.0.2").dep("baz", "*").yanked(true).publish();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr(&format!("\
+[UPDATING] registry `[..]`
+[DOWNLOADING] [..] v0.0.1 (registry `file://[..]`)
+[DOWNLOADING] [..] v0.0.1 (registry `file://[..]`)
+[COMPILING] baz v0.0.1
+[COMPILING] bar v0.0.1
+[COMPILING] foo v0.0.1 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] secs
+",
+ dir = p.url())));
+}
+
+#[test]
+fn relying_on_a_yank_is_bad() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ bar = "*"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ Package::new("baz", "0.0.1").publish();
+ Package::new("baz", "0.0.2").yanked(true).publish();
+ Package::new("bar", "0.0.1").dep("baz", "=0.0.2").publish();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101).with_stderr_contains("\
+error: no matching version `= 0.0.2` found for package `baz`
+location searched: registry `[..]`
+versions found: 0.0.1
+required by package `bar v0.0.1`
+"));
+}
+
+#[test]
+fn yanks_in_lockfiles_are_ok() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ bar = "*"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ Package::new("bar", "0.0.1").publish();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0));
+
+ registry::registry_path().join("3").rm_rf();
+
+ Package::new("bar", "0.0.1").yanked(true).publish();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stdout(""));
+
+ assert_that(p.cargo("update"),
+ execs().with_status(101).with_stderr_contains("\
+error: no matching package named `bar` found
+location searched: registry [..]
+required by package `foo v0.0.1 ([..])`
+"));
+}
+
+#[test]
+fn update_with_lockfile_if_packages_missing() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ bar = "*"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ Package::new("bar", "0.0.1").publish();
+ assert_that(p.cargo("build"),
+ execs().with_status(0));
+ p.root().move_into_the_past();
+
+ paths::home().join(".cargo/registry").rm_rf();
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr("\
+[UPDATING] registry `[..]`
+[DOWNLOADING] bar v0.0.1 (registry `file://[..]`)
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] secs
+"));
+}
+
+#[test]
+fn update_lockfile() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ bar = "*"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ println!("0.0.1");
+ Package::new("bar", "0.0.1").publish();
+ assert_that(p.cargo("build"),
+ execs().with_status(0));
+
+ Package::new("bar", "0.0.2").publish();
+ Package::new("bar", "0.0.3").publish();
+ paths::home().join(".cargo/registry").rm_rf();
+ println!("0.0.2 update");
+ assert_that(p.cargo("update")
+ .arg("-p").arg("bar").arg("--precise").arg("0.0.2"),
+ execs().with_status(0).with_stderr("\
+[UPDATING] registry `[..]`
+[UPDATING] bar v0.0.1 -> v0.0.2
+"));
+
+ println!("0.0.2 build");
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr(&format!("\
+[DOWNLOADING] [..] v0.0.2 (registry `file://[..]`)
+[COMPILING] bar v0.0.2
+[COMPILING] foo v0.0.1 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] secs
+",
+ dir = p.url())));
+
+ println!("0.0.3 update");
+ assert_that(p.cargo("update")
+ .arg("-p").arg("bar"),
+ execs().with_status(0).with_stderr("\
+[UPDATING] registry `[..]`
+[UPDATING] bar v0.0.2 -> v0.0.3
+"));
+
+ println!("0.0.3 build");
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr(&format!("\
+[DOWNLOADING] [..] v0.0.3 (registry `file://[..]`)
+[COMPILING] bar v0.0.3
+[COMPILING] foo v0.0.1 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] secs
+",
+ dir = p.url())));
+
+ println!("new dependencies update");
+ Package::new("bar", "0.0.4").dep("spam", "0.2.5").publish();
+ Package::new("spam", "0.2.5").publish();
+ assert_that(p.cargo("update")
+ .arg("-p").arg("bar"),
+ execs().with_status(0).with_stderr("\
+[UPDATING] registry `[..]`
+[UPDATING] bar v0.0.3 -> v0.0.4
+[ADDING] spam v0.2.5
+"));
+
+ println!("new dependencies update");
+ Package::new("bar", "0.0.5").publish();
+ assert_that(p.cargo("update")
+ .arg("-p").arg("bar"),
+ execs().with_status(0).with_stderr("\
+[UPDATING] registry `[..]`
+[UPDATING] bar v0.0.4 -> v0.0.5
+[REMOVING] spam v0.2.5
+"));
+}
+
+#[test]
+fn update_offline(){
+ use cargotest::ChannelChanger;
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ bar = "*"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+ assert_that(p.cargo("update").masquerade_as_nightly_cargo().arg("-Zoffline"),
+ execs().with_status(101).
+ with_stderr("error: you can't update in the offline mode[..]"));
+}
+
+#[test]
+fn dev_dependency_not_used() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ bar = "*"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ Package::new("baz", "0.0.1").publish();
+ Package::new("bar", "0.0.1").dev_dep("baz", "*").publish();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr(&format!("\
+[UPDATING] registry `[..]`
+[DOWNLOADING] [..] v0.0.1 (registry `file://[..]`)
+[COMPILING] bar v0.0.1
+[COMPILING] foo v0.0.1 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] secs
+",
+ dir = p.url())));
+}
+
+#[test]
+fn login_with_no_cargo_dir() {
+ let home = paths::home().join("new-home");
+ t!(fs::create_dir(&home));
+ assert_that(cargo_process().arg("login").arg("foo").arg("-v"),
+ execs().with_status(0));
+}
+
+#[test]
+fn login_with_differently_sized_token() {
+ // Verify that the configuration file gets properly trunchated.
+ let home = paths::home().join("new-home");
+ t!(fs::create_dir(&home));
+ assert_that(cargo_process().arg("login").arg("lmaolmaolmao").arg("-v"),
+ execs().with_status(0));
+ assert_that(cargo_process().arg("login").arg("lmao").arg("-v"),
+ execs().with_status(0));
+ assert_that(cargo_process().arg("login").arg("lmaolmaolmao").arg("-v"),
+ execs().with_status(0));
+}
+
+#[test]
+fn bad_license_file() {
+ Package::new("foo", "1.0.0").publish();
+ let p = project("all")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ license-file = "foo"
+ description = "bar"
+ repository = "baz"
+ "#)
+ .file("src/main.rs", r#"
+ fn main() {}
+ "#)
+ .build();
+ assert_that(p.cargo("publish")
+ .arg("-v")
+ .arg("--index").arg(registry().to_string()),
+ execs().with_status(101)
+ .with_stderr_contains("\
+[ERROR] the license file `foo` does not exist"));
+}
+
+#[test]
+fn updating_a_dep() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.a]
+ path = "a"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .file("a/Cargo.toml", r#"
+ [project]
+ name = "a"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ bar = "*"
+ "#)
+ .file("a/src/lib.rs", "")
+ .build();
+
+ Package::new("bar", "0.0.1").publish();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr(&format!("\
+[UPDATING] registry `[..]`
+[DOWNLOADING] bar v0.0.1 (registry `file://[..]`)
+[COMPILING] bar v0.0.1
+[COMPILING] a v0.0.1 ({dir}/a)
+[COMPILING] foo v0.0.1 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] secs
+",
+ dir = p.url())));
+
+ t!(t!(File::create(&p.root().join("a/Cargo.toml"))).write_all(br#"
+ [project]
+ name = "a"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ bar = "0.1.0"
+ "#));
+ Package::new("bar", "0.1.0").publish();
+
+ println!("second");
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr(&format!("\
+[UPDATING] registry `[..]`
+[DOWNLOADING] bar v0.1.0 (registry `file://[..]`)
+[COMPILING] bar v0.1.0
+[COMPILING] a v0.0.1 ({dir}/a)
+[COMPILING] foo v0.0.1 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] secs
+",
+ dir = p.url())));
+}
+
+#[test]
+fn git_and_registry_dep() {
+ let b = git::repo(&paths::root().join("b"))
+ .file("Cargo.toml", r#"
+ [project]
+ name = "b"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ a = "0.0.1"
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+ let p = project("foo")
+ .file("Cargo.toml", &format!(r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ a = "0.0.1"
+
+ [dependencies.b]
+ git = '{}'
+ "#, b.url()))
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ Package::new("a", "0.0.1").publish();
+
+ p.root().move_into_the_past();
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr(&format!("\
+[UPDATING] [..]
+[UPDATING] [..]
+[DOWNLOADING] a v0.0.1 (registry `file://[..]`)
+[COMPILING] a v0.0.1
+[COMPILING] b v0.0.1 ([..])
+[COMPILING] foo v0.0.1 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] secs
+",
+ dir = p.url())));
+ p.root().move_into_the_past();
+
+ println!("second");
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stdout(""));
+}
+
+#[test]
+fn update_publish_then_update() {
+ // First generate a Cargo.lock and a clone of the registry index at the
+ // "head" of the current registry.
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+ authors = []
+
+ [dependencies]
+ a = "0.1.0"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+ Package::new("a", "0.1.0").publish();
+ assert_that(p.cargo("build"),
+ execs().with_status(0));
+
+ // Next, publish a new package and back up the copy of the registry we just
+ // created.
+ Package::new("a", "0.1.1").publish();
+ let registry = paths::home().join(".cargo/registry");
+ let backup = paths::root().join("registry-backup");
+ t!(fs::rename(®istry, &backup));
+
+ // Generate a Cargo.lock with the newer version, and then move the old copy
+ // of the registry back into place.
+ let p2 = project("foo2")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+ authors = []
+
+ [dependencies]
+ a = "0.1.1"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+ assert_that(p2.cargo("build"),
+ execs().with_status(0));
+ registry.rm_rf();
+ t!(fs::rename(&backup, ®istry));
+ t!(fs::rename(p2.root().join("Cargo.lock"), p.root().join("Cargo.lock")));
+
+ // Finally, build the first project again (with our newer Cargo.lock) which
+ // should force an update of the old registry, download the new crate, and
+ // then build everything again.
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr(&format!("\
+[UPDATING] [..]
+[DOWNLOADING] a v0.1.1 (registry `file://[..]`)
+[COMPILING] a v0.1.1
+[COMPILING] foo v0.5.0 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] secs
+",
+ dir = p.url())));
+
+}
+
+#[test]
+fn fetch_downloads() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+ authors = []
+
+ [dependencies]
+ a = "0.1.0"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ Package::new("a", "0.1.0").publish();
+
+ assert_that(p.cargo("fetch"),
+ execs().with_status(0)
+ .with_stderr("\
+[UPDATING] registry `[..]`
+[DOWNLOADING] a v0.1.0 (registry [..])
+"));
+}
+
+#[test]
+fn update_transitive_dependency() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+ authors = []
+
+ [dependencies]
+ a = "0.1.0"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ Package::new("a", "0.1.0").dep("b", "*").publish();
+ Package::new("b", "0.1.0").publish();
+
+ assert_that(p.cargo("fetch"),
+ execs().with_status(0));
+
+ Package::new("b", "0.1.1").publish();
+
+ assert_that(p.cargo("update").arg("-pb"),
+ execs().with_status(0)
+ .with_stderr("\
+[UPDATING] registry `[..]`
+[UPDATING] b v0.1.0 -> v0.1.1
+"));
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0)
+ .with_stderr("\
+[DOWNLOADING] b v0.1.1 (registry `file://[..]`)
+[COMPILING] b v0.1.1
+[COMPILING] a v0.1.0
+[COMPILING] foo v0.5.0 ([..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] secs
+"));
+}
+
+#[test]
+fn update_backtracking_ok() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+ authors = []
+
+ [dependencies]
+ webdriver = "0.1"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ Package::new("webdriver", "0.1.0").dep("hyper", "0.6").publish();
+ Package::new("hyper", "0.6.5").dep("openssl", "0.1")
+ .dep("cookie", "0.1")
+ .publish();
+ Package::new("cookie", "0.1.0").dep("openssl", "0.1").publish();
+ Package::new("openssl", "0.1.0").publish();
+
+ assert_that(p.cargo("generate-lockfile"),
+ execs().with_status(0));
+
+ Package::new("openssl", "0.1.1").publish();
+ Package::new("hyper", "0.6.6").dep("openssl", "0.1.1")
+ .dep("cookie", "0.1.0")
+ .publish();
+
+ assert_that(p.cargo("update").arg("-p").arg("hyper"),
+ execs().with_status(0)
+ .with_stderr("\
+[UPDATING] registry `[..]`
+"));
+}
+
+#[test]
+fn update_multiple_packages() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+ authors = []
+
+ [dependencies]
+ a = "*"
+ b = "*"
+ c = "*"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ Package::new("a", "0.1.0").publish();
+ Package::new("b", "0.1.0").publish();
+ Package::new("c", "0.1.0").publish();
+
+ assert_that(p.cargo("fetch"),
+ execs().with_status(0));
+
+ Package::new("a", "0.1.1").publish();
+ Package::new("b", "0.1.1").publish();
+ Package::new("c", "0.1.1").publish();
+
+ assert_that(p.cargo("update").arg("-pa").arg("-pb"),
+ execs().with_status(0)
+ .with_stderr("\
+[UPDATING] registry `[..]`
+[UPDATING] a v0.1.0 -> v0.1.1
+[UPDATING] b v0.1.0 -> v0.1.1
+"));
+
+ assert_that(p.cargo("update").arg("-pb").arg("-pc"),
+ execs().with_status(0)
+ .with_stderr("\
+[UPDATING] registry `[..]`
+[UPDATING] c v0.1.0 -> v0.1.1
+"));
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0)
+ .with_stderr_contains("\
+[DOWNLOADING] a v0.1.1 (registry `file://[..]`)")
+ .with_stderr_contains("\
+[DOWNLOADING] b v0.1.1 (registry `file://[..]`)")
+ .with_stderr_contains("\
+[DOWNLOADING] c v0.1.1 (registry `file://[..]`)")
+ .with_stderr_contains("\
+[COMPILING] a v0.1.1")
+ .with_stderr_contains("\
+[COMPILING] b v0.1.1")
+ .with_stderr_contains("\
+[COMPILING] c v0.1.1")
+ .with_stderr_contains("\
+[COMPILING] foo v0.5.0 ([..])"));
+}
+
+#[test]
+fn bundled_crate_in_registry() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+ authors = []
+
+ [dependencies]
+ bar = "0.1"
+ baz = "0.1"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ Package::new("bar", "0.1.0").publish();
+ Package::new("baz", "0.1.0")
+ .dep("bar", "0.1.0")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "baz"
+ version = "0.1.0"
+ authors = []
+
+ [dependencies]
+ bar = { path = "bar", version = "0.1.0" }
+ "#)
+ .file("src/lib.rs", "")
+ .file("bar/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("bar/src/lib.rs", "")
+ .publish();
+
+ assert_that(p.cargo("run"), execs().with_status(0));
+}
+
+#[test]
+fn update_same_prefix_oh_my_how_was_this_a_bug() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "ugh"
+ version = "0.5.0"
+ authors = []
+
+ [dependencies]
+ foo = "0.1"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ Package::new("foobar", "0.2.0").publish();
+ Package::new("foo", "0.1.0")
+ .dep("foobar", "0.2.0")
+ .publish();
+
+ assert_that(p.cargo("generate-lockfile"), execs().with_status(0));
+ assert_that(p.cargo("update").arg("-pfoobar").arg("--precise=0.2.0"),
+ execs().with_status(0));
+}
+
+#[test]
+fn use_semver() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.5.0"
+ authors = []
+
+ [dependencies]
+ foo = "1.2.3-alpha.0"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ Package::new("foo", "1.2.3-alpha.0").publish();
+
+ assert_that(p.cargo("build"), execs().with_status(0));
+}
+
+#[test]
+fn only_download_relevant() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.5.0"
+ authors = []
+
+ [target.foo.dependencies]
+ foo = "*"
+ [dev-dependencies]
+ bar = "*"
+ [dependencies]
+ baz = "*"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ Package::new("foo", "0.1.0").publish();
+ Package::new("bar", "0.1.0").publish();
+ Package::new("baz", "0.1.0").publish();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0).with_stderr("\
+[UPDATING] registry `[..]`
+[DOWNLOADING] baz v0.1.0 ([..])
+[COMPILING] baz v0.1.0
+[COMPILING] bar v0.5.0 ([..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] secs
+"));
+}
+
+#[test]
+fn resolve_and_backtracking() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.5.0"
+ authors = []
+
+ [dependencies]
+ foo = "*"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ Package::new("foo", "0.1.1")
+ .feature_dep("bar", "0.1", &["a", "b"])
+ .publish();
+ Package::new("foo", "0.1.0").publish();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0));
+}
+
+#[test]
+fn upstream_warnings_on_extra_verbose() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.5.0"
+ authors = []
+
+ [dependencies]
+ foo = "*"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ Package::new("foo", "0.1.0")
+ .file("src/lib.rs", "fn unused() {}")
+ .publish();
+
+ assert_that(p.cargo("build").arg("-vv"),
+ execs().with_status(0).with_stderr_contains("\
+[..]warning: function is never used[..]
+"));
+}
+
+#[test]
+fn disallow_network() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.5.0"
+ authors = []
+
+ [dependencies]
+ foo = "*"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("build").arg("--frozen"),
+ execs().with_status(101).with_stderr("\
+error: failed to load source for a dependency on `foo`
+
+Caused by:
+ Unable to update registry [..]
+
+Caused by:
+ attempting to make an HTTP request, but --frozen was specified
+"));
+}
+
+#[test]
+fn add_dep_dont_update_registry() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.5.0"
+ authors = []
+
+ [dependencies]
+ baz = { path = "baz" }
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .file("baz/Cargo.toml", r#"
+ [project]
+ name = "baz"
+ version = "0.5.0"
+ authors = []
+
+ [dependencies]
+ remote = "0.3"
+ "#)
+ .file("baz/src/lib.rs", "")
+ .build();
+
+ Package::new("remote", "0.3.4").publish();
+
+ assert_that(p.cargo("build"), execs().with_status(0));
+
+ t!(t!(File::create(p.root().join("Cargo.toml"))).write_all(br#"
+ [project]
+ name = "bar"
+ version = "0.5.0"
+ authors = []
+
+ [dependencies]
+ baz = { path = "baz" }
+ remote = "0.3"
+ "#));
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0)
+ .with_stderr("\
+[COMPILING] bar v0.5.0 ([..])
+[FINISHED] [..]
+"));
+}
+
+#[test]
+fn bump_version_dont_update_registry() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.5.0"
+ authors = []
+
+ [dependencies]
+ baz = { path = "baz" }
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .file("baz/Cargo.toml", r#"
+ [project]
+ name = "baz"
+ version = "0.5.0"
+ authors = []
+
+ [dependencies]
+ remote = "0.3"
+ "#)
+ .file("baz/src/lib.rs", "")
+ .build();
+
+ Package::new("remote", "0.3.4").publish();
+
+ assert_that(p.cargo("build"), execs().with_status(0));
+
+ t!(t!(File::create(p.root().join("Cargo.toml"))).write_all(br#"
+ [project]
+ name = "bar"
+ version = "0.6.0"
+ authors = []
+
+ [dependencies]
+ baz = { path = "baz" }
+ "#));
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0)
+ .with_stderr("\
+[COMPILING] bar v0.6.0 ([..])
+[FINISHED] [..]
+"));
+}
+
+#[test]
+fn old_version_req() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.5.0"
+ authors = []
+
+ [dependencies]
+ remote = "0.2*"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ Package::new("remote", "0.2.0").publish();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0)
+ .with_stderr("\
+warning: parsed version requirement `0.2*` is no longer valid
+
+Previous versions of Cargo accepted this malformed requirement,
+but it is being deprecated. This was found when parsing the manifest
+of bar 0.5.0, and the correct version requirement is `0.2.*`.
+
+This will soon become a hard error, so it's either recommended to
+update to a fixed version or contact the upstream maintainer about
+this warning.
+
+warning: parsed version requirement `0.2*` is no longer valid
+
+Previous versions of Cargo accepted this malformed requirement,
+but it is being deprecated. This was found when parsing the manifest
+of bar 0.5.0, and the correct version requirement is `0.2.*`.
+
+This will soon become a hard error, so it's either recommended to
+update to a fixed version or contact the upstream maintainer about
+this warning.
+
+[UPDATING] [..]
+[DOWNLOADING] [..]
+[COMPILING] [..]
+[COMPILING] [..]
+[FINISHED] [..]
+"));
+}
+
+#[test]
+fn old_version_req_upstream() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.5.0"
+ authors = []
+
+ [dependencies]
+ remote = "0.3"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ Package::new("remote", "0.3.0")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "remote"
+ version = "0.3.0"
+ authors = []
+
+ [dependencies]
+ bar = "0.2*"
+ "#)
+ .file("src/lib.rs", "")
+ .publish();
+ Package::new("bar", "0.2.0").publish();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0)
+ .with_stderr("\
+[UPDATING] [..]
+[DOWNLOADING] [..]
+warning: parsed version requirement `0.2*` is no longer valid
+
+Previous versions of Cargo accepted this malformed requirement,
+but it is being deprecated. This was found when parsing the manifest
+of remote 0.3.0, and the correct version requirement is `0.2.*`.
+
+This will soon become a hard error, so it's either recommended to
+update to a fixed version or contact the upstream maintainer about
+this warning.
+
+[COMPILING] [..]
+[COMPILING] [..]
+[FINISHED] [..]
+"));
+}
+
+#[test]
+fn toml_lies_but_index_is_truth() {
+ Package::new("foo", "0.2.0").publish();
+ Package::new("bar", "0.3.0")
+ .dep("foo", "0.2.0")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.3.0"
+ authors = []
+
+ [dependencies]
+ foo = "0.1.0"
+ "#)
+ .file("src/lib.rs", "extern crate foo;")
+ .publish();
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.5.0"
+ authors = []
+
+ [dependencies]
+ bar = "0.3"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(0));
+}
+
+#[test]
+fn vv_prints_warnings() {
+ Package::new("foo", "0.2.0")
+ .file("src/lib.rs", r#"
+ #![deny(warnings)]
+
+ fn foo() {} // unused function
+ "#)
+ .publish();
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "fo"
+ version = "0.5.0"
+ authors = []
+
+ [dependencies]
+ foo = "0.2"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("build").arg("-vv"),
+ execs().with_status(0));
+}
+
+#[test]
+fn bad_and_or_malicious_packages_rejected() {
+ Package::new("foo", "0.2.0")
+ .extra_file("foo-0.1.0/src/lib.rs", "")
+ .publish();
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "fo"
+ version = "0.5.0"
+ authors = []
+
+ [dependencies]
+ foo = "0.2"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("build").arg("-vv"),
+ execs().with_status(101)
+ .with_stderr("\
+[UPDATING] [..]
+[DOWNLOADING] [..]
+error: unable to get packages from source
+
+Caused by:
+ failed to download [..]
+
+Caused by:
+ failed to unpack [..]
+
+Caused by:
+ [..] contains a file at \"foo-0.1.0/src/lib.rs\" which isn't under \"foo-0.2.0\"
+"));
+}
--- /dev/null
+use cargotest::is_nightly;
+use cargotest::install::{cargo_home, has_installed_exe};
+use cargotest::support::{project, execs};
+use hamcrest::{assert_that, existing_file, not};
+
+#[test]
+fn build_bin_default_features() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [features]
+ default = ["a"]
+ a = []
+
+ [[bin]]
+ name = "foo"
+ required-features = ["a"]
+ "#)
+ .file("src/main.rs", r#"
+ extern crate foo;
+
+ #[cfg(feature = "a")]
+ fn test() {
+ foo::foo();
+ }
+
+ fn main() {}
+ "#)
+ .file("src/lib.rs", r#"
+ #[cfg(feature = "a")]
+ pub fn foo() {}
+ "#)
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0));
+ assert_that(&p.bin("foo"), existing_file());
+
+ assert_that(p.cargo("build").arg("--no-default-features"),
+ execs().with_status(0));
+
+ assert_that(p.cargo("build").arg("--bin=foo"),
+ execs().with_status(0));
+ assert_that(&p.bin("foo"), existing_file());
+
+ assert_that(p.cargo("build").arg("--bin=foo").arg("--no-default-features"),
+ execs().with_status(101).with_stderr("\
+error: target `foo` requires the features: `a`
+Consider enabling them by passing e.g. `--features=\"a\"`
+"));
+}
+
+#[test]
+fn build_bin_arg_features() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [features]
+ a = []
+
+ [[bin]]
+ name = "foo"
+ required-features = ["a"]
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("build").arg("--features").arg("a"),
+ execs().with_status(0));
+ assert_that(&p.bin("foo"), existing_file());
+}
+
+#[test]
+fn build_bin_multiple_required_features() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [features]
+ default = ["a", "b"]
+ a = []
+ b = ["a"]
+ c = []
+
+ [[bin]]
+ name = "foo_1"
+ path = "src/foo_1.rs"
+ required-features = ["b", "c"]
+
+ [[bin]]
+ name = "foo_2"
+ path = "src/foo_2.rs"
+ required-features = ["a"]
+ "#)
+ .file("src/foo_1.rs", "fn main() {}")
+ .file("src/foo_2.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0));
+
+ assert_that(&p.bin("foo_1"), not(existing_file()));
+ assert_that(&p.bin("foo_2"), existing_file());
+
+ assert_that(p.cargo("build").arg("--features").arg("c"),
+ execs().with_status(0));
+
+ assert_that(&p.bin("foo_1"), existing_file());
+ assert_that(&p.bin("foo_2"), existing_file());
+
+ assert_that(p.cargo("build").arg("--no-default-features"),
+ execs().with_status(0));
+}
+
+#[test]
+fn build_example_default_features() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [features]
+ default = ["a"]
+ a = []
+
+ [[example]]
+ name = "foo"
+ required-features = ["a"]
+ "#)
+ .file("examples/foo.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("build").arg("--example=foo"),
+ execs().with_status(0));
+ assert_that(&p.bin("examples/foo"), existing_file());
+
+ assert_that(p.cargo("build").arg("--example=foo").arg("--no-default-features"),
+ execs().with_status(101).with_stderr("\
+error: target `foo` requires the features: `a`
+Consider enabling them by passing e.g. `--features=\"a\"`
+"));
+}
+
+#[test]
+fn build_example_arg_features() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [features]
+ a = []
+
+ [[example]]
+ name = "foo"
+ required-features = ["a"]
+ "#)
+ .file("examples/foo.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("build").arg("--example=foo").arg("--features").arg("a"),
+ execs().with_status(0));
+ assert_that(&p.bin("examples/foo"), existing_file());
+}
+
+#[test]
+fn build_example_multiple_required_features() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [features]
+ default = ["a", "b"]
+ a = []
+ b = ["a"]
+ c = []
+
+ [[example]]
+ name = "foo_1"
+ required-features = ["b", "c"]
+
+ [[example]]
+ name = "foo_2"
+ required-features = ["a"]
+ "#)
+ .file("examples/foo_1.rs", "fn main() {}")
+ .file("examples/foo_2.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("build").arg("--example=foo_1"),
+ execs().with_status(101).with_stderr("\
+error: target `foo_1` requires the features: `b`, `c`
+Consider enabling them by passing e.g. `--features=\"b c\"`
+"));
+ assert_that(p.cargo("build").arg("--example=foo_2"),
+ execs().with_status(0));
+
+ assert_that(&p.bin("examples/foo_1"), not(existing_file()));
+ assert_that(&p.bin("examples/foo_2"), existing_file());
+
+ assert_that(p.cargo("build").arg("--example=foo_1")
+ .arg("--features").arg("c"),
+ execs().with_status(0));
+ assert_that(p.cargo("build").arg("--example=foo_2")
+ .arg("--features").arg("c"),
+ execs().with_status(0));
+
+ assert_that(&p.bin("examples/foo_1"), existing_file());
+ assert_that(&p.bin("examples/foo_2"), existing_file());
+
+ assert_that(p.cargo("build").arg("--example=foo_1")
+ .arg("--no-default-features"),
+ execs().with_status(101).with_stderr("\
+error: target `foo_1` requires the features: `b`, `c`
+Consider enabling them by passing e.g. `--features=\"b c\"`
+"));
+ assert_that(p.cargo("build").arg("--example=foo_2")
+ .arg("--no-default-features"),
+ execs().with_status(101).with_stderr("\
+error: target `foo_2` requires the features: `a`
+Consider enabling them by passing e.g. `--features=\"a\"`
+"));
+}
+
+#[test]
+fn test_default_features() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [features]
+ default = ["a"]
+ a = []
+
+ [[test]]
+ name = "foo"
+ required-features = ["a"]
+ "#)
+ .file("tests/foo.rs", "#[test]\nfn test() {}")
+ .build();
+
+ assert_that(p.cargo("test"),
+ execs().with_status(0).with_stderr(format!("\
+[COMPILING] foo v0.0.1 ({})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] target[/]debug[/]deps[/]foo-[..][EXE]", p.url()))
+ .with_stdout_contains("test test ... ok"));
+
+ assert_that(p.cargo("test").arg("--no-default-features"),
+ execs().with_status(0).with_stderr(format!("\
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]"))
+ .with_stdout(""));
+
+ assert_that(p.cargo("test").arg("--test=foo"),
+ execs().with_status(0).with_stderr(format!("\
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] target[/]debug[/]deps[/]foo-[..][EXE]"))
+ .with_stdout_contains("test test ... ok"));
+
+ assert_that(p.cargo("test").arg("--test=foo").arg("--no-default-features"),
+ execs().with_status(101).with_stderr("\
+error: target `foo` requires the features: `a`
+Consider enabling them by passing e.g. `--features=\"a\"`
+"));
+}
+
+#[test]
+fn test_arg_features() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [features]
+ a = []
+
+ [[test]]
+ name = "foo"
+ required-features = ["a"]
+ "#)
+ .file("tests/foo.rs", "#[test]\nfn test() {}")
+ .build();
+
+ assert_that(p.cargo("test").arg("--features").arg("a"),
+ execs().with_status(0).with_stderr(format!("\
+[COMPILING] foo v0.0.1 ({})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] target[/]debug[/]deps[/]foo-[..][EXE]", p.url()))
+ .with_stdout_contains("test test ... ok"));
+}
+
+#[test]
+fn test_multiple_required_features() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [features]
+ default = ["a", "b"]
+ a = []
+ b = ["a"]
+ c = []
+
+ [[test]]
+ name = "foo_1"
+ required-features = ["b", "c"]
+
+ [[test]]
+ name = "foo_2"
+ required-features = ["a"]
+ "#)
+ .file("tests/foo_1.rs", "#[test]\nfn test() {}")
+ .file("tests/foo_2.rs", "#[test]\nfn test() {}")
+ .build();
+
+ assert_that(p.cargo("test"),
+ execs().with_status(0).with_stderr(format!("\
+[COMPILING] foo v0.0.1 ({})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] target[/]debug[/]deps[/]foo_2-[..][EXE]", p.url()))
+ .with_stdout_contains("test test ... ok"));
+
+ assert_that(p.cargo("test").arg("--features").arg("c"),
+ execs().with_status(0).with_stderr(format!("\
+[COMPILING] foo v0.0.1 ({})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] target[/]debug[/]deps[/]foo_1-[..][EXE]
+[RUNNING] target[/]debug[/]deps[/]foo_2-[..][EXE]", p.url()))
+ .with_stdout_contains_n("test test ... ok", 2));
+
+ assert_that(p.cargo("test").arg("--no-default-features"),
+ execs().with_status(0).with_stderr(format!("\
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]"))
+ .with_stdout(""));
+}
+
+#[test]
+fn bench_default_features() {
+ if !is_nightly() {
+ return;
+ }
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [features]
+ default = ["a"]
+ a = []
+
+ [[bench]]
+ name = "foo"
+ required-features = ["a"]
+ "#)
+ .file("benches/foo.rs", r#"
+ #![feature(test)]
+ extern crate test;
+
+ #[bench]
+ fn bench(_: &mut test::Bencher) {
+ }"#)
+ .build();
+
+ assert_that(p.cargo("bench"),
+ execs().with_status(0).with_stderr(format!("\
+[COMPILING] foo v0.0.1 ({})
+[FINISHED] release [optimized] target(s) in [..]
+[RUNNING] target[/]release[/]deps[/]foo-[..][EXE]", p.url()))
+ .with_stdout_contains("test bench ... bench: [..]"));
+
+ assert_that(p.cargo("bench").arg("--no-default-features"),
+ execs().with_status(0).with_stderr(format!("\
+[FINISHED] release [optimized] target(s) in [..]"))
+ .with_stdout(""));
+
+ assert_that(p.cargo("bench").arg("--bench=foo"),
+ execs().with_status(0).with_stderr(format!("\
+[FINISHED] release [optimized] target(s) in [..]
+[RUNNING] target[/]release[/]deps[/]foo-[..][EXE]"))
+ .with_stdout_contains("test bench ... bench: [..]"));
+
+ assert_that(p.cargo("bench").arg("--bench=foo").arg("--no-default-features"),
+ execs().with_status(101).with_stderr("\
+error: target `foo` requires the features: `a`
+Consider enabling them by passing e.g. `--features=\"a\"`
+"));
+}
+
+#[test]
+fn bench_arg_features() {
+ if !is_nightly() {
+ return;
+ }
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [features]
+ a = []
+
+ [[bench]]
+ name = "foo"
+ required-features = ["a"]
+ "#)
+ .file("benches/foo.rs", r#"
+ #![feature(test)]
+ extern crate test;
+
+ #[bench]
+ fn bench(_: &mut test::Bencher) {
+ }"#)
+ .build();
+
+ assert_that(p.cargo("bench").arg("--features").arg("a"),
+ execs().with_status(0).with_stderr(format!("\
+[COMPILING] foo v0.0.1 ({})
+[FINISHED] release [optimized] target(s) in [..]
+[RUNNING] target[/]release[/]deps[/]foo-[..][EXE]", p.url()))
+ .with_stdout_contains("test bench ... bench: [..]"));
+}
+
+#[test]
+fn bench_multiple_required_features() {
+ if !is_nightly() {
+ return;
+ }
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [features]
+ default = ["a", "b"]
+ a = []
+ b = ["a"]
+ c = []
+
+ [[bench]]
+ name = "foo_1"
+ required-features = ["b", "c"]
+
+ [[bench]]
+ name = "foo_2"
+ required-features = ["a"]
+ "#)
+ .file("benches/foo_1.rs", r#"
+ #![feature(test)]
+ extern crate test;
+
+ #[bench]
+ fn bench(_: &mut test::Bencher) {
+ }"#)
+ .file("benches/foo_2.rs", r#"
+ #![feature(test)]
+ extern crate test;
+
+ #[bench]
+ fn bench(_: &mut test::Bencher) {
+ }"#)
+ .build();
+
+ assert_that(p.cargo("bench"),
+ execs().with_status(0).with_stderr(format!("\
+[COMPILING] foo v0.0.1 ({})
+[FINISHED] release [optimized] target(s) in [..]
+[RUNNING] target[/]release[/]deps[/]foo_2-[..][EXE]", p.url()))
+ .with_stdout_contains("test bench ... bench: [..]"));
+
+ assert_that(p.cargo("bench").arg("--features").arg("c"),
+ execs().with_status(0).with_stderr(format!("\
+[COMPILING] foo v0.0.1 ({})
+[FINISHED] release [optimized] target(s) in [..]
+[RUNNING] target[/]release[/]deps[/]foo_1-[..][EXE]
+[RUNNING] target[/]release[/]deps[/]foo_2-[..][EXE]", p.url()))
+ .with_stdout_contains_n("test bench ... bench: [..]", 2));
+
+ assert_that(p.cargo("bench").arg("--no-default-features"),
+ execs().with_status(0).with_stderr(format!("\
+[FINISHED] release [optimized] target(s) in [..]"))
+ .with_stdout(""));
+}
+
+#[test]
+fn install_default_features() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [features]
+ default = ["a"]
+ a = []
+
+ [[bin]]
+ name = "foo"
+ required-features = ["a"]
+
+ [[example]]
+ name = "foo"
+ required-features = ["a"]
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .file("examples/foo.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("install"),
+ execs().with_status(0));
+ assert_that(cargo_home(), has_installed_exe("foo"));
+ assert_that(p.cargo("uninstall").arg("foo"),
+ execs().with_status(0));
+
+ assert_that(p.cargo("install").arg("--no-default-features"),
+ execs().with_status(101).with_stderr(format!("\
+[INSTALLING] foo v0.0.1 ([..])
+[FINISHED] release [optimized] target(s) in [..]
+[ERROR] no binaries are available for install using the selected features
+")));
+ assert_that(cargo_home(), not(has_installed_exe("foo")));
+
+ assert_that(p.cargo("install").arg("--bin=foo"),
+ execs().with_status(0));
+ assert_that(cargo_home(), has_installed_exe("foo"));
+ assert_that(p.cargo("uninstall").arg("foo"),
+ execs().with_status(0));
+
+ assert_that(p.cargo("install").arg("--bin=foo").arg("--no-default-features"),
+ execs().with_status(101).with_stderr(format!("\
+[INSTALLING] foo v0.0.1 ([..])
+[ERROR] failed to compile `foo v0.0.1 ([..])`, intermediate artifacts can be found at \
+ `[..]target`
+
+Caused by:
+ target `foo` requires the features: `a`
+Consider enabling them by passing e.g. `--features=\"a\"`
+")));
+ assert_that(cargo_home(), not(has_installed_exe("foo")));
+
+ assert_that(p.cargo("install").arg("--example=foo"),
+ execs().with_status(0));
+ assert_that(cargo_home(), has_installed_exe("foo"));
+ assert_that(p.cargo("uninstall").arg("foo"),
+ execs().with_status(0));
+
+ assert_that(p.cargo("install").arg("--example=foo").arg("--no-default-features"),
+ execs().with_status(101).with_stderr(format!("\
+[INSTALLING] foo v0.0.1 ([..])
+[ERROR] failed to compile `foo v0.0.1 ([..])`, intermediate artifacts can be found at \
+ `[..]target`
+
+Caused by:
+ target `foo` requires the features: `a`
+Consider enabling them by passing e.g. `--features=\"a\"`
+")));
+ assert_that(cargo_home(), not(has_installed_exe("foo")));
+}
+
+#[test]
+fn install_arg_features() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [features]
+ a = []
+
+ [[bin]]
+ name = "foo"
+ required-features = ["a"]
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("install").arg("--features").arg("a"),
+ execs().with_status(0));
+ assert_that(cargo_home(), has_installed_exe("foo"));
+ assert_that(p.cargo("uninstall").arg("foo"),
+ execs().with_status(0));
+}
+
+#[test]
+fn install_multiple_required_features() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [features]
+ default = ["a", "b"]
+ a = []
+ b = ["a"]
+ c = []
+
+ [[bin]]
+ name = "foo_1"
+ path = "src/foo_1.rs"
+ required-features = ["b", "c"]
+
+ [[bin]]
+ name = "foo_2"
+ path = "src/foo_2.rs"
+ required-features = ["a"]
+ "#)
+ .file("src/foo_1.rs", "fn main() {}")
+ .file("src/foo_2.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("install"),
+ execs().with_status(0));
+ assert_that(cargo_home(), not(has_installed_exe("foo_1")));
+ assert_that(cargo_home(), has_installed_exe("foo_2"));
+ assert_that(p.cargo("uninstall").arg("foo"),
+ execs().with_status(0));
+
+ assert_that(p.cargo("install").arg("--features").arg("c"),
+ execs().with_status(0));
+ assert_that(cargo_home(), has_installed_exe("foo_1"));
+ assert_that(cargo_home(), has_installed_exe("foo_2"));
+ assert_that(p.cargo("uninstall").arg("foo"),
+ execs().with_status(0));
+
+ assert_that(p.cargo("install").arg("--no-default-features"),
+ execs().with_status(101).with_stderr("\
+[INSTALLING] foo v0.0.1 ([..])
+[FINISHED] release [optimized] target(s) in [..]
+[ERROR] no binaries are available for install using the selected features
+"));
+ assert_that(cargo_home(), not(has_installed_exe("foo_1")));
+ assert_that(cargo_home(), not(has_installed_exe("foo_2")));
+}
+
+#[test]
+fn dep_feature_in_toml() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ bar = { path = "bar", features = ["a"] }
+
+ [[bin]]
+ name = "foo"
+ required-features = ["bar/a"]
+
+ [[example]]
+ name = "foo"
+ required-features = ["bar/a"]
+
+ [[test]]
+ name = "foo"
+ required-features = ["bar/a"]
+
+ [[bench]]
+ name = "foo"
+ required-features = ["bar/a"]
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .file("examples/foo.rs", "fn main() {}")
+ .file("tests/foo.rs", "#[test]\nfn test() {}")
+ .file("benches/foo.rs", r#"
+ #![feature(test)]
+ extern crate test;
+
+ #[bench]
+ fn bench(_: &mut test::Bencher) {
+ }"#)
+ .file("bar/Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+
+ [features]
+ a = []
+ "#)
+ .file("bar/src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0));
+
+ // bin
+ assert_that(p.cargo("build").arg("--bin=foo"),
+ execs().with_status(0));
+ assert_that(&p.bin("foo"), existing_file());
+
+ // example
+ assert_that(p.cargo("build").arg("--example=foo"),
+ execs().with_status(0));
+ assert_that(&p.bin("examples/foo"), existing_file());
+
+ // test
+ assert_that(p.cargo("test").arg("--test=foo"),
+ execs().with_status(0).with_stderr(format!("\
+[COMPILING] foo v0.0.1 ({})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] target[/]debug[/]deps[/]foo-[..][EXE]", p.url()))
+ .with_stdout_contains("test test ... ok"));
+
+ // bench
+ if is_nightly() {
+ assert_that(p.cargo("bench").arg("--bench=foo"),
+ execs().with_status(0).with_stderr(format!("\
+[COMPILING] bar v0.0.1 ({0}/bar)
+[COMPILING] foo v0.0.1 ({0})
+[FINISHED] release [optimized] target(s) in [..]
+[RUNNING] target[/]release[/]deps[/]foo-[..][EXE]", p.url()))
+ .with_stdout_contains("test bench ... bench: [..]"));
+ }
+
+ // install
+ assert_that(p.cargo("install"),
+ execs().with_status(0));
+ assert_that(cargo_home(), has_installed_exe("foo"));
+ assert_that(p.cargo("uninstall").arg("foo"),
+ execs().with_status(0));
+}
+
+#[test]
+fn dep_feature_in_cmd_line() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ bar = { path = "bar" }
+
+ [[bin]]
+ name = "foo"
+ required-features = ["bar/a"]
+
+ [[example]]
+ name = "foo"
+ required-features = ["bar/a"]
+
+ [[test]]
+ name = "foo"
+ required-features = ["bar/a"]
+
+ [[bench]]
+ name = "foo"
+ required-features = ["bar/a"]
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .file("examples/foo.rs", "fn main() {}")
+ .file("tests/foo.rs", "#[test]\nfn test() {}")
+ .file("benches/foo.rs", r#"
+ #![feature(test)]
+ extern crate test;
+
+ #[bench]
+ fn bench(_: &mut test::Bencher) {
+ }"#)
+ .file("bar/Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+
+ [features]
+ a = []
+ "#)
+ .file("bar/src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0));
+
+ // bin
+ assert_that(p.cargo("build").arg("--bin=foo"),
+ execs().with_status(101).with_stderr("\
+error: target `foo` requires the features: `bar/a`
+Consider enabling them by passing e.g. `--features=\"bar/a\"`
+"));
+
+ assert_that(p.cargo("build").arg("--bin=foo").arg("--features").arg("bar/a"),
+ execs().with_status(0));
+ assert_that(&p.bin("foo"), existing_file());
+
+ // example
+ assert_that(p.cargo("build").arg("--example=foo"),
+ execs().with_status(101).with_stderr("\
+error: target `foo` requires the features: `bar/a`
+Consider enabling them by passing e.g. `--features=\"bar/a\"`
+"));
+
+ assert_that(p.cargo("build").arg("--example=foo").arg("--features").arg("bar/a"),
+ execs().with_status(0));
+ assert_that(&p.bin("examples/foo"), existing_file());
+
+ // test
+ assert_that(p.cargo("test"),
+ execs().with_status(0).with_stderr(format!("\
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]"))
+ .with_stdout(""));
+
+ assert_that(p.cargo("test").arg("--test=foo").arg("--features").arg("bar/a"),
+ execs().with_status(0).with_stderr(format!("\
+[COMPILING] foo v0.0.1 ({})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] target[/]debug[/]deps[/]foo-[..][EXE]", p.url()))
+ .with_stdout_contains("test test ... ok"));
+
+ // bench
+ if is_nightly() {
+ assert_that(p.cargo("bench"),
+ execs().with_status(0).with_stderr(format!("\
+[FINISHED] release [optimized] target(s) in [..]"))
+ .with_stdout(""));
+
+ assert_that(p.cargo("bench").arg("--bench=foo").arg("--features").arg("bar/a"),
+ execs().with_status(0).with_stderr(format!("\
+[COMPILING] bar v0.0.1 ({0}/bar)
+[COMPILING] foo v0.0.1 ({0})
+[FINISHED] release [optimized] target(s) in [..]
+[RUNNING] target[/]release[/]deps[/]foo-[..][EXE]", p.url()))
+ .with_stdout_contains("test bench ... bench: [..]"));
+ }
+
+ // install
+ assert_that(p.cargo("install"),
+ execs().with_status(101).with_stderr(format!("\
+[INSTALLING] foo v0.0.1 ([..])
+[FINISHED] release [optimized] target(s) in [..]
+[ERROR] no binaries are available for install using the selected features
+")));
+ assert_that(cargo_home(), not(has_installed_exe("foo")));
+
+ assert_that(p.cargo("install").arg("--features").arg("bar/a"),
+ execs().with_status(0));
+ assert_that(cargo_home(), has_installed_exe("foo"));
+ assert_that(p.cargo("uninstall").arg("foo"),
+ execs().with_status(0));
+}
+
+#[test]
+fn test_skips_compiling_bin_with_missing_required_features() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [features]
+ a = []
+
+ [[bin]]
+ name = "bin_foo"
+ path = "src/bin/foo.rs"
+ required-features = ["a"]
+ "#)
+ .file("src/bin/foo.rs", "extern crate bar; fn main() {}")
+ .file("tests/foo.rs", "")
+ .file("benches/foo.rs", "")
+ .build();
+
+ assert_that(p.cargo("test"),
+ execs().with_status(0).with_stderr(format!("\
+[COMPILING] foo v0.0.1 ({})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] target[/]debug[/]deps[/]foo-[..][EXE]", p.url()))
+ .with_stdout_contains("running 0 tests"));
+
+ assert_that(p.cargo("test").arg("--features").arg("a").arg("-j").arg("1"),
+ execs().with_status(101).with_stderr_contains(format!("\
+[COMPILING] foo v0.0.1 ({})
+error[E0463]: can't find crate for `bar`", p.url())));
+
+ if is_nightly() {
+ assert_that(p.cargo("bench"),
+ execs().with_status(0).with_stderr(format!("\
+[COMPILING] foo v0.0.1 ({})
+[FINISHED] release [optimized] target(s) in [..]
+[RUNNING] target[/]release[/]deps[/]foo-[..][EXE]", p.url()))
+ .with_stdout_contains("running 0 tests"));
+
+ assert_that(p.cargo("bench").arg("--features").arg("a").arg("-j").arg("1"),
+ execs().with_status(101).with_stderr_contains(format!("\
+[COMPILING] foo v0.0.1 ({})
+error[E0463]: can't find crate for `bar`", p.url())));
+ }
+}
+
+#[test]
+fn run_default() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [features]
+ default = []
+ a = []
+
+ [[bin]]
+ name = "foo"
+ required-features = ["a"]
+ "#)
+ .file("src/lib.rs", "")
+ .file("src/main.rs", "extern crate foo; fn main() {}")
+ .build();
+
+ assert_that(p.cargo("run"),
+ execs().with_status(101).with_stderr("\
+error: target `foo` requires the features: `a`
+Consider enabling them by passing e.g. `--features=\"a\"`
+"));
+
+ assert_that(p.cargo("run").arg("--features").arg("a"),
+ execs().with_status(0));
+}
+
+#[test]
+fn run_default_multiple_required_features() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [features]
+ default = ["a"]
+ a = []
+ b = []
+
+ [[bin]]
+ name = "foo1"
+ path = "src/foo1.rs"
+ required-features = ["a"]
+
+ [[bin]]
+ name = "foo2"
+ path = "src/foo2.rs"
+ required-features = ["b"]
+ "#)
+ .file("src/lib.rs", "")
+ .file("src/foo1.rs", "extern crate foo; fn main() {}")
+ .file("src/foo2.rs", "extern crate foo; fn main() {}")
+ .build();
+
+ assert_that(p.cargo("run"),
+ execs().with_status(101).with_stderr("\
+error: `cargo run` requires that a project only have one executable; \
+use the `--bin` option to specify which one to run\navailable binaries: foo1, foo2"));
+}
--- /dev/null
+#![deny(warnings)]
+
+use std::collections::BTreeMap;
+
+use hamcrest::{assert_that, equal_to, contains, not};
+
+use cargo::core::source::{SourceId, GitReference};
+use cargo::core::dependency::Kind::{self, Development};
+use cargo::core::{Dependency, PackageId, Summary, Registry};
+use cargo::util::{CargoResult, ToUrl};
+use cargo::core::resolver::{self, Method};
+
+fn resolve(pkg: &PackageId, deps: Vec<Dependency>, registry: &[Summary])
+ -> CargoResult<Vec<PackageId>>
+{
+ struct MyRegistry<'a>(&'a [Summary]);
+ impl<'a> Registry for MyRegistry<'a> {
+ fn query(&mut self,
+ dep: &Dependency,
+ f: &mut FnMut(Summary)) -> CargoResult<()> {
+ for summary in self.0.iter() {
+ if dep.matches(summary) {
+ f(summary.clone());
+ }
+ }
+ Ok(())
+ }
+ fn supports_checksums(&self) -> bool { false }
+ fn requires_precise(&self) -> bool { false }
+ }
+ let mut registry = MyRegistry(registry);
+ let summary = Summary::new(pkg.clone(), deps, BTreeMap::new()).unwrap();
+ let method = Method::Everything;
+ let resolve = resolver::resolve(&[(summary, method)], &[], &mut registry, None, false)?;
+ let res = resolve.iter().cloned().collect();
+ Ok(res)
+}
+
+trait ToDep {
+ fn to_dep(self) -> Dependency;
+}
+
+impl ToDep for &'static str {
+ fn to_dep(self) -> Dependency {
+ let url = "http://example.com".to_url().unwrap();
+ let source_id = SourceId::for_registry(&url).unwrap();
+ Dependency::parse_no_deprecated(self, Some("1.0.0"), &source_id).unwrap()
+ }
+}
+
+impl ToDep for Dependency {
+ fn to_dep(self) -> Dependency {
+ self
+ }
+}
+
+trait ToPkgId {
+ fn to_pkgid(&self) -> PackageId;
+}
+
+impl ToPkgId for &'static str {
+ fn to_pkgid(&self) -> PackageId {
+ PackageId::new(*self, "1.0.0", ®istry_loc()).unwrap()
+ }
+}
+
+impl ToPkgId for (&'static str, &'static str) {
+ fn to_pkgid(&self) -> PackageId {
+ let (name, vers) = *self;
+ PackageId::new(name, vers, ®istry_loc()).unwrap()
+ }
+}
+
+impl ToPkgId for (&'static str, String) {
+ fn to_pkgid(&self) -> PackageId {
+ let (name, ref vers) = *self;
+ PackageId::new(name, vers, ®istry_loc()).unwrap()
+ }
+}
+
+macro_rules! pkg {
+ ($pkgid:expr => [$($deps:expr),+]) => ({
+ let d: Vec<Dependency> = vec![$($deps.to_dep()),+];
+
+ Summary::new($pkgid.to_pkgid(), d, BTreeMap::new()).unwrap()
+ });
+
+ ($pkgid:expr) => (
+ Summary::new($pkgid.to_pkgid(), Vec::new(), BTreeMap::new()).unwrap()
+ )
+}
+
+fn registry_loc() -> SourceId {
+ let remote = "http://example.com".to_url().unwrap();
+ SourceId::for_registry(&remote).unwrap()
+}
+
+fn pkg(name: &str) -> Summary {
+ Summary::new(pkg_id(name), Vec::new(), BTreeMap::new()).unwrap()
+}
+
+fn pkg_id(name: &str) -> PackageId {
+ PackageId::new(name, "1.0.0", ®istry_loc()).unwrap()
+}
+
+fn pkg_id_loc(name: &str, loc: &str) -> PackageId {
+ let remote = loc.to_url();
+ let master = GitReference::Branch("master".to_string());
+ let source_id = SourceId::for_git(&remote.unwrap(), master).unwrap();
+
+ PackageId::new(name, "1.0.0", &source_id).unwrap()
+}
+
+fn pkg_loc(name: &str, loc: &str) -> Summary {
+ Summary::new(pkg_id_loc(name, loc), Vec::new(), BTreeMap::new()).unwrap()
+}
+
+fn dep(name: &str) -> Dependency { dep_req(name, "1.0.0") }
+fn dep_req(name: &str, req: &str) -> Dependency {
+ let url = "http://example.com".to_url().unwrap();
+ let source_id = SourceId::for_registry(&url).unwrap();
+ Dependency::parse_no_deprecated(name, Some(req), &source_id).unwrap()
+}
+
+fn dep_loc(name: &str, location: &str) -> Dependency {
+ let url = location.to_url().unwrap();
+ let master = GitReference::Branch("master".to_string());
+ let source_id = SourceId::for_git(&url, master).unwrap();
+ Dependency::parse_no_deprecated(name, Some("1.0.0"), &source_id).unwrap()
+}
+fn dep_kind(name: &str, kind: Kind) -> Dependency {
+ dep(name).set_kind(kind).clone()
+}
+
+fn registry(pkgs: Vec<Summary>) -> Vec<Summary> {
+ pkgs
+}
+
+fn names<P: ToPkgId>(names: &[P]) -> Vec<PackageId> {
+ names.iter().map(|name| name.to_pkgid()).collect()
+}
+
+fn loc_names(names: &[(&'static str, &'static str)]) -> Vec<PackageId> {
+ names.iter()
+ .map(|&(name, loc)| pkg_id_loc(name, loc)).collect()
+}
+
+#[test]
+fn test_resolving_empty_dependency_list() {
+ let res = resolve(&pkg_id("root"), Vec::new(),
+ ®istry(vec![])).unwrap();
+
+ assert_that(&res, equal_to(&names(&["root"])));
+}
+
+#[test]
+fn test_resolving_only_package() {
+ let reg = registry(vec![pkg("foo")]);
+ let res = resolve(&pkg_id("root"), vec![dep("foo")], ®);
+
+ assert_that(&res.unwrap(), contains(names(&["root", "foo"])).exactly());
+}
+
+#[test]
+fn test_resolving_one_dep() {
+ let reg = registry(vec![pkg("foo"), pkg("bar")]);
+ let res = resolve(&pkg_id("root"), vec![dep("foo")], ®);
+
+ assert_that(&res.unwrap(), contains(names(&["root", "foo"])).exactly());
+}
+
+#[test]
+fn test_resolving_multiple_deps() {
+ let reg = registry(vec![pkg!("foo"), pkg!("bar"), pkg!("baz")]);
+ let res = resolve(&pkg_id("root"), vec![dep("foo"), dep("baz")],
+ ®).unwrap();
+
+ assert_that(&res, contains(names(&["root", "foo", "baz"])).exactly());
+}
+
+#[test]
+fn test_resolving_transitive_deps() {
+ let reg = registry(vec![pkg!("foo"), pkg!("bar" => ["foo"])]);
+ let res = resolve(&pkg_id("root"), vec![dep("bar")], ®).unwrap();
+
+ assert_that(&res, contains(names(&["root", "foo", "bar"])));
+}
+
+#[test]
+fn test_resolving_common_transitive_deps() {
+ let reg = registry(vec![pkg!("foo" => ["bar"]), pkg!("bar")]);
+ let res = resolve(&pkg_id("root"), vec![dep("foo"), dep("bar")],
+ ®).unwrap();
+
+ assert_that(&res, contains(names(&["root", "foo", "bar"])));
+}
+
+#[test]
+fn test_resolving_with_same_name() {
+ let list = vec![pkg_loc("foo", "http://first.example.com"),
+ pkg_loc("bar", "http://second.example.com")];
+
+ let reg = registry(list);
+ let res = resolve(&pkg_id("root"),
+ vec![dep_loc("foo", "http://first.example.com"),
+ dep_loc("bar", "http://second.example.com")],
+ ®);
+
+ let mut names = loc_names(&[("foo", "http://first.example.com"),
+ ("bar", "http://second.example.com")]);
+
+ names.push(pkg_id("root"));
+
+ assert_that(&res.unwrap(), contains(names).exactly());
+}
+
+#[test]
+fn test_resolving_with_dev_deps() {
+ let reg = registry(vec![
+ pkg!("foo" => ["bar", dep_kind("baz", Development)]),
+ pkg!("baz" => ["bat", dep_kind("bam", Development)]),
+ pkg!("bar"),
+ pkg!("bat")
+ ]);
+
+ let res = resolve(&pkg_id("root"),
+ vec![dep("foo"), dep_kind("baz", Development)],
+ ®).unwrap();
+
+ assert_that(&res, contains(names(&["root", "foo", "bar", "baz"])));
+}
+
+#[test]
+fn resolving_with_many_versions() {
+ let reg = registry(vec![
+ pkg!(("foo", "1.0.1")),
+ pkg!(("foo", "1.0.2")),
+ ]);
+
+ let res = resolve(&pkg_id("root"), vec![dep("foo")], ®).unwrap();
+
+ assert_that(&res, contains(names(&[("root", "1.0.0"),
+ ("foo", "1.0.2")])));
+}
+
+#[test]
+fn resolving_with_specific_version() {
+ let reg = registry(vec![
+ pkg!(("foo", "1.0.1")),
+ pkg!(("foo", "1.0.2")),
+ ]);
+
+ let res = resolve(&pkg_id("root"), vec![dep_req("foo", "=1.0.1")],
+ ®).unwrap();
+
+ assert_that(&res, contains(names(&[("root", "1.0.0"),
+ ("foo", "1.0.1")])));
+}
+
+#[test]
+fn test_resolving_maximum_version_with_transitive_deps() {
+ let reg = registry(vec![
+ pkg!(("util", "1.2.2")),
+ pkg!(("util", "1.0.0")),
+ pkg!(("util", "1.1.1")),
+ pkg!("foo" => [dep_req("util", "1.0.0")]),
+ pkg!("bar" => [dep_req("util", ">=1.0.1")]),
+ ]);
+
+ let res = resolve(&pkg_id("root"), vec![dep_req("foo", "1.0.0"), dep_req("bar", "1.0.0")],
+ ®).unwrap();
+
+ assert_that(&res, contains(names(&[("root", "1.0.0"),
+ ("foo", "1.0.0"),
+ ("bar", "1.0.0"),
+ ("util", "1.2.2")])));
+ assert_that(&res, not(contains(names(&[("util", "1.0.1")]))));
+ assert_that(&res, not(contains(names(&[("util", "1.1.1")]))));
+}
+
+#[test]
+fn resolving_incompat_versions() {
+ let reg = registry(vec![
+ pkg!(("foo", "1.0.1")),
+ pkg!(("foo", "1.0.2")),
+ pkg!("bar" => [dep_req("foo", "=1.0.2")]),
+ ]);
+
+ assert!(resolve(&pkg_id("root"), vec![
+ dep_req("foo", "=1.0.1"),
+ dep("bar"),
+ ], ®).is_err());
+}
+
+#[test]
+fn resolving_backtrack() {
+ let reg = registry(vec![
+ pkg!(("foo", "1.0.2") => [dep("bar")]),
+ pkg!(("foo", "1.0.1") => [dep("baz")]),
+ pkg!("bar" => [dep_req("foo", "=2.0.2")]),
+ pkg!("baz"),
+ ]);
+
+ let res = resolve(&pkg_id("root"), vec![
+ dep_req("foo", "^1"),
+ ], ®).unwrap();
+
+ assert_that(&res, contains(names(&[("root", "1.0.0"),
+ ("foo", "1.0.1"),
+ ("baz", "1.0.0")])));
+}
+
+#[test]
+fn resolving_allows_multiple_compatible_versions() {
+ let reg = registry(vec![
+ pkg!(("foo", "1.0.0")),
+ pkg!(("foo", "2.0.0")),
+ pkg!(("foo", "0.1.0")),
+ pkg!(("foo", "0.2.0")),
+
+ pkg!("bar" => ["d1", "d2", "d3", "d4"]),
+ pkg!("d1" => [dep_req("foo", "1")]),
+ pkg!("d2" => [dep_req("foo", "2")]),
+ pkg!("d3" => [dep_req("foo", "0.1")]),
+ pkg!("d4" => [dep_req("foo", "0.2")]),
+ ]);
+
+ let res = resolve(&pkg_id("root"), vec![
+ dep("bar"),
+ ], ®).unwrap();
+
+ assert_that(&res, contains(names(&[("root", "1.0.0"),
+ ("foo", "1.0.0"),
+ ("foo", "2.0.0"),
+ ("foo", "0.1.0"),
+ ("foo", "0.2.0"),
+ ("d1", "1.0.0"),
+ ("d2", "1.0.0"),
+ ("d3", "1.0.0"),
+ ("d4", "1.0.0"),
+ ("bar", "1.0.0")])));
+}
+
+#[test]
+fn resolving_with_deep_backtracking() {
+ let reg = registry(vec![
+ pkg!(("foo", "1.0.1") => [dep_req("bar", "1")]),
+ pkg!(("foo", "1.0.0") => [dep_req("bar", "2")]),
+
+ pkg!(("bar", "1.0.0") => [dep_req("baz", "=1.0.2"),
+ dep_req("other", "1")]),
+ pkg!(("bar", "2.0.0") => [dep_req("baz", "=1.0.1")]),
+
+ pkg!(("baz", "1.0.2") => [dep_req("other", "2")]),
+ pkg!(("baz", "1.0.1")),
+
+ pkg!(("dep_req", "1.0.0")),
+ pkg!(("dep_req", "2.0.0")),
+ ]);
+
+ let res = resolve(&pkg_id("root"), vec![
+ dep_req("foo", "1"),
+ ], ®).unwrap();
+
+ assert_that(&res, contains(names(&[("root", "1.0.0"),
+ ("foo", "1.0.0"),
+ ("bar", "2.0.0"),
+ ("baz", "1.0.1")])));
+}
+
+#[test]
+fn resolving_with_constrained_sibling_backtrack_parent() {
+ // There is no point in considering all of the backtrack_trap{1,2}
+ // candidates since they can't change the result of failing to
+ // resolve 'constrained'. Cargo should (ideally) skip past them and resume
+ // resolution once the activation of the parent, 'bar', is rolled back.
+ // Note that the traps are slightly more constrained to make sure they
+ // get picked first.
+ let mut reglist = vec![
+ pkg!(("foo", "1.0.0") => [dep_req("bar", "1.0"),
+ dep_req("constrained", "=1.0.0")]),
+
+ pkg!(("bar", "1.0.0") => [dep_req("backtrack_trap1", "1.0.2"),
+ dep_req("backtrack_trap2", "1.0.2"),
+ dep_req("constrained", "1.0.0")]),
+ pkg!(("constrained", "1.0.0")),
+ pkg!(("backtrack_trap1", "1.0.0")),
+ pkg!(("backtrack_trap2", "1.0.0")),
+ ];
+ // Bump this to make the test harder - it adds more versions of bar that will
+ // fail to resolve, and more versions of the traps to consider.
+ const NUM_BARS_AND_TRAPS: usize = 50; // minimum 2
+ for i in 1..NUM_BARS_AND_TRAPS {
+ let vsn = format!("1.0.{}", i);
+ reglist.push(pkg!(("bar", vsn.clone()) => [dep_req("backtrack_trap1", "1.0.2"),
+ dep_req("backtrack_trap2", "1.0.2"),
+ dep_req("constrained", "1.0.1")]));
+ reglist.push(pkg!(("backtrack_trap1", vsn.clone())));
+ reglist.push(pkg!(("backtrack_trap2", vsn.clone())));
+ reglist.push(pkg!(("constrained", vsn.clone())));
+ }
+ let reg = registry(reglist);
+
+ let res = resolve(&pkg_id("root"), vec![
+ dep_req("foo", "1"),
+ ], ®).unwrap();
+
+ assert_that(&res, contains(names(&[("root", "1.0.0"),
+ ("foo", "1.0.0"),
+ ("bar", "1.0.0"),
+ ("constrained", "1.0.0")])));
+}
+
+#[test]
+fn resolving_with_constrained_sibling_backtrack_activation() {
+ // It makes sense to resolve most-constrained deps first, but
+ // with that logic the backtrack traps here come between the two
+ // attempted resolutions of 'constrained'. When backtracking,
+ // cargo should skip past them and resume resolution once the
+ // number of activations for 'constrained' changes.
+ let mut reglist = vec![
+ pkg!(("foo", "1.0.0") => [dep_req("bar", "=1.0.0"),
+ dep_req("backtrack_trap1", "1.0"),
+ dep_req("backtrack_trap2", "1.0"),
+ dep_req("constrained", "<=1.0.60")]),
+ pkg!(("bar", "1.0.0") => [dep_req("constrained", ">=1.0.60")]),
+ ];
+ // Bump these to make the test harder, but you'll also need to
+ // change the version constraints on `constrained` above. To correctly
+ // exercise Cargo, the relationship between the values is:
+ // NUM_CONSTRAINED - vsn < NUM_TRAPS < vsn
+ // to make sure the traps are resolved between `constrained`.
+ const NUM_TRAPS: usize = 45; // min 1
+ const NUM_CONSTRAINED: usize = 100; // min 1
+ for i in 0..NUM_TRAPS {
+ let vsn = format!("1.0.{}", i);
+ reglist.push(pkg!(("backtrack_trap1", vsn.clone())));
+ reglist.push(pkg!(("backtrack_trap2", vsn.clone())));
+ }
+ for i in 0..NUM_CONSTRAINED {
+ let vsn = format!("1.0.{}", i);
+ reglist.push(pkg!(("constrained", vsn.clone())));
+ }
+ let reg = registry(reglist);
+
+ let res = resolve(&pkg_id("root"), vec![
+ dep_req("foo", "1"),
+ ], ®).unwrap();
+
+ assert_that(&res, contains(names(&[("root", "1.0.0"),
+ ("foo", "1.0.0"),
+ ("bar", "1.0.0"),
+ ("constrained", "1.0.60")])));
+}
+
+#[test]
+fn resolving_with_constrained_sibling_transitive_dep_effects() {
+ // When backtracking due to a failed dependency, if Cargo is
+ // trying to be clever and skip irrelevant dependencies, care must
+ // be taken to not miss the transitive effects of alternatives. E.g.
+ // in the right-to-left resolution of the graph below, B may
+ // affect whether D is successfully resolved.
+ //
+ // A
+ // / | \
+ // B C D
+ // | |
+ // C D
+ let reg = registry(vec![
+ pkg!(("A", "1.0.0") => [dep_req("B", "1.0"),
+ dep_req("C", "1.0"),
+ dep_req("D", "1.0.100")]),
+
+ pkg!(("B", "1.0.0") => [dep_req("C", ">=1.0.0")]),
+ pkg!(("B", "1.0.1") => [dep_req("C", ">=1.0.1")]),
+
+ pkg!(("C", "1.0.0") => [dep_req("D", "1.0.0")]),
+ pkg!(("C", "1.0.1") => [dep_req("D", ">=1.0.1,<1.0.100")]),
+ pkg!(("C", "1.0.2") => [dep_req("D", ">=1.0.2,<1.0.100")]),
+
+ pkg!(("D", "1.0.0")),
+ pkg!(("D", "1.0.1")),
+ pkg!(("D", "1.0.2")),
+ pkg!(("D", "1.0.100")),
+ pkg!(("D", "1.0.101")),
+ pkg!(("D", "1.0.102")),
+ pkg!(("D", "1.0.103")),
+ pkg!(("D", "1.0.104")),
+ pkg!(("D", "1.0.105")),
+ ]);
+
+ let res = resolve(&pkg_id("root"), vec![
+ dep_req("A", "1"),
+ ], ®).unwrap();
+
+ assert_that(&res, contains(names(&[("A", "1.0.0"),
+ ("B", "1.0.0"),
+ ("C", "1.0.0"),
+ ("D", "1.0.105")])));
+}
+
+#[test]
+fn resolving_but_no_exists() {
+ let reg = registry(vec![
+ ]);
+
+ let res = resolve(&pkg_id("root"), vec![
+ dep_req("foo", "1"),
+ ], ®);
+ assert!(res.is_err());
+
+ assert_eq!(res.err().unwrap().to_string(), "\
+no matching package named `foo` found\n\
+location searched: registry `http://example.com/`\n\
+required by package `root v1.0.0 (registry `http://example.com/`)`\
+");
+}
+
+#[test]
+fn resolving_cycle() {
+ let reg = registry(vec![
+ pkg!("foo" => ["foo"]),
+ ]);
+
+ let _ = resolve(&pkg_id("root"), vec![
+ dep_req("foo", "1"),
+ ], ®);
+}
+
+#[test]
+fn hard_equality() {
+ let reg = registry(vec![
+ pkg!(("foo", "1.0.1")),
+ pkg!(("foo", "1.0.0")),
+
+ pkg!(("bar", "1.0.0") => [dep_req("foo", "1.0.0")]),
+ ]);
+
+ let res = resolve(&pkg_id("root"), vec![
+ dep_req("bar", "1"),
+ dep_req("foo", "=1.0.0"),
+ ], ®).unwrap();
+
+ assert_that(&res, contains(names(&[("root", "1.0.0"),
+ ("foo", "1.0.0"),
+ ("bar", "1.0.0")])));
+}
--- /dev/null
+use cargo::util::paths::dylib_path_envvar;
+use cargotest::support::{project, execs, path2url};
+use hamcrest::{assert_that, existing_file};
+
+#[test]
+fn simple() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/main.rs", r#"
+ fn main() { println!("hello"); }
+ "#)
+ .build();
+
+ assert_that(p.cargo("run"),
+ execs().with_status(0)
+ .with_stderr(&format!("\
+[COMPILING] foo v0.0.1 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] `target[/]debug[/]foo[EXE]`", dir = path2url(p.root())))
+ .with_stdout("\
+hello
+"));
+ assert_that(&p.bin("foo"), existing_file());
+}
+
+#[test]
+#[ignore]
+fn simple_implicit_main() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/main.rs", r#"
+ fn main() { println!("hello world"); }
+ "#)
+ .build();
+
+ assert_that(p.cargo("run").arg("--bins"),
+ execs().with_status(0)
+ .with_stderr(&format!("\
+[COMPILING] foo v0.0.1 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] `target[/]debug[/]foo[EXE]`", dir = path2url(p.root())))
+ .with_stdout("\
+hello
+"));
+ assert_that(&p.bin("foo"), existing_file());
+}
+
+#[test]
+fn simple_quiet() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/main.rs", r#"
+ fn main() { println!("hello"); }
+ "#)
+ .build();
+
+ assert_that(p.cargo("run").arg("-q"),
+ execs().with_status(0).with_stdout("\
+hello
+")
+ );
+}
+
+#[test]
+fn simple_quiet_and_verbose() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/main.rs", r#"
+ fn main() { println!("hello"); }
+ "#)
+ .build();
+
+ assert_that(p.cargo("run").arg("-q").arg("-v"),
+ execs().with_status(101).with_stderr("\
+[ERROR] cannot set both --verbose and --quiet
+"));
+}
+
+#[test]
+fn quiet_and_verbose_config() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file(".cargo/config", r#"
+ [term]
+ verbose = true
+ "#)
+ .file("src/main.rs", r#"
+ fn main() { println!("hello"); }
+ "#)
+ .build();
+
+ assert_that(p.cargo("run").arg("-q"),
+ execs().with_status(0));
+}
+
+#[test]
+fn simple_with_args() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/main.rs", r#"
+ fn main() {
+ assert_eq!(std::env::args().nth(1).unwrap(), "hello");
+ assert_eq!(std::env::args().nth(2).unwrap(), "world");
+ }
+ "#)
+ .build();
+
+ assert_that(p.cargo("run").arg("hello").arg("world"),
+ execs().with_status(0));
+}
+
+#[test]
+fn exit_code() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/main.rs", r#"
+ fn main() { std::process::exit(2); }
+ "#)
+ .build();
+
+ let mut output = String::from("\
+[COMPILING] foo v0.0.1 (file[..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] `target[..]`
+");
+ if !cfg!(unix) {
+ output.push_str("\
+[ERROR] process didn't exit successfully: `target[..]foo[..]` (exit code: 2)
+");
+ }
+ assert_that(p.cargo("run"),
+ execs().with_status(2).with_stderr(output));
+}
+
+#[test]
+fn exit_code_verbose() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/main.rs", r#"
+ fn main() { std::process::exit(2); }
+ "#)
+ .build();
+
+ let mut output = String::from("\
+[COMPILING] foo v0.0.1 (file[..])
+[RUNNING] `rustc [..]`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] `target[..]`
+");
+ if !cfg!(unix) {
+ output.push_str("\
+[ERROR] process didn't exit successfully: `target[..]foo[..]` (exit code: 2)
+");
+ }
+
+ assert_that(p.cargo("run").arg("-v"),
+ execs().with_status(2).with_stderr(output));
+}
+
+#[test]
+fn no_main_file() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("run"),
+ execs().with_status(101)
+ .with_stderr("[ERROR] a bin target must be available \
+ for `cargo run`\n"));
+}
+
+#[test]
+#[ignore]
+fn no_main_file_implicit() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("run").arg("--bins"),
+ execs().with_status(101)
+ .with_stderr("[ERROR] a bin target must be available \
+ for `cargo run`\n"));
+}
+
+#[test]
+fn too_many_bins() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/lib.rs", "")
+ .file("src/bin/a.rs", "")
+ .file("src/bin/b.rs", "")
+ .build();
+
+ assert_that(p.cargo("run"),
+ execs().with_status(101)
+ .with_stderr("[ERROR] `cargo run` requires that a project only \
+ have one executable; use the `--bin` option \
+ to specify which one to run\navailable binaries: [..]\n"));
+}
+
+#[test]
+#[ignore]
+fn too_many_bins_implicit() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/lib.rs", "")
+ .file("src/bin/a.rs", "")
+ .file("src/bin/b.rs", "")
+ .build();
+
+ assert_that(p.cargo("run").arg("--bins"),
+ execs().with_status(101)
+ .with_stderr("[ERROR] `cargo run` requires that a project only \
+ have one executable; use the `--bin` option \
+ to specify which one to run\navailable binaries: [..]\n"));
+}
+
+#[test]
+fn specify_name() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/lib.rs", "")
+ .file("src/bin/a.rs", r#"
+ #[allow(unused_extern_crates)]
+ extern crate foo;
+ fn main() { println!("hello a.rs"); }
+ "#)
+ .file("src/bin/b.rs", r#"
+ #[allow(unused_extern_crates)]
+ extern crate foo;
+ fn main() { println!("hello b.rs"); }
+ "#)
+ .build();
+
+ assert_that(p.cargo("run").arg("--bin").arg("a").arg("-v"),
+ execs().with_status(0)
+ .with_stderr(&format!("\
+[COMPILING] foo v0.0.1 ({dir})
+[RUNNING] `rustc [..] src[/]lib.rs [..]`
+[RUNNING] `rustc [..] src[/]bin[/]a.rs [..]`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] `target[/]debug[/]a[EXE]`", dir = path2url(p.root())))
+ .with_stdout("\
+hello a.rs
+"));
+
+ assert_that(p.cargo("run").arg("--bin").arg("b").arg("-v"),
+ execs().with_status(0)
+ .with_stderr("\
+[COMPILING] foo v0.0.1 ([..])
+[RUNNING] `rustc [..] src[/]bin[/]b.rs [..]`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] `target[/]debug[/]b[EXE]`")
+ .with_stdout("\
+hello b.rs
+"));
+}
+
+#[test]
+fn run_example() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/lib.rs", "")
+ .file("examples/a.rs", r#"
+ fn main() { println!("example"); }
+ "#)
+ .file("src/bin/a.rs", r#"
+ fn main() { println!("bin"); }
+ "#)
+ .build();
+
+ assert_that(p.cargo("run").arg("--example").arg("a"),
+ execs().with_status(0)
+ .with_stderr(&format!("\
+[COMPILING] foo v0.0.1 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] `target[/]debug[/]examples[/]a[EXE]`", dir = path2url(p.root())))
+ .with_stdout("\
+example
+"));
+}
+
+#[test]
+#[ignore]
+fn run_bin_implicit() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/lib.rs", "")
+ .file("examples/a.rs", r#"
+ fn main() { println!("example"); }
+ "#)
+ .file("src/bin/a.rs", r#"
+ fn main() { println!("bin"); }
+ "#)
+ .build();
+
+ assert_that(p.cargo("run").arg("--bins"),
+ execs().with_status(0)
+ .with_stderr(&format!("\
+[COMPILING] foo v0.0.1 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] `target[/]debug[/]examples[/]a[EXE]`", dir = path2url(p.root())))
+ .with_stdout("\
+bin
+"));
+}
+
+#[test]
+#[ignore]
+fn run_example_implicit() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/lib.rs", "")
+ .file("examples/a.rs", r#"
+ fn main() { println!("example"); }
+ "#)
+ .file("src/bin/a.rs", r#"
+ fn main() { println!("bin"); }
+ "#)
+ .build();
+
+ assert_that(p.cargo("run").arg("--examples"),
+ execs().with_status(0)
+ .with_stderr(&format!("\
+[COMPILING] foo v0.0.1 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] `target[/]debug[/]examples[/]a[EXE]`", dir = path2url(p.root())))
+ .with_stdout("\
+example
+"));
+}
+
+#[test]
+fn run_with_filename() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/lib.rs", "")
+ .file("src/bin/a.rs", r#"
+ extern crate foo;
+ fn main() { println!("hello a.rs"); }
+ "#)
+ .file("examples/a.rs", r#"
+ fn main() { println!("example"); }
+ "#)
+ .build();
+
+ assert_that(p.cargo("run").arg("--bin").arg("bin.rs"),
+ execs().with_status(101).with_stderr("\
+[ERROR] no bin target named `bin.rs`"));
+
+ assert_that(p.cargo("run").arg("--bin").arg("a.rs"),
+ execs().with_status(101).with_stderr("\
+[ERROR] no bin target named `a.rs`
+
+Did you mean `a`?"));
+
+ assert_that(p.cargo("run").arg("--example").arg("example.rs"),
+ execs().with_status(101).with_stderr("\
+[ERROR] no example target named `example.rs`"));
+
+ assert_that(p.cargo("run").arg("--example").arg("a.rs"),
+ execs().with_status(101).with_stderr("\
+[ERROR] no example target named `a.rs`
+
+Did you mean `a`?"));
+}
+
+#[test]
+fn either_name_or_example() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/bin/a.rs", r#"
+ fn main() { println!("hello a.rs"); }
+ "#)
+ .file("examples/b.rs", r#"
+ fn main() { println!("hello b.rs"); }
+ "#)
+ .build();
+
+ assert_that(p.cargo("run").arg("--bin").arg("a").arg("--example").arg("b"),
+ execs().with_status(101)
+ .with_stderr("[ERROR] `cargo run` can run at most one \
+ executable, but multiple were \
+ specified"));
+}
+
+#[test]
+fn one_bin_multiple_examples() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/lib.rs", "")
+ .file("src/bin/main.rs", r#"
+ fn main() { println!("hello main.rs"); }
+ "#)
+ .file("examples/a.rs", r#"
+ fn main() { println!("hello a.rs"); }
+ "#)
+ .file("examples/b.rs", r#"
+ fn main() { println!("hello b.rs"); }
+ "#)
+ .build();
+
+ assert_that(p.cargo("run"),
+ execs().with_status(0)
+ .with_stderr(&format!("\
+[COMPILING] foo v0.0.1 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] `target[/]debug[/]main[EXE]`", dir = path2url(p.root())))
+ .with_stdout("\
+hello main.rs
+"));
+}
+
+#[test]
+fn example_with_release_flag() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.bar]
+ version = "*"
+ path = "bar"
+ "#)
+ .file("examples/a.rs", r#"
+ extern crate bar;
+
+ fn main() {
+ if cfg!(debug_assertions) {
+ println!("slow1")
+ } else {
+ println!("fast1")
+ }
+ bar::baz();
+ }
+ "#)
+ .file("bar/Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+
+ [lib]
+ name = "bar"
+ "#)
+ .file("bar/src/bar.rs", r#"
+ pub fn baz() {
+ if cfg!(debug_assertions) {
+ println!("slow2")
+ } else {
+ println!("fast2")
+ }
+ }
+ "#)
+ .build();
+
+ assert_that(p.cargo("run").arg("-v").arg("--release").arg("--example").arg("a"),
+ execs().with_status(0)
+ .with_stderr(&format!("\
+[COMPILING] bar v0.0.1 ({url}/bar)
+[RUNNING] `rustc --crate-name bar bar[/]src[/]bar.rs --crate-type lib \
+ --emit=dep-info,link \
+ -C opt-level=3 \
+ -C metadata=[..] \
+ --out-dir {dir}[/]target[/]release[/]deps \
+ -L dependency={dir}[/]target[/]release[/]deps`
+[COMPILING] foo v0.0.1 ({url})
+[RUNNING] `rustc --crate-name a examples[/]a.rs --crate-type bin \
+ --emit=dep-info,link \
+ -C opt-level=3 \
+ -C metadata=[..] \
+ --out-dir {dir}[/]target[/]release[/]examples \
+ -L dependency={dir}[/]target[/]release[/]deps \
+ --extern bar={dir}[/]target[/]release[/]deps[/]libbar-[..].rlib`
+[FINISHED] release [optimized] target(s) in [..]
+[RUNNING] `target[/]release[/]examples[/]a[EXE]`
+",
+ dir = p.root().display(),
+ url = path2url(p.root()),
+ ))
+ .with_stdout("\
+fast1
+fast2"));
+
+ assert_that(p.cargo("run").arg("-v").arg("--example").arg("a"),
+ execs().with_status(0)
+ .with_stderr(&format!("\
+[COMPILING] bar v0.0.1 ({url}/bar)
+[RUNNING] `rustc --crate-name bar bar[/]src[/]bar.rs --crate-type lib \
+ --emit=dep-info,link \
+ -C debuginfo=2 \
+ -C metadata=[..] \
+ --out-dir {dir}[/]target[/]debug[/]deps \
+ -L dependency={dir}[/]target[/]debug[/]deps`
+[COMPILING] foo v0.0.1 ({url})
+[RUNNING] `rustc --crate-name a examples[/]a.rs --crate-type bin \
+ --emit=dep-info,link \
+ -C debuginfo=2 \
+ -C metadata=[..] \
+ --out-dir {dir}[/]target[/]debug[/]examples \
+ -L dependency={dir}[/]target[/]debug[/]deps \
+ --extern bar={dir}[/]target[/]debug[/]deps[/]libbar-[..].rlib`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] `target[/]debug[/]examples[/]a[EXE]`
+",
+ dir = p.root().display(),
+ url = path2url(p.root()),
+ ))
+ .with_stdout("\
+slow1
+slow2"));
+}
+
+#[test]
+fn run_dylib_dep() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.bar]
+ path = "bar"
+ "#)
+ .file("src/main.rs", r#"
+ extern crate bar;
+ fn main() { bar::bar(); }
+ "#)
+ .file("bar/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+
+ [lib]
+ name = "bar"
+ crate-type = ["dylib"]
+ "#)
+ .file("bar/src/lib.rs", "pub fn bar() {}")
+ .build();
+
+ assert_that(p.cargo("run").arg("hello").arg("world"),
+ execs().with_status(0));
+}
+
+#[test]
+fn release_works() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/main.rs", r#"
+ fn main() { if cfg!(debug_assertions) { panic!() } }
+ "#)
+ .build();
+
+ assert_that(p.cargo("run").arg("--release"),
+ execs().with_status(0).with_stderr(&format!("\
+[COMPILING] foo v0.0.1 ({dir})
+[FINISHED] release [optimized] target(s) in [..]
+[RUNNING] `target[/]release[/]foo[EXE]`
+",
+ dir = path2url(p.root()),
+ )));
+ assert_that(&p.release_bin("foo"), existing_file());
+}
+
+#[test]
+fn run_bin_different_name() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [[bin]]
+ name = "bar"
+ "#)
+ .file("src/bar.rs", r#"
+ fn main() { }
+ "#)
+ .build();
+
+ assert_that(p.cargo("run"), execs().with_status(0));
+}
+
+#[test]
+fn dashes_are_forwarded() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [[bin]]
+ name = "bar"
+ "#)
+ .file("src/main.rs", r#"
+ fn main() {
+ let s: Vec<String> = std::env::args().collect();
+ assert_eq!(s[1], "a");
+ assert_eq!(s[2], "--");
+ assert_eq!(s[3], "b");
+ }
+ "#)
+ .build();
+
+ assert_that(p.cargo("run").arg("--").arg("a").arg("--").arg("b"),
+ execs().with_status(0));
+}
+
+#[test]
+fn run_from_executable_folder() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/main.rs", r#"
+ fn main() { println!("hello"); }
+ "#)
+ .build();
+
+ let cwd = p.root().join("target").join("debug");
+ p.cargo("build").exec_with_output().unwrap();
+
+ assert_that(p.cargo("run").cwd(cwd),
+ execs().with_status(0)
+ .with_stderr("\
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]\n\
+[RUNNING] `.[/]foo[EXE]`")
+ .with_stdout("\
+hello
+"));
+}
+
+#[test]
+fn run_with_library_paths() {
+ let p = project("foo");
+
+ // Only link search directories within the target output directory are
+ // propagated through to dylib_path_envvar() (see #3366).
+ let mut dir1 = p.target_debug_dir();
+ dir1.push("foo\\backslash");
+
+ let mut dir2 = p.target_debug_dir();
+ dir2.push("dir=containing=equal=signs");
+
+ let p = p
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ build = "build.rs"
+ "#)
+ .file("build.rs", &format!(r##"
+ fn main() {{
+ println!(r#"cargo:rustc-link-search=native={}"#);
+ println!(r#"cargo:rustc-link-search={}"#);
+ }}
+ "##, dir1.display(), dir2.display()))
+ .file("src/main.rs", &format!(r##"
+ fn main() {{
+ let search_path = std::env::var_os("{}").unwrap();
+ let paths = std::env::split_paths(&search_path).collect::<Vec<_>>();
+ assert!(paths.contains(&r#"{}"#.into()));
+ assert!(paths.contains(&r#"{}"#.into()));
+ }}
+ "##, dylib_path_envvar(), dir1.display(), dir2.display()))
+ .build();
+
+ assert_that(p.cargo("run"), execs().with_status(0));
+}
+
+#[test]
+fn library_paths_sorted_alphabetically() {
+ let p = project("foo");
+
+ let mut dir1 = p.target_debug_dir();
+ dir1.push("zzzzzzz");
+
+ let mut dir2 = p.target_debug_dir();
+ dir2.push("BBBBBBB");
+
+ let mut dir3 = p.target_debug_dir();
+ dir3.push("aaaaaaa");
+
+ let p = p
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ build = "build.rs"
+ "#)
+ .file("build.rs", &format!(r##"
+ fn main() {{
+ println!(r#"cargo:rustc-link-search=native={}"#);
+ println!(r#"cargo:rustc-link-search=native={}"#);
+ println!(r#"cargo:rustc-link-search=native={}"#);
+ }}
+ "##, dir1.display(), dir2.display(), dir3.display()))
+ .file("src/main.rs", &format!(r##"
+ fn main() {{
+ let search_path = std::env::var_os("{}").unwrap();
+ let paths = std::env::split_paths(&search_path).collect::<Vec<_>>();
+ // ASCII case-sensitive sort
+ assert_eq!("BBBBBBB", paths[0].file_name().unwrap().to_string_lossy());
+ assert_eq!("aaaaaaa", paths[1].file_name().unwrap().to_string_lossy());
+ assert_eq!("zzzzzzz", paths[2].file_name().unwrap().to_string_lossy());
+ }}
+ "##, dylib_path_envvar()))
+ .build();
+
+ assert_that(p.cargo("run"), execs().with_status(0));
+}
+
+#[test]
+fn fail_no_extra_verbose() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/main.rs", r#"
+ fn main() {
+ std::process::exit(1);
+ }
+ "#)
+ .build();
+
+ assert_that(p.cargo("run").arg("-q"),
+ execs().with_status(1)
+ .with_stdout("")
+ .with_stderr(""));
+}
+
+#[test]
+fn run_multiple_packages() {
+ let p = project("foo")
+ .file("foo/Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [workspace]
+
+ [dependencies]
+ d1 = { path = "d1" }
+ d2 = { path = "d2" }
+ d3 = { path = "../d3" } # outside of the workspace
+
+ [[bin]]
+ name = "foo"
+ "#)
+ .file("foo/src/foo.rs", "fn main() { println!(\"foo\"); }")
+ .file("foo/d1/Cargo.toml", r#"
+ [package]
+ name = "d1"
+ version = "0.0.1"
+ authors = []
+
+ [[bin]]
+ name = "d1"
+ "#)
+ .file("foo/d1/src/lib.rs", "")
+ .file("foo/d1/src/main.rs", "fn main() { println!(\"d1\"); }")
+ .file("foo/d2/Cargo.toml", r#"
+ [package]
+ name = "d2"
+ version = "0.0.1"
+ authors = []
+
+ [[bin]]
+ name = "d2"
+ "#)
+ .file("foo/d2/src/main.rs", "fn main() { println!(\"d2\"); }")
+ .file("d3/Cargo.toml", r#"
+ [package]
+ name = "d3"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("d3/src/main.rs", "fn main() { println!(\"d2\"); }")
+ .build();
+
+ let cargo = || {
+ let mut process_builder = p.cargo("run");
+ process_builder.cwd(p.root().join("foo"));
+ process_builder
+ };
+
+ assert_that(cargo().arg("-p").arg("d1"),
+ execs().with_status(0).with_stdout("d1"));
+
+ assert_that(cargo().arg("-p").arg("d2").arg("--bin").arg("d2"),
+ execs().with_status(0).with_stdout("d2"));
+
+ assert_that(cargo(),
+ execs().with_status(0).with_stdout("foo"));
+
+ assert_that(cargo().arg("-p").arg("d1").arg("-p").arg("d2"),
+ execs()
+ .with_status(1)
+ .with_stderr_contains("[ERROR] Invalid arguments."));
+
+ assert_that(cargo().arg("-p").arg("d3"),
+ execs()
+ .with_status(101)
+ .with_stderr_contains("[ERROR] package `d3` is not a member of the workspace"));
+}
--- /dev/null
+use cargotest::support::{execs, project};
+use hamcrest::assert_that;
+
+const CARGO_RUSTC_ERROR: &'static str =
+"[ERROR] extra arguments to `rustc` can only be passed to one target, consider filtering
+the package by passing e.g. `--lib` or `--bin NAME` to specify a single target";
+
+#[test]
+fn build_lib_for_foo() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/main.rs", r#"
+ fn main() {}
+ "#)
+ .file("src/lib.rs", r#" "#)
+ .build();
+
+ assert_that(p.cargo("rustc").arg("--lib").arg("-v"),
+ execs()
+ .with_status(0)
+ .with_stderr(format!("\
+[COMPILING] foo v0.0.1 ({url})
+[RUNNING] `rustc --crate-name foo src[/]lib.rs --crate-type lib \
+ --emit=dep-info,link -C debuginfo=2 \
+ -C metadata=[..] \
+ --out-dir [..] \
+ -L dependency={dir}[/]target[/]debug[/]deps`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+", dir = p.root().display(), url = p.url())));
+}
+
+#[test]
+fn lib() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/main.rs", r#"
+ fn main() {}
+ "#)
+ .file("src/lib.rs", r#" "#)
+ .build();
+
+ assert_that(p.cargo("rustc").arg("--lib").arg("-v")
+ .arg("--").arg("-C").arg("debug-assertions=off"),
+ execs()
+ .with_status(0)
+ .with_stderr(format!("\
+[COMPILING] foo v0.0.1 ({url})
+[RUNNING] `rustc --crate-name foo src[/]lib.rs --crate-type lib \
+ --emit=dep-info,link -C debuginfo=2 \
+ -C debug-assertions=off \
+ -C metadata=[..] \
+ --out-dir [..] \
+ -L dependency={dir}[/]target[/]debug[/]deps`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+", dir = p.root().display(), url = p.url())))
+}
+
+#[test]
+fn build_main_and_allow_unstable_options() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/main.rs", r#"
+ fn main() {}
+ "#)
+ .file("src/lib.rs", r#" "#)
+ .build();
+
+ assert_that(p.cargo("rustc").arg("-v").arg("--bin").arg("foo")
+ .arg("--").arg("-C").arg("debug-assertions"),
+ execs()
+ .with_status(0)
+ .with_stderr(&format!("\
+[COMPILING] {name} v{version} ({url})
+[RUNNING] `rustc --crate-name {name} src[/]lib.rs --crate-type lib \
+ --emit=dep-info,link -C debuginfo=2 \
+ -C metadata=[..] \
+ --out-dir [..] \
+ -L dependency={dir}[/]target[/]debug[/]deps`
+[RUNNING] `rustc --crate-name {name} src[/]main.rs --crate-type bin \
+ --emit=dep-info,link -C debuginfo=2 \
+ -C debug-assertions \
+ -C metadata=[..] \
+ --out-dir [..] \
+ -L dependency={dir}[/]target[/]debug[/]deps \
+ --extern {name}={dir}[/]target[/]debug[/]deps[/]lib{name}-[..].rlib`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+",
+ dir = p.root().display(), url = p.url(),
+ name = "foo", version = "0.0.1")));
+}
+
+#[test]
+fn fails_when_trying_to_build_main_and_lib_with_args() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/main.rs", r#"
+ fn main() {}
+ "#)
+ .file("src/lib.rs", r#" "#)
+ .build();
+
+ assert_that(p.cargo("rustc").arg("-v")
+ .arg("--").arg("-C").arg("debug-assertions"),
+ execs()
+ .with_status(101)
+ .with_stderr(CARGO_RUSTC_ERROR));
+}
+
+#[test]
+fn build_with_args_to_one_of_multiple_binaries() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/bin/foo.rs", r#"
+ fn main() {}
+ "#)
+ .file("src/bin/bar.rs", r#"
+ fn main() {}
+ "#)
+ .file("src/bin/baz.rs", r#"
+ fn main() {}
+ "#)
+ .file("src/lib.rs", r#" "#)
+ .build();
+
+ assert_that(p.cargo("rustc").arg("-v").arg("--bin").arg("bar")
+ .arg("--").arg("-C").arg("debug-assertions"),
+ execs()
+ .with_status(0)
+ .with_stderr(format!("\
+[COMPILING] foo v0.0.1 ({url})
+[RUNNING] `rustc --crate-name foo src[/]lib.rs --crate-type lib --emit=dep-info,link \
+ -C debuginfo=2 -C metadata=[..] \
+ --out-dir [..]`
+[RUNNING] `rustc --crate-name bar src[/]bin[/]bar.rs --crate-type bin --emit=dep-info,link \
+ -C debuginfo=2 -C debug-assertions [..]`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+", url = p.url())));
+}
+
+#[test]
+fn fails_with_args_to_all_binaries() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/bin/foo.rs", r#"
+ fn main() {}
+ "#)
+ .file("src/bin/bar.rs", r#"
+ fn main() {}
+ "#)
+ .file("src/bin/baz.rs", r#"
+ fn main() {}
+ "#)
+ .file("src/lib.rs", r#" "#)
+ .build();
+
+ assert_that(p.cargo("rustc").arg("-v")
+ .arg("--").arg("-C").arg("debug-assertions"),
+ execs()
+ .with_status(101)
+ .with_stderr(CARGO_RUSTC_ERROR));
+}
+
+#[test]
+fn build_with_args_to_one_of_multiple_tests() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("tests/foo.rs", r#" "#)
+ .file("tests/bar.rs", r#" "#)
+ .file("tests/baz.rs", r#" "#)
+ .file("src/lib.rs", r#" "#)
+ .build();
+
+ assert_that(p.cargo("rustc").arg("-v").arg("--test").arg("bar")
+ .arg("--").arg("-C").arg("debug-assertions"),
+ execs()
+ .with_status(0)
+ .with_stderr(format!("\
+[COMPILING] foo v0.0.1 ({url})
+[RUNNING] `rustc --crate-name foo src[/]lib.rs --crate-type lib --emit=dep-info,link \
+ -C debuginfo=2 -C metadata=[..] \
+ --out-dir [..]`
+[RUNNING] `rustc --crate-name bar tests[/]bar.rs --emit=dep-info,link -C debuginfo=2 \
+ -C debug-assertions [..]--test[..]`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+", url = p.url())));
+}
+
+#[test]
+fn build_foo_with_bar_dependency() {
+ let foo = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.bar]
+ path = "../bar"
+ "#)
+ .file("src/main.rs", r#"
+ extern crate bar;
+ fn main() {
+ bar::baz()
+ }
+ "#)
+ .build();
+ let _bar = project("bar")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("src/lib.rs", r#"
+ pub fn baz() {}
+ "#)
+ .build();
+
+ assert_that(foo.cargo("rustc").arg("-v").arg("--").arg("-C").arg("debug-assertions"),
+ execs()
+ .with_status(0)
+ .with_stderr(format!("\
+[COMPILING] bar v0.1.0 ([..])
+[RUNNING] `[..] -C debuginfo=2 [..]`
+[COMPILING] foo v0.0.1 ({url})
+[RUNNING] `[..] -C debuginfo=2 -C debug-assertions [..]`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+", url = foo.url())));
+}
+
+#[test]
+fn build_only_bar_dependency() {
+ let foo = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.bar]
+ path = "../bar"
+ "#)
+ .file("src/main.rs", r#"
+ extern crate bar;
+ fn main() {
+ bar::baz()
+ }
+ "#)
+ .build();
+ let _bar = project("bar")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("src/lib.rs", r#"
+ pub fn baz() {}
+ "#)
+ .build();
+
+ assert_that(foo.cargo("rustc").arg("-v").arg("-p").arg("bar")
+ .arg("--").arg("-C").arg("debug-assertions"),
+ execs()
+ .with_status(0)
+ .with_stderr("\
+[COMPILING] bar v0.1.0 ([..])
+[RUNNING] `rustc --crate-name bar [..] --crate-type lib [..] -C debug-assertions [..]`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+}
+
+#[test]
+fn fail_with_multiple_packages() {
+ let foo = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.bar]
+ path = "../bar"
+
+ [dependencies.baz]
+ path = "../baz"
+ "#)
+ .file("src/main.rs", r#"
+ fn main() {}
+ "#)
+ .build();
+
+ let _bar = project("bar")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("src/main.rs", r#"
+ fn main() {
+ if cfg!(flag = "1") { println!("Yeah from bar!"); }
+ }
+ "#)
+ .build();
+
+ let _baz = project("baz")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "baz"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("src/main.rs", r#"
+ fn main() {
+ if cfg!(flag = "1") { println!("Yeah from baz!"); }
+ }
+ "#)
+ .build();
+
+ assert_that(foo.cargo("rustc").arg("-v").arg("-p").arg("bar")
+ .arg("-p").arg("baz"),
+ execs().with_status(1).with_stderr("\
+[ERROR] Invalid arguments.
+
+Usage:
+ cargo rustc [options] [--] [<opts>...]"));
+}
+
+#[test]
+fn rustc_with_other_profile() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dev-dependencies]
+ a = { path = "a" }
+ "#)
+ .file("src/main.rs", r#"
+ #[cfg(test)] extern crate a;
+
+ #[test]
+ fn foo() {}
+ "#)
+ .file("a/Cargo.toml", r#"
+ [package]
+ name = "a"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("a/src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("rustc").arg("--profile").arg("test"),
+ execs().with_status(0));
+}
--- /dev/null
+use cargotest::support::{execs, project};
+use hamcrest::{assert_that};
+
+#[test]
+fn rustdoc_simple() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/lib.rs", r#" "#)
+ .build();
+
+ assert_that(p.cargo("rustdoc").arg("-v"),
+ execs()
+ .with_status(0)
+ .with_stderr(format!("\
+[DOCUMENTING] foo v0.0.1 ({url})
+[RUNNING] `rustdoc --crate-name foo src[/]lib.rs \
+ -o {dir}[/]target[/]doc \
+ -L dependency={dir}[/]target[/]debug[/]deps`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+", dir = p.root().display(), url = p.url())));
+}
+
+#[test]
+fn rustdoc_args() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/lib.rs", r#" "#)
+ .build();
+
+ assert_that(p.cargo("rustdoc").arg("-v").arg("--").arg("--cfg=foo"),
+ execs()
+ .with_status(0)
+ .with_stderr(format!("\
+[DOCUMENTING] foo v0.0.1 ({url})
+[RUNNING] `rustdoc --crate-name foo src[/]lib.rs \
+ -o {dir}[/]target[/]doc \
+ --cfg=foo \
+ -L dependency={dir}[/]target[/]debug[/]deps`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+", dir = p.root().display(), url = p.url())));
+}
+
+
+
+#[test]
+fn rustdoc_foo_with_bar_dependency() {
+ let foo = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.bar]
+ path = "../bar"
+ "#)
+ .file("src/lib.rs", r#"
+ extern crate bar;
+ pub fn foo() {}
+ "#)
+ .build();
+ let _bar = project("bar")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/lib.rs", r#"
+ pub fn baz() {}
+ "#)
+ .build();
+
+ assert_that(foo.cargo("rustdoc").arg("-v").arg("--").arg("--cfg=foo"),
+ execs()
+ .with_status(0)
+ .with_stderr(format!("\
+[COMPILING] bar v0.0.1 ([..])
+[RUNNING] `rustc [..]bar[/]src[/]lib.rs [..]`
+[DOCUMENTING] foo v0.0.1 ({url})
+[RUNNING] `rustdoc --crate-name foo src[/]lib.rs \
+ -o {dir}[/]target[/]doc \
+ --cfg=foo \
+ -L dependency={dir}[/]target[/]debug[/]deps \
+ --extern [..]`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+", dir = foo.root().display(), url = foo.url())));
+}
+
+#[test]
+fn rustdoc_only_bar_dependency() {
+ let foo = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.bar]
+ path = "../bar"
+ "#)
+ .file("src/main.rs", r#"
+ extern crate bar;
+ fn main() {
+ bar::baz()
+ }
+ "#)
+ .build();
+ let _bar = project("bar")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/lib.rs", r#"
+ pub fn baz() {}
+ "#)
+ .build();
+
+ assert_that(foo.cargo("rustdoc").arg("-v").arg("-p").arg("bar")
+ .arg("--").arg("--cfg=foo"),
+ execs()
+ .with_status(0)
+ .with_stderr(format!("\
+[DOCUMENTING] bar v0.0.1 ([..])
+[RUNNING] `rustdoc --crate-name bar [..]bar[/]src[/]lib.rs \
+ -o {dir}[/]target[/]doc \
+ --cfg=foo \
+ -L dependency={dir}[/]target[/]debug[/]deps`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+", dir = foo.root().display())));
+}
+
+
+#[test]
+fn rustdoc_same_name_documents_lib() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/main.rs", r#"
+ fn main() {}
+ "#)
+ .file("src/lib.rs", r#" "#)
+ .build();
+
+ assert_that(p.cargo("rustdoc").arg("-v")
+ .arg("--").arg("--cfg=foo"),
+ execs()
+ .with_status(0)
+ .with_stderr(format!("\
+[DOCUMENTING] foo v0.0.1 ([..])
+[RUNNING] `rustdoc --crate-name foo src[/]lib.rs \
+ -o {dir}[/]target[/]doc \
+ --cfg=foo \
+ -L dependency={dir}[/]target[/]debug[/]deps`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+", dir = p.root().display())));
+}
--- /dev/null
+use cargotest::support::{project, execs};
+use hamcrest::assert_that;
+
+#[test]
+fn parses_env() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("doc").env("RUSTDOCFLAGS", "--cfg=foo").arg("-v"),
+ execs().with_status(0)
+ .with_stderr_contains("\
+[RUNNING] `rustdoc [..] --cfg=foo[..]`
+"));
+}
+
+#[test]
+fn parses_config() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/lib.rs", "")
+ .file(".cargo/config", r#"
+ [build]
+ rustdocflags = ["--cfg", "foo"]
+ "#)
+ .build();
+
+ assert_that(p.cargo("doc").arg("-v"),
+ execs().with_status(0)
+ .with_stderr_contains("\
+[RUNNING] `rustdoc [..] --cfg foo[..]`
+"));
+}
+
+#[test]
+fn bad_flags() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("doc").env("RUSTDOCFLAGS", "--bogus"),
+ execs().with_status(101));
+}
+
+#[test]
+fn rerun() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("doc").env("RUSTDOCFLAGS", "--cfg=foo"),
+ execs().with_status(0));
+ assert_that(p.cargo("doc").env("RUSTDOCFLAGS", "--cfg=foo"),
+ execs().with_status(0).with_stderr("\
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+ assert_that(p.cargo("doc").env("RUSTDOCFLAGS", "--cfg=bar"),
+ execs().with_status(0).with_stderr("\
+[DOCUMENTING] foo v0.0.1 ([..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+}
+
+#[test]
+fn rustdocflags_passed_to_rustdoc_through_cargo_test() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ "#)
+ .file("src/lib.rs", r#"
+ //! ```
+ //! assert!(cfg!(do_not_choke));
+ //! ```
+ "#)
+ .build();
+
+ assert_that(p.cargo("test").arg("--doc").env("RUSTDOCFLAGS", "--cfg do_not_choke"),
+ execs().with_status(0));
+}
+
+#[test]
+fn rustdocflags_passed_to_rustdoc_through_cargo_test_only_once() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("test").arg("--doc").env("RUSTDOCFLAGS", "--markdown-no-toc"),
+ execs().with_status(0));
+}
--- /dev/null
+use std::io::Write;
+use std::fs::{self, File};
+
+use cargotest::rustc_host;
+use cargotest::support::{project, project_in_home, execs, paths};
+use hamcrest::assert_that;
+
+#[test]
+fn env_rustflags_normal_source() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ "#)
+ .file("src/lib.rs", "")
+ .file("src/bin/a.rs", "fn main() {}")
+ .file("examples/b.rs", "fn main() {}")
+ .file("tests/c.rs", "#[test] fn f() { }")
+ .file("benches/d.rs", r#"
+ #![feature(test)]
+ extern crate test;
+ #[bench] fn run1(_ben: &mut test::Bencher) { }"#)
+ .build();
+
+ // Use RUSTFLAGS to pass an argument that will generate an error
+ assert_that(p.cargo("build").env("RUSTFLAGS", "-Z bogus")
+ .arg("--lib"),
+ execs().with_status(101));
+ assert_that(p.cargo("build").env("RUSTFLAGS", "-Z bogus")
+ .arg("--bin=a"),
+ execs().with_status(101));
+ assert_that(p.cargo("build").env("RUSTFLAGS", "-Z bogus")
+ .arg("--example=b"),
+ execs().with_status(101));
+ assert_that(p.cargo("test").env("RUSTFLAGS", "-Z bogus"),
+ execs().with_status(101));
+ assert_that(p.cargo("bench").env("RUSTFLAGS", "-Z bogus"),
+ execs().with_status(101));
+}
+
+#[test]
+fn env_rustflags_build_script() {
+ // RUSTFLAGS should be passed to rustc for build scripts
+ // when --target is not specified.
+ // In this test if --cfg foo is passed the build will fail.
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ build = "build.rs"
+ "#)
+ .file("src/lib.rs", "")
+ .file("build.rs", r#"
+ fn main() { }
+ #[cfg(not(foo))]
+ fn main() { }
+ "#)
+ .build();
+
+ assert_that(p.cargo("build").env("RUSTFLAGS", "--cfg foo"),
+ execs().with_status(0));
+}
+
+#[test]
+fn env_rustflags_build_script_dep() {
+ // RUSTFLAGS should be passed to rustc for build scripts
+ // when --target is not specified.
+ // In this test if --cfg foo is not passed the build will fail.
+ let foo = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ build = "build.rs"
+
+ [build-dependencies.bar]
+ path = "../bar"
+ "#)
+ .file("src/lib.rs", "")
+ .file("build.rs", r#"
+ fn main() { }
+ "#)
+ .build();
+ let _bar = project("bar")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ "#)
+ .file("src/lib.rs", r#"
+ fn bar() { }
+ #[cfg(not(foo))]
+ fn bar() { }
+ "#)
+ .build();
+
+ assert_that(foo.cargo("build").env("RUSTFLAGS", "--cfg foo"),
+ execs().with_status(0));
+}
+
+#[test]
+fn env_rustflags_plugin() {
+ // RUSTFLAGS should be passed to rustc for plugins
+ // when --target is not specified.
+ // In this test if --cfg foo is not passed the build will fail.
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+
+ [lib]
+ name = "foo"
+ plugin = true
+ "#)
+ .file("src/lib.rs", r#"
+ fn main() { }
+ #[cfg(not(foo))]
+ fn main() { }
+ "#)
+ .build();
+
+ assert_that(p.cargo("build").env("RUSTFLAGS", "--cfg foo"),
+ execs().with_status(0));
+}
+
+#[test]
+fn env_rustflags_plugin_dep() {
+ // RUSTFLAGS should be passed to rustc for plugins
+ // when --target is not specified.
+ // In this test if --cfg foo is not passed the build will fail.
+ let foo = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+
+ [lib]
+ name = "foo"
+ plugin = true
+
+ [dependencies.bar]
+ path = "../bar"
+ "#)
+ .file("src/lib.rs", r#"
+ fn foo() { }
+ "#)
+ .build();
+ let _bar = project("bar")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+
+ [lib]
+ name = "bar"
+ "#)
+ .file("src/lib.rs", r#"
+ fn bar() { }
+ #[cfg(not(foo))]
+ fn bar() { }
+ "#)
+ .build();
+
+ assert_that(foo.cargo("build").env("RUSTFLAGS", "--cfg foo"),
+ execs().with_status(0));
+}
+
+#[test]
+fn env_rustflags_normal_source_with_target() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ "#)
+ .file("src/lib.rs", "")
+ .file("src/bin/a.rs", "fn main() {}")
+ .file("examples/b.rs", "fn main() {}")
+ .file("tests/c.rs", "#[test] fn f() { }")
+ .file("benches/d.rs", r#"
+ #![feature(test)]
+ extern crate test;
+ #[bench] fn run1(_ben: &mut test::Bencher) { }"#)
+ .build();
+
+ let host = &rustc_host();
+
+ // Use RUSTFLAGS to pass an argument that will generate an error
+ assert_that(p.cargo("build").env("RUSTFLAGS", "-Z bogus")
+ .arg("--lib").arg("--target").arg(host),
+ execs().with_status(101));
+ assert_that(p.cargo("build").env("RUSTFLAGS", "-Z bogus")
+ .arg("--bin=a").arg("--target").arg(host),
+ execs().with_status(101));
+ assert_that(p.cargo("build").env("RUSTFLAGS", "-Z bogus")
+ .arg("--example=b").arg("--target").arg(host),
+ execs().with_status(101));
+ assert_that(p.cargo("test").env("RUSTFLAGS", "-Z bogus")
+ .arg("--target").arg(host),
+ execs().with_status(101));
+ assert_that(p.cargo("bench").env("RUSTFLAGS", "-Z bogus")
+ .arg("--target").arg(host),
+ execs().with_status(101));
+}
+
+#[test]
+fn env_rustflags_build_script_with_target() {
+ // RUSTFLAGS should not be passed to rustc for build scripts
+ // when --target is specified.
+ // In this test if --cfg foo is passed the build will fail.
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ build = "build.rs"
+ "#)
+ .file("src/lib.rs", "")
+ .file("build.rs", r#"
+ fn main() { }
+ #[cfg(foo)]
+ fn main() { }
+ "#)
+ .build();
+
+ let host = rustc_host();
+ assert_that(p.cargo("build").env("RUSTFLAGS", "--cfg foo")
+ .arg("--target").arg(host),
+ execs().with_status(0));
+}
+
+#[test]
+fn env_rustflags_build_script_dep_with_target() {
+ // RUSTFLAGS should not be passed to rustc for build scripts
+ // when --target is specified.
+ // In this test if --cfg foo is passed the build will fail.
+ let foo = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ build = "build.rs"
+
+ [build-dependencies.bar]
+ path = "../bar"
+ "#)
+ .file("src/lib.rs", "")
+ .file("build.rs", r#"
+ fn main() { }
+ "#)
+ .build();
+ let _bar = project("bar")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ "#)
+ .file("src/lib.rs", r#"
+ fn bar() { }
+ #[cfg(foo)]
+ fn bar() { }
+ "#)
+ .build();
+
+ let host = rustc_host();
+ assert_that(foo.cargo("build").env("RUSTFLAGS", "--cfg foo")
+ .arg("--target").arg(host),
+ execs().with_status(0));
+}
+
+#[test]
+fn env_rustflags_plugin_with_target() {
+ // RUSTFLAGS should not be passed to rustc for plugins
+ // when --target is specified.
+ // In this test if --cfg foo is passed the build will fail.
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+
+ [lib]
+ name = "foo"
+ plugin = true
+ "#)
+ .file("src/lib.rs", r#"
+ fn main() { }
+ #[cfg(foo)]
+ fn main() { }
+ "#)
+ .build();
+
+ let host = rustc_host();
+ assert_that(p.cargo("build").env("RUSTFLAGS", "--cfg foo")
+ .arg("--target").arg(host),
+ execs().with_status(0));
+}
+
+#[test]
+fn env_rustflags_plugin_dep_with_target() {
+ // RUSTFLAGS should not be passed to rustc for plugins
+ // when --target is specified.
+ // In this test if --cfg foo is passed the build will fail.
+ let foo = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+
+ [lib]
+ name = "foo"
+ plugin = true
+
+ [dependencies.bar]
+ path = "../bar"
+ "#)
+ .file("src/lib.rs", r#"
+ fn foo() { }
+ "#)
+ .build();
+ let _bar = project("bar")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+
+ [lib]
+ name = "bar"
+ "#)
+ .file("src/lib.rs", r#"
+ fn bar() { }
+ #[cfg(foo)]
+ fn bar() { }
+ "#)
+ .build();
+
+ let host = rustc_host();
+ assert_that(foo.cargo("build").env("RUSTFLAGS", "--cfg foo")
+ .arg("--target").arg(host),
+ execs().with_status(0));
+}
+
+#[test]
+fn env_rustflags_recompile() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0));
+ // Setting RUSTFLAGS forces a recompile
+ assert_that(p.cargo("build").env("RUSTFLAGS", "-Z bogus"),
+ execs().with_status(101));
+}
+
+#[test]
+fn env_rustflags_recompile2() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build").env("RUSTFLAGS", "--cfg foo"),
+ execs().with_status(0));
+ // Setting RUSTFLAGS forces a recompile
+ assert_that(p.cargo("build").env("RUSTFLAGS", "-Z bogus"),
+ execs().with_status(101));
+}
+
+#[test]
+fn env_rustflags_no_recompile() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build").env("RUSTFLAGS", "--cfg foo"),
+ execs().with_status(0));
+ assert_that(p.cargo("build").env("RUSTFLAGS", "--cfg foo"),
+ execs().with_stdout("").with_status(0));
+}
+
+#[test]
+fn build_rustflags_normal_source() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ "#)
+ .file("src/lib.rs", "")
+ .file("src/bin/a.rs", "fn main() {}")
+ .file("examples/b.rs", "fn main() {}")
+ .file("tests/c.rs", "#[test] fn f() { }")
+ .file("benches/d.rs", r#"
+ #![feature(test)]
+ extern crate test;
+ #[bench] fn run1(_ben: &mut test::Bencher) { }"#)
+ .file(".cargo/config", r#"
+ [build]
+ rustflags = ["-Z", "bogus"]
+ "#)
+ .build();
+
+ assert_that(p.cargo("build")
+ .arg("--lib"),
+ execs().with_status(101));
+ assert_that(p.cargo("build")
+ .arg("--bin=a"),
+ execs().with_status(101));
+ assert_that(p.cargo("build")
+ .arg("--example=b"),
+ execs().with_status(101));
+ assert_that(p.cargo("test"),
+ execs().with_status(101));
+ assert_that(p.cargo("bench"),
+ execs().with_status(101));
+}
+
+#[test]
+fn build_rustflags_build_script() {
+ // RUSTFLAGS should be passed to rustc for build scripts
+ // when --target is not specified.
+ // In this test if --cfg foo is passed the build will fail.
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ build = "build.rs"
+ "#)
+ .file("src/lib.rs", "")
+ .file("build.rs", r#"
+ fn main() { }
+ #[cfg(not(foo))]
+ fn main() { }
+ "#)
+ .file(".cargo/config", r#"
+ [build]
+ rustflags = ["--cfg", "foo"]
+ "#)
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0));
+}
+
+#[test]
+fn build_rustflags_build_script_dep() {
+ // RUSTFLAGS should be passed to rustc for build scripts
+ // when --target is not specified.
+ // In this test if --cfg foo is not passed the build will fail.
+ let foo = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ build = "build.rs"
+
+ [build-dependencies.bar]
+ path = "../bar"
+ "#)
+ .file("src/lib.rs", "")
+ .file("build.rs", r#"
+ fn main() { }
+ "#)
+ .file(".cargo/config", r#"
+ [build]
+ rustflags = ["--cfg", "foo"]
+ "#)
+ .build();
+ let _bar = project("bar")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ "#)
+ .file("src/lib.rs", r#"
+ fn bar() { }
+ #[cfg(not(foo))]
+ fn bar() { }
+ "#)
+ .build();
+
+ assert_that(foo.cargo("build"),
+ execs().with_status(0));
+}
+
+#[test]
+fn build_rustflags_plugin() {
+ // RUSTFLAGS should be passed to rustc for plugins
+ // when --target is not specified.
+ // In this test if --cfg foo is not passed the build will fail.
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+
+ [lib]
+ name = "foo"
+ plugin = true
+ "#)
+ .file("src/lib.rs", r#"
+ fn main() { }
+ #[cfg(not(foo))]
+ fn main() { }
+ "#)
+ .file(".cargo/config", r#"
+ [build]
+ rustflags = ["--cfg", "foo"]
+ "#)
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0));
+}
+
+#[test]
+fn build_rustflags_plugin_dep() {
+ // RUSTFLAGS should be passed to rustc for plugins
+ // when --target is not specified.
+ // In this test if --cfg foo is not passed the build will fail.
+ let foo = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+
+ [lib]
+ name = "foo"
+ plugin = true
+
+ [dependencies.bar]
+ path = "../bar"
+ "#)
+ .file("src/lib.rs", r#"
+ fn foo() { }
+ "#)
+ .file(".cargo/config", r#"
+ [build]
+ rustflags = ["--cfg", "foo"]
+ "#)
+ .build();
+ let _bar = project("bar")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+
+ [lib]
+ name = "bar"
+ "#)
+ .file("src/lib.rs", r#"
+ fn bar() { }
+ #[cfg(not(foo))]
+ fn bar() { }
+ "#)
+ .build();
+
+ assert_that(foo.cargo("build"),
+ execs().with_status(0));
+}
+
+#[test]
+fn build_rustflags_normal_source_with_target() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ "#)
+ .file("src/lib.rs", "")
+ .file("src/bin/a.rs", "fn main() {}")
+ .file("examples/b.rs", "fn main() {}")
+ .file("tests/c.rs", "#[test] fn f() { }")
+ .file("benches/d.rs", r#"
+ #![feature(test)]
+ extern crate test;
+ #[bench] fn run1(_ben: &mut test::Bencher) { }"#)
+ .file(".cargo/config", r#"
+ [build]
+ rustflags = ["-Z", "bogus"]
+ "#)
+ .build();
+
+ let ref host = rustc_host();
+
+ // Use RUSTFLAGS to pass an argument that will generate an error
+ assert_that(p.cargo("build")
+ .arg("--lib").arg("--target").arg(host),
+ execs().with_status(101));
+ assert_that(p.cargo("build")
+ .arg("--bin=a").arg("--target").arg(host),
+ execs().with_status(101));
+ assert_that(p.cargo("build")
+ .arg("--example=b").arg("--target").arg(host),
+ execs().with_status(101));
+ assert_that(p.cargo("test")
+ .arg("--target").arg(host),
+ execs().with_status(101));
+ assert_that(p.cargo("bench")
+ .arg("--target").arg(host),
+ execs().with_status(101));
+}
+
+#[test]
+fn build_rustflags_build_script_with_target() {
+ // RUSTFLAGS should not be passed to rustc for build scripts
+ // when --target is specified.
+ // In this test if --cfg foo is passed the build will fail.
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ build = "build.rs"
+ "#)
+ .file("src/lib.rs", "")
+ .file("build.rs", r#"
+ fn main() { }
+ #[cfg(foo)]
+ fn main() { }
+ "#)
+ .file(".cargo/config", r#"
+ [build]
+ rustflags = ["--cfg", "foo"]
+ "#)
+ .build();
+
+ let host = rustc_host();
+ assert_that(p.cargo("build")
+ .arg("--target").arg(host),
+ execs().with_status(0));
+}
+
+#[test]
+fn build_rustflags_build_script_dep_with_target() {
+ // RUSTFLAGS should not be passed to rustc for build scripts
+ // when --target is specified.
+ // In this test if --cfg foo is passed the build will fail.
+ let foo = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ build = "build.rs"
+
+ [build-dependencies.bar]
+ path = "../bar"
+ "#)
+ .file("src/lib.rs", "")
+ .file("build.rs", r#"
+ fn main() { }
+ "#)
+ .file(".cargo/config", r#"
+ [build]
+ rustflags = ["--cfg", "foo"]
+ "#)
+ .build();
+ let _bar = project("bar")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ "#)
+ .file("src/lib.rs", r#"
+ fn bar() { }
+ #[cfg(foo)]
+ fn bar() { }
+ "#)
+ .build();
+
+ let host = rustc_host();
+ assert_that(foo.cargo("build")
+ .arg("--target").arg(host),
+ execs().with_status(0));
+}
+
+#[test]
+fn build_rustflags_plugin_with_target() {
+ // RUSTFLAGS should not be passed to rustc for plugins
+ // when --target is specified.
+ // In this test if --cfg foo is passed the build will fail.
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+
+ [lib]
+ name = "foo"
+ plugin = true
+ "#)
+ .file("src/lib.rs", r#"
+ fn main() { }
+ #[cfg(foo)]
+ fn main() { }
+ "#)
+ .file(".cargo/config", r#"
+ [build]
+ rustflags = ["--cfg", "foo"]
+ "#)
+ .build();
+
+ let host = rustc_host();
+ assert_that(p.cargo("build")
+ .arg("--target").arg(host),
+ execs().with_status(0));
+}
+
+#[test]
+fn build_rustflags_plugin_dep_with_target() {
+ // RUSTFLAGS should not be passed to rustc for plugins
+ // when --target is specified.
+ // In this test if --cfg foo is passed the build will fail.
+ let foo = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+
+ [lib]
+ name = "foo"
+ plugin = true
+
+ [dependencies.bar]
+ path = "../bar"
+ "#)
+ .file("src/lib.rs", r#"
+ fn foo() { }
+ "#)
+ .file(".cargo/config", r#"
+ [build]
+ rustflags = ["--cfg", "foo"]
+ "#)
+ .build();
+ let _bar = project("bar")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+
+ [lib]
+ name = "bar"
+ "#)
+ .file("src/lib.rs", r#"
+ fn bar() { }
+ #[cfg(foo)]
+ fn bar() { }
+ "#)
+ .build();
+
+ let host = rustc_host();
+ assert_that(foo.cargo("build")
+ .arg("--target").arg(host),
+ execs().with_status(0));
+}
+
+#[test]
+fn build_rustflags_recompile() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0));
+
+ // Setting RUSTFLAGS forces a recompile
+ let config = r#"
+ [build]
+ rustflags = ["-Z", "bogus"]
+ "#;
+ let config_file = paths::root().join("foo/.cargo/config");
+ fs::create_dir_all(config_file.parent().unwrap()).unwrap();
+ let mut config_file = File::create(config_file).unwrap();
+ config_file.write_all(config.as_bytes()).unwrap();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101));
+}
+
+#[test]
+fn build_rustflags_recompile2() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build").env("RUSTFLAGS", "--cfg foo"),
+ execs().with_status(0));
+
+ // Setting RUSTFLAGS forces a recompile
+ let config = r#"
+ [build]
+ rustflags = ["-Z", "bogus"]
+ "#;
+ let config_file = paths::root().join("foo/.cargo/config");
+ fs::create_dir_all(config_file.parent().unwrap()).unwrap();
+ let mut config_file = File::create(config_file).unwrap();
+ config_file.write_all(config.as_bytes()).unwrap();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101));
+}
+
+#[test]
+fn build_rustflags_no_recompile() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ "#)
+ .file("src/lib.rs", "")
+ .file(".cargo/config", r#"
+ [build]
+ rustflags = ["--cfg", "foo"]
+ "#)
+ .build();
+
+ assert_that(p.cargo("build").env("RUSTFLAGS", "--cfg foo"),
+ execs().with_status(0));
+ assert_that(p.cargo("build").env("RUSTFLAGS", "--cfg foo"),
+ execs().with_stdout("").with_status(0));
+}
+
+#[test]
+fn build_rustflags_with_home_config() {
+ // We need a config file inside the home directory
+ let home = paths::home();
+ let home_config = home.join(".cargo");
+ fs::create_dir(&home_config).unwrap();
+ File::create(&home_config.join("config")).unwrap().write_all(br#"
+ [build]
+ rustflags = ["-Cllvm-args=-x86-asm-syntax=intel"]
+ "#).unwrap();
+
+ // And we need the project to be inside the home directory
+ // so the walking process finds the home project twice.
+ let p = project_in_home("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(0));
+}
+
+#[test]
+fn target_rustflags_normal_source() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ "#)
+ .file("src/lib.rs", "")
+ .file("src/bin/a.rs", "fn main() {}")
+ .file("examples/b.rs", "fn main() {}")
+ .file("tests/c.rs", "#[test] fn f() { }")
+ .file("benches/d.rs", r#"
+ #![feature(test)]
+ extern crate test;
+ #[bench] fn run1(_ben: &mut test::Bencher) { }"#)
+ .file(".cargo/config", &format!("
+ [target.{}]
+ rustflags = [\"-Z\", \"bogus\"]
+ ", rustc_host()))
+ .build();
+
+ assert_that(p.cargo("build")
+ .arg("--lib"),
+ execs().with_status(101));
+ assert_that(p.cargo("build")
+ .arg("--bin=a"),
+ execs().with_status(101));
+ assert_that(p.cargo("build")
+ .arg("--example=b"),
+ execs().with_status(101));
+ assert_that(p.cargo("test"),
+ execs().with_status(101));
+ assert_that(p.cargo("bench"),
+ execs().with_status(101));
+}
+
+// target.{}.rustflags takes precedence over build.rustflags
+#[test]
+fn target_rustflags_precedence() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ "#)
+ .file("src/lib.rs", "")
+ .file(".cargo/config", &format!("
+ [build]
+ rustflags = [\"--cfg\", \"foo\"]
+
+ [target.{}]
+ rustflags = [\"-Z\", \"bogus\"]
+ ", rustc_host()))
+ .build();
+
+ assert_that(p.cargo("build")
+ .arg("--lib"),
+ execs().with_status(101));
+ assert_that(p.cargo("build")
+ .arg("--bin=a"),
+ execs().with_status(101));
+ assert_that(p.cargo("build")
+ .arg("--example=b"),
+ execs().with_status(101));
+ assert_that(p.cargo("test"),
+ execs().with_status(101));
+ assert_that(p.cargo("bench"),
+ execs().with_status(101));
+}
+
+#[test]
+fn cfg_rustflags_normal_source() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ "#)
+ .file("src/lib.rs", "pub fn t() {}")
+ .file("src/bin/a.rs", "fn main() {}")
+ .file("examples/b.rs", "fn main() {}")
+ .file("tests/c.rs", "#[test] fn f() { }")
+ .file(".cargo/config", &format!(r#"
+ [target.'cfg({})']
+ rustflags = ["--cfg", "bar"]
+ "#, if rustc_host().contains("-windows-") {"windows"} else {"not(windows)"}))
+ .build();
+
+ assert_that(p.cargo("build").arg("--lib").arg("-v"),
+ execs().with_status(0).with_stderr("\
+[COMPILING] foo v0.0.1 ([..])
+[RUNNING] `rustc [..] --cfg bar[..]`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+
+ assert_that(p.cargo("build").arg("--bin=a").arg("-v"),
+ execs().with_status(0).with_stderr("\
+[COMPILING] foo v0.0.1 ([..])
+[RUNNING] `rustc [..] --cfg bar[..]`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+
+ assert_that(p.cargo("build").arg("--example=b").arg("-v"),
+ execs().with_status(0).with_stderr("\
+[COMPILING] foo v0.0.1 ([..])
+[RUNNING] `rustc [..] --cfg bar[..]`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+
+ assert_that(p.cargo("test").arg("--no-run").arg("-v"),
+ execs().with_status(0).with_stderr("\
+[COMPILING] foo v0.0.1 ([..])
+[RUNNING] `rustc [..] --cfg bar[..]`
+[RUNNING] `rustc [..] --cfg bar[..]`
+[RUNNING] `rustc [..] --cfg bar[..]`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+
+ assert_that(p.cargo("bench").arg("--no-run").arg("-v"),
+ execs().with_status(0).with_stderr("\
+[COMPILING] foo v0.0.1 ([..])
+[RUNNING] `rustc [..] --cfg bar[..]`
+[RUNNING] `rustc [..] --cfg bar[..]`
+[RUNNING] `rustc [..] --cfg bar[..]`
+[FINISHED] release [optimized] target(s) in [..]
+"));
+
+}
+
+// target.'cfg(...)'.rustflags takes precedence over build.rustflags
+#[test]
+fn cfg_rustflags_precedence() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ "#)
+ .file("src/lib.rs", "pub fn t() {}")
+ .file("src/bin/a.rs", "fn main() {}")
+ .file("examples/b.rs", "fn main() {}")
+ .file("tests/c.rs", "#[test] fn f() { }")
+ .file(".cargo/config", &format!(r#"
+ [build]
+ rustflags = ["--cfg", "foo"]
+
+ [target.'cfg({})']
+ rustflags = ["--cfg", "bar"]
+ "#, if rustc_host().contains("-windows-") { "windows" } else { "not(windows)" }))
+ .build();
+
+ assert_that(p.cargo("build").arg("--lib").arg("-v"),
+ execs().with_status(0).with_stderr("\
+[COMPILING] foo v0.0.1 ([..])
+[RUNNING] `rustc [..] --cfg bar[..]`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+
+ assert_that(p.cargo("build").arg("--bin=a").arg("-v"),
+ execs().with_status(0).with_stderr("\
+[COMPILING] foo v0.0.1 ([..])
+[RUNNING] `rustc [..] --cfg bar[..]`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+
+ assert_that(p.cargo("build").arg("--example=b").arg("-v"),
+ execs().with_status(0).with_stderr("\
+[COMPILING] foo v0.0.1 ([..])
+[RUNNING] `rustc [..] --cfg bar[..]`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+
+ assert_that(p.cargo("test").arg("--no-run").arg("-v"),
+ execs().with_status(0).with_stderr("\
+[COMPILING] foo v0.0.1 ([..])
+[RUNNING] `rustc [..] --cfg bar[..]`
+[RUNNING] `rustc [..] --cfg bar[..]`
+[RUNNING] `rustc [..] --cfg bar[..]`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+
+ assert_that(p.cargo("bench").arg("--no-run").arg("-v"),
+ execs().with_status(0).with_stderr("\
+[COMPILING] foo v0.0.1 ([..])
+[RUNNING] `rustc [..] --cfg bar[..]`
+[RUNNING] `rustc [..] --cfg bar[..]`
+[RUNNING] `rustc [..] --cfg bar[..]`
+[FINISHED] release [optimized] target(s) in [..]
+"));
+
+}
+
+#[test]
+fn target_rustflags_string_and_array_form1() {
+ let p1 = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ "#)
+ .file("src/lib.rs", "")
+ .file(".cargo/config", r#"
+ [build]
+ rustflags = ["--cfg", "foo"]
+ "#)
+ .build();
+
+ assert_that(p1.cargo("build").arg("-v"),
+ execs().with_status(0).with_stderr("\
+[COMPILING] foo v0.0.1 ([..])
+[RUNNING] `rustc [..] --cfg foo[..]`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+
+ let p2 = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ "#)
+ .file("src/lib.rs", "")
+ .file(".cargo/config", r#"
+ [build]
+ rustflags = "--cfg foo"
+ "#)
+ .build();
+
+ assert_that(p2.cargo("build").arg("-v"),
+ execs().with_status(0).with_stderr("\
+[COMPILING] foo v0.0.1 ([..])
+[RUNNING] `rustc [..] --cfg foo[..]`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+
+}
+
+#[test]
+fn target_rustflags_string_and_array_form2() {
+ let p1 = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ "#)
+ .file(".cargo/config", &format!(r#"
+ [target.{}]
+ rustflags = ["--cfg", "foo"]
+ "#, rustc_host()))
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(p1.cargo("build").arg("-v"),
+ execs().with_status(0).with_stderr("\
+[COMPILING] foo v0.0.1 ([..])
+[RUNNING] `rustc [..] --cfg foo[..]`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+
+ let p2 = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ "#)
+ .file(".cargo/config", &format!(r#"
+ [target.{}]
+ rustflags = "--cfg foo"
+ "#, rustc_host()))
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(p2.cargo("build").arg("-v"),
+ execs().with_status(0).with_stderr("\
+[COMPILING] foo v0.0.1 ([..])
+[RUNNING] `rustc [..] --cfg foo[..]`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+}
+
+#[test]
+fn two_matching_in_config() {
+ let p1 = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ "#)
+ .file(".cargo/config", r#"
+ [target.'cfg(unix)']
+ rustflags = ["--cfg", 'foo="a"']
+ [target.'cfg(windows)']
+ rustflags = ["--cfg", 'foo="a"']
+ [target.'cfg(target_pointer_width = "32")']
+ rustflags = ["--cfg", 'foo="b"']
+ [target.'cfg(target_pointer_width = "64")']
+ rustflags = ["--cfg", 'foo="b"']
+ "#)
+ .file("src/main.rs", r#"
+ fn main() {
+ if cfg!(foo = "a") {
+ println!("a");
+ } else if cfg!(foo = "b") {
+ println!("b");
+ } else {
+ panic!()
+ }
+ }
+ "#)
+ .build();
+
+ assert_that(p1.cargo("run"), execs().with_status(0));
+ assert_that(p1.cargo("build"),
+ execs().with_status(0).with_stderr("\
+[FINISHED] [..]
+"));
+}
--- /dev/null
+use std::fs::{self, File};
+use std::io::prelude::*;
+use std::path::PathBuf;
+
+use cargo::util::ProcessBuilder;
+use cargotest;
+use cargotest::support::execs;
+use cargotest::support::git::repo;
+use cargotest::support::paths;
+use hamcrest::assert_that;
+use url::Url;
+
+fn registry_path() -> PathBuf { paths::root().join("registry") }
+fn registry() -> Url { Url::from_file_path(&*registry_path()).ok().unwrap() }
+fn api_path() -> PathBuf { paths::root().join("api") }
+fn api() -> Url { Url::from_file_path(&*api_path()).ok().unwrap() }
+
+fn setup() {
+ let config = paths::root().join(".cargo/config");
+ fs::create_dir_all(config.parent().unwrap()).unwrap();
+ fs::create_dir_all(&api_path().join("api/v1")).unwrap();
+
+ let _ = repo(®istry_path())
+ .file("config.json", &format!(r#"{{
+ "dl": "{0}",
+ "api": "{0}"
+ }}"#, api()))
+ .build();
+}
+
+fn cargo_process(s: &str) -> ProcessBuilder {
+ let mut b = cargotest::cargo_process();
+ b.arg(s);
+ b
+}
+
+#[test]
+fn simple() {
+ setup();
+
+ let contents = r#"{
+ "crates": [{
+ "created_at": "2014-11-16T20:17:35Z",
+ "description": "Design by contract style assertions for Rust",
+ "documentation": null,
+ "downloads": 2,
+ "homepage": null,
+ "id": "hoare",
+ "keywords": [],
+ "license": null,
+ "links": {
+ "owners": "/api/v1/crates/hoare/owners",
+ "reverse_dependencies": "/api/v1/crates/hoare/reverse_dependencies",
+ "version_downloads": "/api/v1/crates/hoare/downloads",
+ "versions": "/api/v1/crates/hoare/versions"
+ },
+ "max_version": "0.1.1",
+ "name": "hoare",
+ "repository": "https://github.com/nick29581/libhoare",
+ "updated_at": "2014-11-20T21:49:21Z",
+ "versions": null
+ }],
+ "meta": {
+ "total": 1
+ }
+ }"#;
+ let base = api_path().join("api/v1/crates");
+
+ // Older versions of curl don't peel off query parameters when looking for
+ // filenames, so just make both files.
+ //
+ // On windows, though, `?` is an invalid character, but we always build curl
+ // from source there anyway!
+ File::create(&base).unwrap().write_all(contents.as_bytes()).unwrap();
+ if !cfg!(windows) {
+ File::create(&base.with_file_name("crates?q=postgres&per_page=10")).unwrap()
+ .write_all(contents.as_bytes()).unwrap();
+ }
+
+ assert_that(cargo_process("search").arg("postgres")
+ .arg("--index").arg(registry().to_string()),
+ execs().with_status(0)
+ .with_stdout_contains("\
+hoare = \"0.1.1\" # Design by contract style assertions for Rust"));
+}
+
+// TODO: Deprecated
+// remove once it has been decided '--host' can be safely removed
+#[test]
+fn simple_with_host() {
+ setup();
+
+ let contents = r#"{
+ "crates": [{
+ "created_at": "2014-11-16T20:17:35Z",
+ "description": "Design by contract style assertions for Rust",
+ "documentation": null,
+ "downloads": 2,
+ "homepage": null,
+ "id": "hoare",
+ "keywords": [],
+ "license": null,
+ "links": {
+ "owners": "/api/v1/crates/hoare/owners",
+ "reverse_dependencies": "/api/v1/crates/hoare/reverse_dependencies",
+ "version_downloads": "/api/v1/crates/hoare/downloads",
+ "versions": "/api/v1/crates/hoare/versions"
+ },
+ "max_version": "0.1.1",
+ "name": "hoare",
+ "repository": "https://github.com/nick29581/libhoare",
+ "updated_at": "2014-11-20T21:49:21Z",
+ "versions": null
+ }],
+ "meta": {
+ "total": 1
+ }
+ }"#;
+ let base = api_path().join("api/v1/crates");
+
+ // Older versions of curl don't peel off query parameters when looking for
+ // filenames, so just make both files.
+ //
+ // On windows, though, `?` is an invalid character, but we always build curl
+ // from source there anyway!
+ File::create(&base).unwrap().write_all(contents.as_bytes()).unwrap();
+ if !cfg!(windows) {
+ File::create(&base.with_file_name("crates?q=postgres&per_page=10")).unwrap()
+ .write_all(contents.as_bytes()).unwrap();
+ }
+
+ assert_that(cargo_process("search").arg("postgres")
+ .arg("--host").arg(registry().to_string()),
+ execs().with_status(0)
+ .with_stderr(&format!("\
+[WARNING] The flag '--host' is no longer valid.
+
+Previous versions of Cargo accepted this flag, but it is being
+deprecated. The flag is being renamed to 'index', as the flag
+wants the location of the index in which to search. Please
+use '--index' instead.
+
+This will soon become a hard error, so it's either recommended
+to update to a fixed version or contact the upstream maintainer
+about this warning.
+[UPDATING] registry `{reg}`
+",
+ reg = registry()))
+ .with_stdout_contains("\
+hoare = \"0.1.1\" # Design by contract style assertions for Rust"));
+}
+
+// TODO: Deprecated
+// remove once it has been decided '--host' can be safely removed
+#[test]
+fn simple_with_index_and_host() {
+ setup();
+
+ let contents = r#"{
+ "crates": [{
+ "created_at": "2014-11-16T20:17:35Z",
+ "description": "Design by contract style assertions for Rust",
+ "documentation": null,
+ "downloads": 2,
+ "homepage": null,
+ "id": "hoare",
+ "keywords": [],
+ "license": null,
+ "links": {
+ "owners": "/api/v1/crates/hoare/owners",
+ "reverse_dependencies": "/api/v1/crates/hoare/reverse_dependencies",
+ "version_downloads": "/api/v1/crates/hoare/downloads",
+ "versions": "/api/v1/crates/hoare/versions"
+ },
+ "max_version": "0.1.1",
+ "name": "hoare",
+ "repository": "https://github.com/nick29581/libhoare",
+ "updated_at": "2014-11-20T21:49:21Z",
+ "versions": null
+ }],
+ "meta": {
+ "total": 1
+ }
+ }"#;
+ let base = api_path().join("api/v1/crates");
+
+ // Older versions of curl don't peel off query parameters when looking for
+ // filenames, so just make both files.
+ //
+ // On windows, though, `?` is an invalid character, but we always build curl
+ // from source there anyway!
+ File::create(&base).unwrap().write_all(contents.as_bytes()).unwrap();
+ if !cfg!(windows) {
+ File::create(&base.with_file_name("crates?q=postgres&per_page=10")).unwrap()
+ .write_all(contents.as_bytes()).unwrap();
+ }
+
+ assert_that(cargo_process("search").arg("postgres")
+ .arg("--index").arg(registry().to_string())
+ .arg("--host").arg(registry().to_string()),
+ execs().with_status(0)
+ .with_stderr(&format!("\
+[WARNING] The flag '--host' is no longer valid.
+
+Previous versions of Cargo accepted this flag, but it is being
+deprecated. The flag is being renamed to 'index', as the flag
+wants the location of the index in which to search. Please
+use '--index' instead.
+
+This will soon become a hard error, so it's either recommended
+to update to a fixed version or contact the upstream maintainer
+about this warning.
+[UPDATING] registry `{reg}`
+",
+ reg = registry()))
+ .with_stdout_contains("\
+hoare = \"0.1.1\" # Design by contract style assertions for Rust"));
+}
+
+#[test]
+fn multiple_query_params() {
+ setup();
+
+ let contents = r#"{
+ "crates": [{
+ "created_at": "2014-11-16T20:17:35Z",
+ "description": "Design by contract style assertions for Rust",
+ "documentation": null,
+ "downloads": 2,
+ "homepage": null,
+ "id": "hoare",
+ "keywords": [],
+ "license": null,
+ "links": {
+ "owners": "/api/v1/crates/hoare/owners",
+ "reverse_dependencies": "/api/v1/crates/hoare/reverse_dependencies",
+ "version_downloads": "/api/v1/crates/hoare/downloads",
+ "versions": "/api/v1/crates/hoare/versions"
+ },
+ "max_version": "0.1.1",
+ "name": "hoare",
+ "repository": "https://github.com/nick29581/libhoare",
+ "updated_at": "2014-11-20T21:49:21Z",
+ "versions": null
+ }],
+ "meta": {
+ "total": 1
+ }
+ }"#;
+ let base = api_path().join("api/v1/crates");
+
+ // Older versions of curl don't peel off query parameters when looking for
+ // filenames, so just make both files.
+ //
+ // On windows, though, `?` is an invalid character, but we always build curl
+ // from source there anyway!
+ File::create(&base).unwrap().write_all(contents.as_bytes()).unwrap();
+ if !cfg!(windows) {
+ File::create(&base.with_file_name("crates?q=postgres+sql&per_page=10")).unwrap()
+ .write_all(contents.as_bytes()).unwrap();
+ }
+
+ assert_that(cargo_process("search").arg("postgres").arg("sql")
+ .arg("--index").arg(registry().to_string()),
+ execs().with_status(0)
+ .with_stdout_contains("\
+hoare = \"0.1.1\" # Design by contract style assertions for Rust"));
+}
+
+#[test]
+fn help() {
+ assert_that(cargo_process("search").arg("-h"),
+ execs().with_status(0));
+ assert_that(cargo_process("help").arg("search"),
+ execs().with_status(0));
+ // Ensure that help output goes to stdout, not stderr.
+ assert_that(cargo_process("search").arg("--help"),
+ execs().with_stderr(""));
+ assert_that(cargo_process("search").arg("--help"),
+ execs().with_stdout_contains("[..] --frozen [..]"));
+}
--- /dev/null
+use std::env;
+use std::ffi::OsStr;
+use std::path::PathBuf;
+use std::process::Command;
+
+use git2;
+use cargotest::support::{execs, project};
+use cargotest::support::registry::Package;
+use cargotest::support::paths;
+use cargotest::support::git;
+use hamcrest::assert_that;
+
+use url::Url;
+
+fn find_index() -> PathBuf {
+ let dir = paths::home().join(".cargo/registry/index");
+ dir.read_dir().unwrap().next().unwrap().unwrap().path()
+}
+
+fn run_test(path_env: Option<&OsStr>) {
+ const N: usize = 50;
+
+ let foo = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ bar = "*"
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+ Package::new("bar", "0.1.0").publish();
+
+ assert_that(foo.cargo("build"),
+ execs().with_status(0));
+
+ let index = find_index();
+ let path = paths::home().join("tmp");
+ let url = Url::from_file_path(&path).unwrap().to_string();
+ let repo = git2::Repository::init(&path).unwrap();
+ let index = git2::Repository::open(&index).unwrap();
+ let mut cfg = repo.config().unwrap();
+ cfg.set_str("user.email", "foo@bar.com").unwrap();
+ cfg.set_str("user.name", "Foo Bar").unwrap();
+ let mut cfg = index.config().unwrap();
+ cfg.set_str("user.email", "foo@bar.com").unwrap();
+ cfg.set_str("user.name", "Foo Bar").unwrap();
+
+ for _ in 0..N {
+ git::commit(&repo);
+ index.remote_anonymous(&url).unwrap()
+ .fetch(&["refs/heads/master:refs/remotes/foo/master"],
+ None,
+ None).unwrap();
+ }
+ drop((repo, index));
+ Package::new("bar", "0.1.1").publish();
+
+ let before = find_index().join(".git/objects/pack")
+ .read_dir().unwrap()
+ .count();
+ assert!(before > N);
+
+ let mut cmd = foo.cargo("update");
+ cmd.env("__CARGO_PACKFILE_LIMIT", "10");
+ if let Some(path) = path_env {
+ cmd.env("PATH", path);
+ }
+ cmd.env("RUST_LOG", "trace");
+ assert_that(cmd, execs().with_status(0));
+ let after = find_index().join(".git/objects/pack")
+ .read_dir().unwrap()
+ .count();
+ assert!(after < before,
+ "packfiles before: {}\n\
+ packfiles after: {}", before, after);
+}
+
+#[test]
+fn use_git_gc() {
+ if Command::new("git").arg("--version").output().is_err() {
+ return
+ }
+ run_test(None);
+}
+
+#[test]
+// it looks like this test passes on some windows machines but not others,
+// notably not on AppVeyor's machines. Sounds like another but for another day.
+#[cfg_attr(windows, ignore)]
+fn avoid_using_git() {
+ let path = env::var_os("PATH").unwrap_or_default();
+ let mut paths = env::split_paths(&path).collect::<Vec<_>>();
+ let idx = paths.iter().position(|p| {
+ p.join("git").exists() || p.join("git.exe").exists()
+ });
+ match idx {
+ Some(i) => { paths.remove(i); }
+ None => return,
+ }
+ run_test(Some(&env::join_paths(&paths).unwrap()));
+}
--- /dev/null
+use std::fs::File;
+use std::io::prelude::*;
+use std::str;
+
+use cargo;
+use cargotest::{sleep_ms, is_nightly, rustc_host};
+use cargotest::support::{project, execs, basic_bin_manifest, basic_lib_manifest, cargo_exe};
+use cargotest::support::paths::CargoPathExt;
+use cargotest::support::registry::Package;
+use hamcrest::{assert_that, existing_file, is_not};
+use cargo::util::process;
+
+#[test]
+fn cargo_test_simple() {
+ let p = project("foo")
+ .file("Cargo.toml", &basic_bin_manifest("foo"))
+ .file("src/main.rs", r#"
+ fn hello() -> &'static str {
+ "hello"
+ }
+
+ pub fn main() {
+ println!("{}", hello())
+ }
+
+ #[test]
+ fn test_hello() {
+ assert_eq!(hello(), "hello")
+ }"#)
+ .build();
+
+ assert_that(p.cargo("build"), execs().with_status(0));
+ assert_that(&p.bin("foo"), existing_file());
+
+ assert_that(process(&p.bin("foo")),
+ execs().with_status(0).with_stdout("hello\n"));
+
+ assert_that(p.cargo("test"),
+ execs().with_status(0).with_stderr(format!("\
+[COMPILING] foo v0.5.0 ({})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] target[/]debug[/]deps[/]foo-[..][EXE]", p.url()))
+ .with_stdout_contains("test test_hello ... ok"));
+}
+
+#[test]
+fn cargo_test_release() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ authors = []
+ version = "0.1.0"
+
+ [dependencies]
+ bar = { path = "bar" }
+ "#)
+ .file("src/lib.rs", r#"
+ extern crate bar;
+ pub fn foo() { bar::bar(); }
+
+ #[test]
+ fn test() { foo(); }
+ "#)
+ .file("tests/test.rs", r#"
+ extern crate foo;
+
+ #[test]
+ fn test() { foo::foo(); }
+ "#)
+ .file("bar/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("bar/src/lib.rs", "pub fn bar() {}")
+ .build();
+
+ assert_that(p.cargo("test").arg("-v").arg("--release"),
+ execs().with_status(0).with_stderr(format!("\
+[COMPILING] bar v0.0.1 ({dir}/bar)
+[RUNNING] [..] -C opt-level=3 [..]
+[COMPILING] foo v0.1.0 ({dir})
+[RUNNING] [..] -C opt-level=3 [..]
+[RUNNING] [..] -C opt-level=3 [..]
+[RUNNING] [..] -C opt-level=3 [..]
+[FINISHED] release [optimized] target(s) in [..]
+[RUNNING] `[..]target[/]release[/]deps[/]foo-[..][EXE]`
+[RUNNING] `[..]target[/]release[/]deps[/]test-[..][EXE]`
+[DOCTEST] foo
+[RUNNING] `rustdoc --test [..]lib.rs[..]`", dir = p.url()))
+ .with_stdout_contains_n("test test ... ok", 2)
+ .with_stdout_contains("running 0 tests"));
+}
+
+#[test]
+fn cargo_test_overflow_checks() {
+ if !is_nightly() {
+ return;
+ }
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.5.0"
+ authors = []
+
+ [[bin]]
+ name = "foo"
+
+ [profile.release]
+ overflow-checks = true
+ "#)
+ .file("src/foo.rs", r#"
+ use std::panic;
+ pub fn main() {
+ let r = panic::catch_unwind(|| {
+ [1, i32::max_value()].iter().sum::<i32>();
+ });
+ assert!(r.is_err());
+ }"#)
+ .build();
+
+ assert_that(p.cargo("build").arg("--release"),
+ execs().with_status(0));
+ assert_that(&p.release_bin("foo"), existing_file());
+
+ assert_that(process(&p.release_bin("foo")),
+ execs().with_status(0).with_stdout(""));
+}
+
+#[test]
+fn cargo_test_verbose() {
+ let p = project("foo")
+ .file("Cargo.toml", &basic_bin_manifest("foo"))
+ .file("src/main.rs", r#"
+ fn main() {}
+ #[test] fn test_hello() {}
+ "#)
+ .build();
+
+ assert_that(p.cargo("test").arg("-v").arg("hello"),
+ execs().with_status(0).with_stderr(format!("\
+[COMPILING] foo v0.5.0 ({url})
+[RUNNING] `rustc [..] src[/]main.rs [..]`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] `[..]target[/]debug[/]deps[/]foo-[..][EXE] hello`", url = p.url()))
+ .with_stdout_contains("test test_hello ... ok"));
+}
+
+#[test]
+fn many_similar_names() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/lib.rs", "
+ pub fn foo() {}
+ #[test] fn lib_test() {}
+ ")
+ .file("src/main.rs", "
+ extern crate foo;
+ fn main() {}
+ #[test] fn bin_test() { foo::foo() }
+ ")
+ .file("tests/foo.rs", r#"
+ extern crate foo;
+ #[test] fn test_test() { foo::foo() }
+ "#)
+ .build();
+
+ let output = p.cargo("test").arg("-v").exec_with_output().unwrap();
+ let output = str::from_utf8(&output.stdout).unwrap();
+ assert!(output.contains("test bin_test"), "bin_test missing\n{}", output);
+ assert!(output.contains("test lib_test"), "lib_test missing\n{}", output);
+ assert!(output.contains("test test_test"), "test_test missing\n{}", output);
+}
+
+#[test]
+fn cargo_test_failing_test_in_bin() {
+ let p = project("foo")
+ .file("Cargo.toml", &basic_bin_manifest("foo"))
+ .file("src/main.rs", r#"
+ fn hello() -> &'static str {
+ "hello"
+ }
+
+ pub fn main() {
+ println!("{}", hello())
+ }
+
+ #[test]
+ fn test_hello() {
+ assert_eq!(hello(), "nope")
+ }"#)
+ .build();
+
+ assert_that(p.cargo("build"), execs().with_status(0));
+ assert_that(&p.bin("foo"), existing_file());
+
+ assert_that(process(&p.bin("foo")),
+ execs().with_status(0).with_stdout("hello\n"));
+
+ assert_that(p.cargo("test"),
+ execs().with_stderr(format!("\
+[COMPILING] foo v0.5.0 ({url})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] target[/]debug[/]deps[/]foo-[..][EXE]
+[ERROR] test failed, to rerun pass '--bin foo'", url = p.url()))
+ .with_stdout_contains("
+running 1 test
+test test_hello ... FAILED
+
+failures:
+
+---- test_hello stdout ----
+<tab>thread 'test_hello' panicked at 'assertion failed:[..]")
+ .with_stdout_contains("[..]`(left == right)`[..]")
+ .with_stdout_contains("[..]left: `\"hello\"`,[..]")
+ .with_stdout_contains("[..]right: `\"nope\"`[..]")
+ .with_stdout_contains("[..]src[/]main.rs:12[..]")
+ .with_stdout_contains("\
+failures:
+ test_hello
+")
+ .with_status(101));
+}
+
+#[test]
+fn cargo_test_failing_test_in_test() {
+ let p = project("foo")
+ .file("Cargo.toml", &basic_bin_manifest("foo"))
+ .file("src/main.rs", r#"
+ pub fn main() {
+ println!("hello");
+ }"#)
+ .file("tests/footest.rs", r#"
+ #[test]
+ fn test_hello() {
+ assert!(false)
+ }"#)
+ .build();
+
+ assert_that(p.cargo("build"), execs().with_status(0));
+ assert_that(&p.bin("foo"), existing_file());
+
+ assert_that(process(&p.bin("foo")),
+ execs().with_status(0).with_stdout("hello\n"));
+
+ assert_that(p.cargo("test"),
+ execs().with_stderr(format!("\
+[COMPILING] foo v0.5.0 ({url})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] target[/]debug[/]deps[/]foo-[..][EXE]
+[RUNNING] target[/]debug[/]deps[/]footest-[..][EXE]
+[ERROR] test failed, to rerun pass '--test footest'", url = p.url()))
+ .with_stdout_contains("running 0 tests")
+ .with_stdout_contains("\
+running 1 test
+test test_hello ... FAILED
+
+failures:
+
+---- test_hello stdout ----
+<tab>thread 'test_hello' panicked at 'assertion failed: false', \
+ tests[/]footest.rs:4[..]
+")
+ .with_stdout_contains("\
+failures:
+ test_hello
+")
+ .with_status(101));
+}
+
+#[test]
+fn cargo_test_failing_test_in_lib() {
+ let p = project("foo")
+ .file("Cargo.toml", &basic_lib_manifest("foo"))
+ .file("src/lib.rs", r#"
+ #[test]
+ fn test_hello() {
+ assert!(false)
+ }"#)
+ .build();
+
+ assert_that(p.cargo("test"),
+ execs().with_stderr(format!("\
+[COMPILING] foo v0.5.0 ({url})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] target[/]debug[/]deps[/]foo-[..][EXE]
+[ERROR] test failed, to rerun pass '--lib'", url = p.url()))
+ .with_stdout_contains("\
+test test_hello ... FAILED
+
+failures:
+
+---- test_hello stdout ----
+<tab>thread 'test_hello' panicked at 'assertion failed: false', \
+ src[/]lib.rs:4[..]
+")
+ .with_stdout_contains("\
+failures:
+ test_hello
+")
+ .with_status(101));
+}
+
+
+#[test]
+fn test_with_lib_dep() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [[bin]]
+ name = "baz"
+ path = "src/main.rs"
+ "#)
+ .file("src/lib.rs", r#"
+ ///
+ /// ```rust
+ /// extern crate foo;
+ /// fn main() {
+ /// println!("{:?}", foo::foo());
+ /// }
+ /// ```
+ ///
+ pub fn foo(){}
+ #[test] fn lib_test() {}
+ "#)
+ .file("src/main.rs", "
+ #[allow(unused_extern_crates)]
+ extern crate foo;
+
+ fn main() {}
+
+ #[test]
+ fn bin_test() {}
+ ")
+ .build();
+
+ assert_that(p.cargo("test"),
+ execs().with_status(0).with_stderr(format!("\
+[COMPILING] foo v0.0.1 ({})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] target[/]debug[/]deps[/]foo-[..][EXE]
+[RUNNING] target[/]debug[/]deps[/]baz-[..][EXE]
+[DOCTEST] foo", p.url()))
+ .with_stdout_contains("test lib_test ... ok")
+ .with_stdout_contains("test bin_test ... ok")
+ .with_stdout_contains_n("test [..] ... ok", 3));
+}
+
+#[test]
+fn test_with_deep_lib_dep() {
+ let p = project("bar")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.foo]
+ path = "../foo"
+ "#)
+ .file("src/lib.rs", "
+ #[cfg(test)]
+ extern crate foo;
+ /// ```
+ /// bar::bar();
+ /// ```
+ pub fn bar() {}
+
+ #[test]
+ fn bar_test() {
+ foo::foo();
+ }
+ ")
+ .build();
+ let _p2 = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/lib.rs", "
+ pub fn foo() {}
+
+ #[test]
+ fn foo_test() {}
+ ")
+ .build();
+
+ assert_that(p.cargo("test"),
+ execs().with_status(0)
+ .with_stderr(&format!("\
+[COMPILING] foo v0.0.1 ([..])
+[COMPILING] bar v0.0.1 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] target[..]
+[DOCTEST] bar", dir = p.url()))
+ .with_stdout_contains("test bar_test ... ok")
+ .with_stdout_contains_n("test [..] ... ok", 2));
+}
+
+#[test]
+fn external_test_explicit() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [[test]]
+ name = "test"
+ path = "src/test.rs"
+ "#)
+ .file("src/lib.rs", r#"
+ pub fn get_hello() -> &'static str { "Hello" }
+
+ #[test]
+ fn internal_test() {}
+ "#)
+ .file("src/test.rs", r#"
+ extern crate foo;
+
+ #[test]
+ fn external_test() { assert_eq!(foo::get_hello(), "Hello") }
+ "#)
+ .build();
+
+ assert_that(p.cargo("test"),
+ execs().with_status(0).with_stderr(format!("\
+[COMPILING] foo v0.0.1 ({})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] target[/]debug[/]deps[/]foo-[..][EXE]
+[RUNNING] target[/]debug[/]deps[/]test-[..][EXE]
+[DOCTEST] foo", p.url()))
+ .with_stdout_contains("test internal_test ... ok")
+ .with_stdout_contains("test external_test ... ok")
+ .with_stdout_contains("running 0 tests"));
+}
+
+#[test]
+fn external_test_named_test() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [[test]]
+ name = "test"
+ "#)
+ .file("src/lib.rs", "")
+ .file("tests/test.rs", r#"
+ #[test]
+ fn foo() { }
+ "#)
+ .build();
+
+ assert_that(p.cargo("test"),
+ execs().with_status(0))
+}
+
+#[test]
+fn external_test_implicit() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/lib.rs", r#"
+ pub fn get_hello() -> &'static str { "Hello" }
+
+ #[test]
+ fn internal_test() {}
+ "#)
+ .file("tests/external.rs", r#"
+ extern crate foo;
+
+ #[test]
+ fn external_test() { assert_eq!(foo::get_hello(), "Hello") }
+ "#)
+ .build();
+
+ assert_that(p.cargo("test"),
+ execs().with_status(0).with_stderr(format!("\
+[COMPILING] foo v0.0.1 ({})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] target[/]debug[/]deps[/]foo-[..][EXE]
+[RUNNING] target[/]debug[/]deps[/]external-[..][EXE]
+[DOCTEST] foo", p.url()))
+ .with_stdout_contains("test internal_test ... ok")
+ .with_stdout_contains("test external_test ... ok")
+ .with_stdout_contains("running 0 tests"));
+}
+
+#[test]
+fn dont_run_examples() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/lib.rs", r#"
+ "#)
+ .file("examples/dont-run-me-i-will-fail.rs", r#"
+ fn main() { panic!("Examples should not be run by 'cargo test'"); }
+ "#)
+ .build();
+ assert_that(p.cargo("test"),
+ execs().with_status(0));
+}
+
+#[test]
+fn pass_through_command_line() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/lib.rs", "
+ #[test] fn foo() {}
+ #[test] fn bar() {}
+ ")
+ .build();
+
+ assert_that(p.cargo("test").arg("bar"),
+ execs().with_status(0)
+ .with_stderr(&format!("\
+[COMPILING] foo v0.0.1 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] target[/]debug[/]deps[/]foo-[..][EXE]
+[DOCTEST] foo", dir = p.url()))
+ .with_stdout_contains("test bar ... ok")
+ .with_stdout_contains("running 0 tests"));
+
+ assert_that(p.cargo("test").arg("foo"),
+ execs().with_status(0)
+ .with_stderr("\
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] target[/]debug[/]deps[/]foo-[..][EXE]
+[DOCTEST] foo")
+ .with_stdout_contains("test foo ... ok")
+ .with_stdout_contains("running 0 tests"));
+}
+
+// Regression test for running cargo-test twice with
+// tests in an rlib
+#[test]
+fn cargo_test_twice() {
+ let p = project("test_twice")
+ .file("Cargo.toml", &basic_lib_manifest("test_twice"))
+ .file("src/test_twice.rs", r#"
+ #![crate_type = "rlib"]
+
+ #[test]
+ fn dummy_test() { }
+ "#)
+ .build();
+
+ p.cargo("build");
+
+ for _ in 0..2 {
+ assert_that(p.cargo("test"),
+ execs().with_status(0));
+ }
+}
+
+#[test]
+fn lib_bin_same_name() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [lib]
+ name = "foo"
+ [[bin]]
+ name = "foo"
+ "#)
+ .file("src/lib.rs", "
+ #[test] fn lib_test() {}
+ ")
+ .file("src/main.rs", "
+ #[allow(unused_extern_crates)]
+ extern crate foo;
+
+ #[test]
+ fn bin_test() {}
+ ")
+ .build();
+
+ assert_that(p.cargo("test"),
+ execs().with_status(0).with_stderr(format!("\
+[COMPILING] foo v0.0.1 ({})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] target[/]debug[/]deps[/]foo-[..][EXE]
+[RUNNING] target[/]debug[/]deps[/]foo-[..][EXE]
+[DOCTEST] foo", p.url()))
+ .with_stdout_contains_n("test [..] ... ok", 2)
+ .with_stdout_contains("running 0 tests"));
+}
+
+#[test]
+fn lib_with_standard_name() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "syntax"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/lib.rs", "
+ /// ```
+ /// syntax::foo();
+ /// ```
+ pub fn foo() {}
+
+ #[test]
+ fn foo_test() {}
+ ")
+ .file("tests/test.rs", "
+ extern crate syntax;
+
+ #[test]
+ fn test() { syntax::foo() }
+ ")
+ .build();
+
+ assert_that(p.cargo("test"),
+ execs().with_status(0)
+ .with_stderr(&format!("\
+[COMPILING] syntax v0.0.1 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] target[/]debug[/]deps[/]syntax-[..][EXE]
+[RUNNING] target[/]debug[/]deps[/]test-[..][EXE]
+[DOCTEST] syntax", dir = p.url()))
+ .with_stdout_contains("test foo_test ... ok")
+ .with_stdout_contains("test test ... ok")
+ .with_stdout_contains_n("test [..] ... ok", 3));
+}
+
+#[test]
+fn lib_with_standard_name2() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "syntax"
+ version = "0.0.1"
+ authors = []
+
+ [lib]
+ name = "syntax"
+ test = false
+ doctest = false
+ "#)
+ .file("src/lib.rs", "
+ pub fn foo() {}
+ ")
+ .file("src/main.rs", "
+ extern crate syntax;
+
+ fn main() {}
+
+ #[test]
+ fn test() { syntax::foo() }
+ ")
+ .build();
+
+ assert_that(p.cargo("test"),
+ execs().with_status(0)
+ .with_stderr(&format!("\
+[COMPILING] syntax v0.0.1 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] target[/]debug[/]deps[/]syntax-[..][EXE]", dir = p.url()))
+ .with_stdout_contains("test test ... ok"));
+}
+
+#[test]
+fn lib_without_name() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "syntax"
+ version = "0.0.1"
+ authors = []
+
+ [lib]
+ test = false
+ doctest = false
+ "#)
+ .file("src/lib.rs", "
+ pub fn foo() {}
+ ")
+ .file("src/main.rs", "
+ extern crate syntax;
+
+ fn main() {}
+
+ #[test]
+ fn test() { syntax::foo() }
+ ")
+ .build();
+
+ assert_that(p.cargo("test"),
+ execs().with_status(0)
+ .with_stderr(&format!("\
+[COMPILING] syntax v0.0.1 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] target[/]debug[/]deps[/]syntax-[..][EXE]", dir = p.url()))
+ .with_stdout_contains("test test ... ok"));
+}
+
+#[test]
+fn bin_without_name() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "syntax"
+ version = "0.0.1"
+ authors = []
+
+ [lib]
+ test = false
+ doctest = false
+
+ [[bin]]
+ path = "src/main.rs"
+ "#)
+ .file("src/lib.rs", "
+ pub fn foo() {}
+ ")
+ .file("src/main.rs", "
+ extern crate syntax;
+
+ fn main() {}
+
+ #[test]
+ fn test() { syntax::foo() }
+ ")
+ .build();
+
+ assert_that(p.cargo("test"),
+ execs().with_status(101)
+ .with_stderr("\
+[ERROR] failed to parse manifest at `[..]`
+
+Caused by:
+ binary target bin.name is required"));
+}
+
+#[test]
+fn bench_without_name() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "syntax"
+ version = "0.0.1"
+ authors = []
+
+ [lib]
+ test = false
+ doctest = false
+
+ [[bench]]
+ path = "src/bench.rs"
+ "#)
+ .file("src/lib.rs", "
+ pub fn foo() {}
+ ")
+ .file("src/main.rs", "
+ extern crate syntax;
+
+ fn main() {}
+
+ #[test]
+ fn test() { syntax::foo() }
+ ")
+ .file("src/bench.rs", "
+ #![feature(test)]
+ extern crate syntax;
+ extern crate test;
+
+ #[bench]
+ fn external_bench(_b: &mut test::Bencher) {}
+ ")
+ .build();
+
+ assert_that(p.cargo("test"),
+ execs().with_status(101)
+ .with_stderr("\
+[ERROR] failed to parse manifest at `[..]`
+
+Caused by:
+ benchmark target bench.name is required"));
+}
+
+#[test]
+fn test_without_name() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "syntax"
+ version = "0.0.1"
+ authors = []
+
+ [lib]
+ test = false
+ doctest = false
+
+ [[test]]
+ path = "src/test.rs"
+ "#)
+ .file("src/lib.rs", r#"
+ pub fn foo() {}
+ pub fn get_hello() -> &'static str { "Hello" }
+ "#)
+ .file("src/main.rs", "
+ extern crate syntax;
+
+ fn main() {}
+
+ #[test]
+ fn test() { syntax::foo() }
+ ")
+ .file("src/test.rs", r#"
+ extern crate syntax;
+
+ #[test]
+ fn external_test() { assert_eq!(syntax::get_hello(), "Hello") }
+ "#)
+ .build();
+
+ assert_that(p.cargo("test"),
+ execs().with_status(101)
+ .with_stderr("\
+[ERROR] failed to parse manifest at `[..]`
+
+Caused by:
+ test target test.name is required"));
+}
+
+#[test]
+fn example_without_name() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "syntax"
+ version = "0.0.1"
+ authors = []
+
+ [lib]
+ test = false
+ doctest = false
+
+ [[example]]
+ path = "examples/example.rs"
+ "#)
+ .file("src/lib.rs", "
+ pub fn foo() {}
+ ")
+ .file("src/main.rs", "
+ extern crate syntax;
+
+ fn main() {}
+
+ #[test]
+ fn test() { syntax::foo() }
+ ")
+ .file("examples/example.rs", r#"
+ extern crate syntax;
+
+ fn main() {
+ println!("example1");
+ }
+ "#)
+ .build();
+
+ assert_that(p.cargo("test"),
+ execs().with_status(101)
+ .with_stderr("\
+[ERROR] failed to parse manifest at `[..]`
+
+Caused by:
+ example target example.name is required"));
+}
+
+#[test]
+fn bin_there_for_integration() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/main.rs", "
+ fn main() { std::process::exit(101); }
+ #[test] fn main_test() {}
+ ")
+ .file("tests/foo.rs", r#"
+ use std::process::Command;
+ #[test]
+ fn test_test() {
+ let status = Command::new("target/debug/foo").status().unwrap();
+ assert_eq!(status.code(), Some(101));
+ }
+ "#)
+ .build();
+
+ let output = p.cargo("test").arg("-v").exec_with_output().unwrap();
+ let output = str::from_utf8(&output.stdout).unwrap();
+ assert!(output.contains("main_test ... ok"), "no main_test\n{}", output);
+ assert!(output.contains("test_test ... ok"), "no test_test\n{}", output);
+}
+
+#[test]
+fn test_dylib() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [lib]
+ name = "foo"
+ crate_type = ["dylib"]
+
+ [dependencies.bar]
+ path = "bar"
+ "#)
+ .file("src/lib.rs", r#"
+ extern crate bar as the_bar;
+
+ pub fn bar() { the_bar::baz(); }
+
+ #[test]
+ fn foo() { bar(); }
+ "#)
+ .file("tests/test.rs", r#"
+ extern crate foo as the_foo;
+
+ #[test]
+ fn foo() { the_foo::bar(); }
+ "#)
+ .file("bar/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+
+ [lib]
+ name = "bar"
+ crate_type = ["dylib"]
+ "#)
+ .file("bar/src/lib.rs", "
+ pub fn baz() {}
+ ")
+ .build();
+
+ assert_that(p.cargo("test"),
+ execs().with_status(0)
+ .with_stderr(&format!("\
+[COMPILING] bar v0.0.1 ({dir}/bar)
+[COMPILING] foo v0.0.1 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] target[/]debug[/]deps[/]foo-[..][EXE]
+[RUNNING] target[/]debug[/]deps[/]test-[..][EXE]", dir = p.url()))
+ .with_stdout_contains_n("test foo ... ok", 2));
+
+ p.root().move_into_the_past();
+ assert_that(p.cargo("test"),
+ execs().with_status(0)
+ .with_stderr("\
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] target[/]debug[/]deps[/]foo-[..][EXE]
+[RUNNING] target[/]debug[/]deps[/]test-[..][EXE]")
+ .with_stdout_contains_n("test foo ... ok", 2));
+}
+
+#[test]
+fn test_twice_with_build_cmd() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ build = "build.rs"
+ "#)
+ .file("build.rs", "fn main() {}")
+ .file("src/lib.rs", "
+ #[test]
+ fn foo() {}
+ ")
+ .build();
+
+ assert_that(p.cargo("test"),
+ execs().with_status(0)
+ .with_stderr(&format!("\
+[COMPILING] foo v0.0.1 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] target[/]debug[/]deps[/]foo-[..][EXE]
+[DOCTEST] foo", dir = p.url()))
+ .with_stdout_contains("test foo ... ok")
+ .with_stdout_contains("running 0 tests"));
+
+ assert_that(p.cargo("test"),
+ execs().with_status(0)
+ .with_stderr("\
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] target[/]debug[/]deps[/]foo-[..][EXE]
+[DOCTEST] foo")
+ .with_stdout_contains("test foo ... ok")
+ .with_stdout_contains("running 0 tests"));
+}
+
+#[test]
+fn test_then_build() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/lib.rs", "
+ #[test]
+ fn foo() {}
+ ")
+ .build();
+
+ assert_that(p.cargo("test"),
+ execs().with_status(0)
+ .with_stderr(&format!("\
+[COMPILING] foo v0.0.1 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] target[/]debug[/]deps[/]foo-[..][EXE]
+[DOCTEST] foo", dir = p.url()))
+ .with_stdout_contains("test foo ... ok")
+ .with_stdout_contains("running 0 tests"));
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0)
+ .with_stdout(""));
+}
+
+#[test]
+fn test_no_run() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/lib.rs", "
+ #[test]
+ fn foo() { panic!() }
+ ")
+ .build();
+
+ assert_that(p.cargo("test").arg("--no-run"),
+ execs().with_status(0)
+ .with_stderr(&format!("\
+[COMPILING] foo v0.0.1 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+",
+ dir = p.url())));
+}
+
+#[test]
+fn test_run_specific_bin_target() {
+ let prj = project("foo")
+ .file("Cargo.toml" , r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [[bin]]
+ name="bin1"
+ path="src/bin1.rs"
+
+ [[bin]]
+ name="bin2"
+ path="src/bin2.rs"
+ "#)
+ .file("src/bin1.rs", "#[test] fn test1() { }")
+ .file("src/bin2.rs", "#[test] fn test2() { }")
+ .build();
+
+ assert_that(prj.cargo("test").arg("--bin").arg("bin2"),
+ execs().with_status(0)
+ .with_stderr(format!("\
+[COMPILING] foo v0.0.1 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] target[/]debug[/]deps[/]bin2-[..][EXE]", dir = prj.url()))
+ .with_stdout_contains("test test2 ... ok"));
+}
+
+#[test]
+fn test_run_implicit_bin_target() {
+ let prj = project("foo")
+ .file("Cargo.toml" , r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [[bin]]
+ name="mybin"
+ path="src/mybin.rs"
+ "#)
+ .file("src/mybin.rs", "#[test] fn test_in_bin() { }
+ fn main() { panic!(\"Don't execute me!\"); }")
+ .file("tests/mytest.rs", "#[test] fn test_in_test() { }")
+ .file("benches/mybench.rs", "#[test] fn test_in_bench() { }")
+ .file("examples/myexm.rs", "#[test] fn test_in_exm() { }
+ fn main() { panic!(\"Don't execute me!\"); }")
+ .build();
+
+ assert_that(prj.cargo("test").arg("--bins"),
+ execs().with_status(0)
+ .with_stderr(format!("\
+[COMPILING] foo v0.0.1 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] target[/]debug[/]deps[/]mybin-[..][EXE]", dir = prj.url()))
+ .with_stdout_contains("test test_in_bin ... ok"));
+}
+
+#[test]
+fn test_run_specific_test_target() {
+ let prj = project("foo")
+ .file("Cargo.toml" , r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/bin/a.rs", "fn main() { }")
+ .file("src/bin/b.rs", "#[test] fn test_b() { } fn main() { }")
+ .file("tests/a.rs", "#[test] fn test_a() { }")
+ .file("tests/b.rs", "#[test] fn test_b() { }")
+ .build();
+
+ assert_that(prj.cargo("test").arg("--test").arg("b"),
+ execs().with_status(0)
+ .with_stderr(format!("\
+[COMPILING] foo v0.0.1 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] target[/]debug[/]deps[/]b-[..][EXE]", dir = prj.url()))
+ .with_stdout_contains("test test_b ... ok"));
+}
+
+#[test]
+fn test_run_implicit_test_target() {
+ let prj = project("foo")
+ .file("Cargo.toml" , r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [[bin]]
+ name="mybin"
+ path="src/mybin.rs"
+ "#)
+ .file("src/mybin.rs", "#[test] fn test_in_bin() { }
+ fn main() { panic!(\"Don't execute me!\"); }")
+ .file("tests/mytest.rs", "#[test] fn test_in_test() { }")
+ .file("benches/mybench.rs", "#[test] fn test_in_bench() { }")
+ .file("examples/myexm.rs", "#[test] fn test_in_exm() { }
+ fn main() { panic!(\"Don't execute me!\"); }")
+ .build();
+
+ assert_that(prj.cargo("test").arg("--tests"),
+ execs().with_status(0)
+ .with_stderr(format!("\
+[COMPILING] foo v0.0.1 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] target[/]debug[/]deps[/]mybin-[..][EXE]
+[RUNNING] target[/]debug[/]deps[/]mytest-[..][EXE]
+[RUNNING] target[/]debug[/]examples[/]myexm-[..][EXE]", dir = prj.url()))
+ .with_stdout_contains("test test_in_test ... ok"));
+}
+
+#[test]
+fn test_run_implicit_bench_target() {
+ let prj = project("foo")
+ .file("Cargo.toml" , r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [[bin]]
+ name="mybin"
+ path="src/mybin.rs"
+ "#)
+ .file("src/mybin.rs", "#[test] fn test_in_bin() { }
+ fn main() { panic!(\"Don't execute me!\"); }")
+ .file("tests/mytest.rs", "#[test] fn test_in_test() { }")
+ .file("benches/mybench.rs", "#[test] fn test_in_bench() { }")
+ .file("examples/myexm.rs", "#[test] fn test_in_exm() { }
+ fn main() { panic!(\"Don't execute me!\"); }")
+ .build();
+
+ assert_that(prj.cargo("test").arg("--benches"),
+ execs().with_status(0)
+ .with_stderr(format!("\
+[COMPILING] foo v0.0.1 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] target[/]debug[/]deps[/]mybin-[..][EXE]
+[RUNNING] target[/]debug[/]deps[/]mybench-[..][EXE]", dir = prj.url()))
+ .with_stdout_contains("test test_in_bench ... ok"));
+}
+
+#[test]
+fn test_run_implicit_example_target() {
+ let prj = project("foo")
+ .file("Cargo.toml" , r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [[bin]]
+ name="mybin"
+ path="src/mybin.rs"
+ "#)
+ .file("src/mybin.rs", "#[test] fn test_in_bin() { }
+ fn main() { panic!(\"Don't execute me!\"); }")
+ .file("tests/mytest.rs", "#[test] fn test_in_test() { }")
+ .file("benches/mybench.rs", "#[test] fn test_in_bench() { }")
+ .file("examples/myexm.rs", "#[test] fn test_in_exm() { }
+ fn main() { panic!(\"Don't execute me!\"); }")
+ .build();
+
+ assert_that(prj.cargo("test").arg("--examples"),
+ execs().with_status(0)
+ .with_stderr(format!("\
+[COMPILING] foo v0.0.1 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] target[/]debug[/]examples[/]myexm-[..][EXE]", dir = prj.url())));
+}
+
+#[test]
+fn test_no_harness() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [[bin]]
+ name = "foo"
+ test = false
+
+ [[test]]
+ name = "bar"
+ path = "foo.rs"
+ harness = false
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .file("foo.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("test").arg("--").arg("--nocapture"),
+ execs().with_status(0)
+ .with_stderr(&format!("\
+[COMPILING] foo v0.0.1 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] target[/]debug[/]deps[/]bar-[..][EXE]
+",
+ dir = p.url())));
+}
+
+#[test]
+fn selective_testing() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.d1]
+ path = "d1"
+ [dependencies.d2]
+ path = "d2"
+
+ [lib]
+ name = "foo"
+ doctest = false
+ "#)
+ .file("src/lib.rs", "")
+ .file("d1/Cargo.toml", r#"
+ [package]
+ name = "d1"
+ version = "0.0.1"
+ authors = []
+
+ [lib]
+ name = "d1"
+ doctest = false
+ "#)
+ .file("d1/src/lib.rs", "")
+ .file("d1/src/main.rs", "#[allow(unused_extern_crates)] extern crate d1; fn main() {}")
+ .file("d2/Cargo.toml", r#"
+ [package]
+ name = "d2"
+ version = "0.0.1"
+ authors = []
+
+ [lib]
+ name = "d2"
+ doctest = false
+ "#)
+ .file("d2/src/lib.rs", "")
+ .file("d2/src/main.rs", "#[allow(unused_extern_crates)] extern crate d2; fn main() {}");
+ let p = p.build();
+
+ println!("d1");
+ assert_that(p.cargo("test").arg("-p").arg("d1"),
+ execs().with_status(0)
+ .with_stderr(&format!("\
+[COMPILING] d1 v0.0.1 ({dir}/d1)
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] target[/]debug[/]deps[/]d1-[..][EXE]
+[RUNNING] target[/]debug[/]deps[/]d1-[..][EXE]", dir = p.url()))
+ .with_stdout_contains_n("running 0 tests", 2));
+
+ println!("d2");
+ assert_that(p.cargo("test").arg("-p").arg("d2"),
+ execs().with_status(0)
+ .with_stderr(&format!("\
+[COMPILING] d2 v0.0.1 ({dir}/d2)
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] target[/]debug[/]deps[/]d2-[..][EXE]
+[RUNNING] target[/]debug[/]deps[/]d2-[..][EXE]", dir = p.url()))
+ .with_stdout_contains_n("running 0 tests", 2));
+
+ println!("whole");
+ assert_that(p.cargo("test"),
+ execs().with_status(0)
+ .with_stderr(&format!("\
+[COMPILING] foo v0.0.1 ({dir})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] target[/]debug[/]deps[/]foo-[..][EXE]", dir = p.url()))
+ .with_stdout_contains("running 0 tests"));
+}
+
+#[test]
+fn almost_cyclic_but_not_quite() {
+ let p = project("a")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "a"
+ version = "0.0.1"
+ authors = []
+
+ [dev-dependencies.b]
+ path = "b"
+ [dev-dependencies.c]
+ path = "c"
+ "#)
+ .file("src/lib.rs", r#"
+ #[cfg(test)] extern crate b;
+ #[cfg(test)] extern crate c;
+ "#)
+ .file("b/Cargo.toml", r#"
+ [package]
+ name = "b"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.a]
+ path = ".."
+ "#)
+ .file("b/src/lib.rs", r#"
+ #[allow(unused_extern_crates)]
+ extern crate a;
+ "#)
+ .file("c/Cargo.toml", r#"
+ [package]
+ name = "c"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("c/src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"), execs().with_status(0));
+ assert_that(p.cargo("test"),
+ execs().with_status(0));
+}
+
+#[test]
+fn build_then_selective_test() {
+ let p = project("a")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "a"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.b]
+ path = "b"
+ "#)
+ .file("src/lib.rs", "#[allow(unused_extern_crates)] extern crate b;")
+ .file("src/main.rs", r#"
+ #[allow(unused_extern_crates)]
+ extern crate b;
+ #[allow(unused_extern_crates)]
+ extern crate a;
+ fn main() {}
+ "#)
+ .file("b/Cargo.toml", r#"
+ [package]
+ name = "b"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("b/src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("build"), execs().with_status(0));
+ p.root().move_into_the_past();
+ assert_that(p.cargo("test").arg("-p").arg("b"),
+ execs().with_status(0));
+}
+
+#[test]
+fn example_dev_dep() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dev-dependencies.bar]
+ path = "bar"
+ "#)
+ .file("src/lib.rs", r#"
+ "#)
+ .file("examples/e1.rs", r#"
+ extern crate bar;
+ fn main() { }
+ "#)
+ .file("bar/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("bar/src/lib.rs", r#"
+ // make sure this file takes awhile to compile
+ macro_rules! f0( () => (1) );
+ macro_rules! f1( () => ({(f0!()) + (f0!())}) );
+ macro_rules! f2( () => ({(f1!()) + (f1!())}) );
+ macro_rules! f3( () => ({(f2!()) + (f2!())}) );
+ macro_rules! f4( () => ({(f3!()) + (f3!())}) );
+ macro_rules! f5( () => ({(f4!()) + (f4!())}) );
+ macro_rules! f6( () => ({(f5!()) + (f5!())}) );
+ macro_rules! f7( () => ({(f6!()) + (f6!())}) );
+ macro_rules! f8( () => ({(f7!()) + (f7!())}) );
+ pub fn bar() {
+ f8!();
+ }
+ "#)
+ .build();
+ assert_that(p.cargo("test"),
+ execs().with_status(0));
+ assert_that(p.cargo("run")
+ .arg("--example").arg("e1").arg("--release").arg("-v"),
+ execs().with_status(0));
+}
+
+#[test]
+fn selective_testing_with_docs() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.d1]
+ path = "d1"
+ "#)
+ .file("src/lib.rs", r#"
+ /// ```
+ /// not valid rust
+ /// ```
+ pub fn foo() {}
+ "#)
+ .file("d1/Cargo.toml", r#"
+ [package]
+ name = "d1"
+ version = "0.0.1"
+ authors = []
+
+ [lib]
+ name = "d1"
+ path = "d1.rs"
+ "#)
+ .file("d1/d1.rs", "");
+ let p = p.build();
+
+ assert_that(p.cargo("test").arg("-p").arg("d1"),
+ execs().with_status(0)
+ .with_stderr(&format!("\
+[COMPILING] d1 v0.0.1 ({dir}/d1)
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] target[/]debug[/]deps[/]d1[..][EXE]
+[DOCTEST] d1", dir = p.url()))
+ .with_stdout_contains_n("running 0 tests", 2));
+}
+
+#[test]
+fn example_bin_same_name() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/bin/foo.rs", r#"fn main() { println!("bin"); }"#)
+ .file("examples/foo.rs", r#"fn main() { println!("example"); }"#)
+ .build();
+
+ assert_that(p.cargo("test").arg("--no-run").arg("-v"),
+ execs().with_status(0)
+ .with_stderr(&format!("\
+[COMPILING] foo v0.0.1 ({dir})
+[RUNNING] `rustc [..]`
+[RUNNING] `rustc [..]`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+", dir = p.url())));
+
+ assert_that(&p.bin("foo"), is_not(existing_file()));
+ assert_that(&p.bin("examples/foo"), existing_file());
+
+ assert_that(p.process(&p.bin("examples/foo")),
+ execs().with_status(0).with_stdout("example\n"));
+
+ assert_that(p.cargo("run"),
+ execs().with_status(0)
+ .with_stderr("\
+[COMPILING] foo v0.0.1 ([..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] [..]")
+ .with_stdout("\
+bin
+"));
+ assert_that(&p.bin("foo"), existing_file());
+}
+
+#[test]
+fn test_with_example_twice() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/bin/foo.rs", r#"fn main() { println!("bin"); }"#)
+ .file("examples/foo.rs", r#"fn main() { println!("example"); }"#)
+ .build();
+
+ println!("first");
+ assert_that(p.cargo("test").arg("-v"),
+ execs().with_status(0));
+ assert_that(&p.bin("examples/foo"), existing_file());
+ println!("second");
+ assert_that(p.cargo("test").arg("-v"),
+ execs().with_status(0));
+ assert_that(&p.bin("examples/foo"), existing_file());
+}
+
+#[test]
+fn example_with_dev_dep() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [lib]
+ name = "foo"
+ test = false
+ doctest = false
+
+ [dev-dependencies.a]
+ path = "a"
+ "#)
+ .file("src/lib.rs", "")
+ .file("examples/ex.rs", "#[allow(unused_extern_crates)] extern crate a; fn main() {}")
+ .file("a/Cargo.toml", r#"
+ [package]
+ name = "a"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("a/src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("test").arg("-v"),
+ execs().with_status(0)
+ .with_stderr("\
+[..]
+[..]
+[..]
+[..]
+[RUNNING] `rustc --crate-name ex [..] --extern a=[..]`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+}
+
+#[test]
+fn bin_is_preserved() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/lib.rs", "")
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ assert_that(p.cargo("build").arg("-v"),
+ execs().with_status(0));
+ assert_that(&p.bin("foo"), existing_file());
+
+ println!("testing");
+ assert_that(p.cargo("test").arg("-v"),
+ execs().with_status(0));
+ assert_that(&p.bin("foo"), existing_file());
+}
+
+#[test]
+fn bad_example() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/lib.rs", "");
+ let p = p.build();
+
+ assert_that(p.cargo("run").arg("--example").arg("foo"),
+ execs().with_status(101).with_stderr("\
+[ERROR] no example target named `foo`
+"));
+ assert_that(p.cargo("run").arg("--bin").arg("foo"),
+ execs().with_status(101).with_stderr("\
+[ERROR] no bin target named `foo`
+"));
+}
+
+#[test]
+fn doctest_feature() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ [features]
+ bar = []
+ "#)
+ .file("src/lib.rs", r#"
+ /// ```rust
+ /// assert_eq!(foo::foo(), 1);
+ /// ```
+ #[cfg(feature = "bar")]
+ pub fn foo() -> i32 { 1 }
+ "#)
+ .build();
+
+ assert_that(p.cargo("test").arg("--features").arg("bar"),
+ execs().with_status(0)
+ .with_stderr("\
+[COMPILING] foo [..]
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] target[/]debug[/]deps[/]foo[..][EXE]
+[DOCTEST] foo")
+ .with_stdout_contains("running 0 tests")
+ .with_stdout_contains("test [..] ... ok"));
+}
+
+#[test]
+fn dashes_to_underscores() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo-bar"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/lib.rs", r#"
+ /// ```
+ /// assert_eq!(foo_bar::foo(), 1);
+ /// ```
+ pub fn foo() -> i32 { 1 }
+ "#)
+ .build();
+
+ assert_that(p.cargo("test").arg("-v"),
+ execs().with_status(0));
+}
+
+#[test]
+fn doctest_dev_dep() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dev-dependencies]
+ b = { path = "b" }
+ "#)
+ .file("src/lib.rs", r#"
+ /// ```
+ /// extern crate b;
+ /// ```
+ pub fn foo() {}
+ "#)
+ .file("b/Cargo.toml", r#"
+ [package]
+ name = "b"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("b/src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("test").arg("-v"),
+ execs().with_status(0));
+}
+
+#[test]
+fn filter_no_doc_tests() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/lib.rs", r#"
+ /// ```
+ /// extern crate b;
+ /// ```
+ pub fn foo() {}
+ "#)
+ .file("tests/foo.rs", "")
+ .build();
+
+ assert_that(p.cargo("test").arg("--test=foo"),
+ execs().with_status(0).with_stderr("\
+[COMPILING] foo v0.0.1 ([..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] target[/]debug[/]deps[/]foo[..][EXE]")
+ .with_stdout_contains("running 0 tests"));
+}
+
+#[test]
+fn dylib_doctest() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [lib]
+ name = "foo"
+ crate-type = ["rlib", "dylib"]
+ test = false
+ "#)
+ .file("src/lib.rs", r#"
+ /// ```
+ /// foo::foo();
+ /// ```
+ pub fn foo() {}
+ "#)
+ .build();
+
+ assert_that(p.cargo("test"),
+ execs().with_status(0).with_stderr("\
+[COMPILING] foo v0.0.1 ([..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[DOCTEST] foo")
+ .with_stdout_contains("test [..] ... ok"));
+}
+
+#[test]
+fn dylib_doctest2() {
+ // can't doctest dylibs as they're statically linked together
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [lib]
+ name = "foo"
+ crate-type = ["dylib"]
+ test = false
+ "#)
+ .file("src/lib.rs", r#"
+ /// ```
+ /// foo::foo();
+ /// ```
+ pub fn foo() {}
+ "#)
+ .build();
+
+ assert_that(p.cargo("test"),
+ execs().with_status(0).with_stdout(""));
+}
+
+#[test]
+fn cyclic_dev_dep_doc_test() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dev-dependencies]
+ bar = { path = "bar" }
+ "#)
+ .file("src/lib.rs", r#"
+ //! ```
+ //! extern crate bar;
+ //! ```
+ "#)
+ .file("bar/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ foo = { path = ".." }
+ "#)
+ .file("bar/src/lib.rs", r#"
+ #[allow(unused_extern_crates)]
+ extern crate foo;
+ "#)
+ .build();
+ assert_that(p.cargo("test"),
+ execs().with_status(0).with_stderr("\
+[COMPILING] foo v0.0.1 ([..])
+[COMPILING] bar v0.0.1 ([..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] target[/]debug[/]deps[/]foo[..][EXE]
+[DOCTEST] foo")
+ .with_stdout_contains("running 0 tests")
+ .with_stdout_contains("test [..] ... ok"));
+}
+
+#[test]
+fn dev_dep_with_build_script() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dev-dependencies]
+ bar = { path = "bar" }
+ "#)
+ .file("src/lib.rs", "")
+ .file("examples/foo.rs", "fn main() {}")
+ .file("bar/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+ build = "build.rs"
+ "#)
+ .file("bar/src/lib.rs", "")
+ .file("bar/build.rs", "fn main() {}")
+ .build();
+ assert_that(p.cargo("test"),
+ execs().with_status(0));
+}
+
+#[test]
+fn no_fail_fast() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/lib.rs", r#"
+ pub fn add_one(x: i32) -> i32{
+ x + 1
+ }
+
+ /// ```rust
+ /// use foo::sub_one;
+ /// assert_eq!(sub_one(101), 100);
+ /// ```
+ pub fn sub_one(x: i32) -> i32{
+ x - 1
+ }
+ "#)
+ .file("tests/test_add_one.rs", r#"
+ extern crate foo;
+ use foo::*;
+
+ #[test]
+ fn add_one_test() {
+ assert_eq!(add_one(1), 2);
+ }
+
+ #[test]
+ fn fail_add_one_test() {
+ assert_eq!(add_one(1), 1);
+ }
+ "#)
+ .file("tests/test_sub_one.rs", r#"
+ extern crate foo;
+ use foo::*;
+
+ #[test]
+ fn sub_one_test() {
+ assert_eq!(sub_one(1), 0);
+ }
+ "#)
+ .build();
+ assert_that(p.cargo("test").arg("--no-fail-fast"),
+ execs().with_status(101)
+ .with_stderr_contains("\
+[COMPILING] foo v0.0.1 ([..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] target[/]debug[/]deps[/]foo-[..][EXE]
+[RUNNING] target[/]debug[/]deps[/]test_add_one-[..][EXE]")
+ .with_stdout_contains("running 0 tests")
+ .with_stderr_contains("\
+[RUNNING] target[/]debug[/]deps[/]test_sub_one-[..][EXE]
+[DOCTEST] foo")
+ .with_stdout_contains("test result: FAILED. [..]")
+ .with_stdout_contains("test sub_one_test ... ok")
+ .with_stdout_contains_n("test [..] ... ok", 3));
+}
+
+#[test]
+fn test_multiple_packages() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.d1]
+ path = "d1"
+ [dependencies.d2]
+ path = "d2"
+
+ [lib]
+ name = "foo"
+ doctest = false
+ "#)
+ .file("src/lib.rs", "")
+ .file("d1/Cargo.toml", r#"
+ [package]
+ name = "d1"
+ version = "0.0.1"
+ authors = []
+
+ [lib]
+ name = "d1"
+ doctest = false
+ "#)
+ .file("d1/src/lib.rs", "")
+ .file("d2/Cargo.toml", r#"
+ [package]
+ name = "d2"
+ version = "0.0.1"
+ authors = []
+
+ [lib]
+ name = "d2"
+ doctest = false
+ "#)
+ .file("d2/src/lib.rs", "");
+ let p = p.build();
+
+ assert_that(p.cargo("test").arg("-p").arg("d1").arg("-p").arg("d2"),
+ execs().with_status(0)
+ .with_stderr_contains("\
+[RUNNING] target[/]debug[/]deps[/]d1-[..][EXE]")
+ .with_stderr_contains("\
+[RUNNING] target[/]debug[/]deps[/]d2-[..][EXE]")
+ .with_stdout_contains_n("running 0 tests", 2));
+}
+
+#[test]
+fn bin_does_not_rebuild_tests() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/lib.rs", "")
+ .file("src/main.rs", "fn main() {}")
+ .file("tests/foo.rs", "");
+ let p = p.build();
+
+ assert_that(p.cargo("test").arg("-v"),
+ execs().with_status(0));
+
+ sleep_ms(1000);
+ File::create(&p.root().join("src/main.rs")).unwrap()
+ .write_all(b"fn main() { 3; }").unwrap();
+
+ assert_that(p.cargo("test").arg("-v").arg("--no-run"),
+ execs().with_status(0)
+ .with_stderr("\
+[COMPILING] foo v0.0.1 ([..])
+[RUNNING] `rustc [..] src[/]main.rs [..]`
+[RUNNING] `rustc [..] src[/]main.rs [..]`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+}
+
+#[test]
+fn selective_test_wonky_profile() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [profile.release]
+ opt-level = 2
+
+ [dependencies]
+ a = { path = "a" }
+ "#)
+ .file("src/lib.rs", "")
+ .file("a/Cargo.toml", r#"
+ [package]
+ name = "a"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("a/src/lib.rs", "");
+ let p = p.build();
+
+ assert_that(p.cargo("test").arg("-v").arg("--no-run").arg("--release")
+ .arg("-p").arg("foo").arg("-p").arg("a"),
+ execs().with_status(0));
+}
+
+#[test]
+fn selective_test_optional_dep() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ a = { path = "a", optional = true }
+ "#)
+ .file("src/lib.rs", "")
+ .file("a/Cargo.toml", r#"
+ [package]
+ name = "a"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("a/src/lib.rs", "");
+ let p = p.build();
+
+ assert_that(p.cargo("test").arg("-v").arg("--no-run")
+ .arg("--features").arg("a").arg("-p").arg("a"),
+ execs().with_status(0).with_stderr("\
+[COMPILING] a v0.0.1 ([..])
+[RUNNING] `rustc [..] a[/]src[/]lib.rs [..]`
+[RUNNING] `rustc [..] a[/]src[/]lib.rs [..]`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+}
+
+#[test]
+fn only_test_docs() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/lib.rs", r#"
+ #[test]
+ fn foo() {
+ let a: u32 = "hello";
+ }
+
+ /// ```
+ /// foo::bar();
+ /// println!("ok");
+ /// ```
+ pub fn bar() {
+ }
+ "#)
+ .file("tests/foo.rs", "this is not rust");
+ let p = p.build();
+
+ assert_that(p.cargo("test").arg("--doc"),
+ execs().with_status(0)
+ .with_stderr("\
+[COMPILING] foo v0.0.1 ([..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[DOCTEST] foo")
+ .with_stdout_contains("test [..] ... ok"));
+}
+
+#[test]
+fn test_panic_abort_with_dep() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ bar = { path = "bar" }
+
+ [profile.dev]
+ panic = 'abort'
+ "#)
+ .file("src/lib.rs", r#"
+ extern crate bar;
+
+ #[test]
+ fn foo() {}
+ "#)
+ .file("bar/Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("bar/src/lib.rs", "")
+ .build();
+ assert_that(p.cargo("test").arg("-v"),
+ execs().with_status(0));
+}
+
+#[test]
+fn cfg_test_even_with_no_harness() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [lib]
+ harness = false
+ doctest = false
+ "#)
+ .file("src/lib.rs", r#"
+ #[cfg(test)]
+ fn main() {
+ println!("hello!");
+ }
+ "#)
+ .build();
+ assert_that(p.cargo("test").arg("-v"),
+ execs().with_status(0)
+ .with_stdout("hello!\n")
+ .with_stderr("\
+[COMPILING] foo v0.0.1 ([..])
+[RUNNING] `rustc [..]`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] `[..]`
+"));
+}
+
+#[test]
+fn panic_abort_multiple() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ a = { path = "a" }
+
+ [profile.release]
+ panic = 'abort'
+ "#)
+ .file("src/lib.rs", "#[allow(unused_extern_crates)] extern crate a;")
+ .file("a/Cargo.toml", r#"
+ [package]
+ name = "a"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("a/src/lib.rs", "")
+ .build();
+ assert_that(p.cargo("test")
+ .arg("--release").arg("-v")
+ .arg("-p").arg("foo")
+ .arg("-p").arg("a"),
+ execs().with_status(0));
+}
+
+#[test]
+fn pass_correct_cfgs_flags_to_rustdoc() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+
+ [features]
+ default = ["feature_a/default"]
+ nightly = ["feature_a/nightly"]
+
+ [dependencies.feature_a]
+ path = "libs/feature_a"
+ default-features = false
+ "#)
+ .file("src/lib.rs", r#"
+ #[cfg(test)]
+ mod tests {
+ #[test]
+ fn it_works() {
+ assert!(true);
+ }
+ }
+ "#)
+ .file("libs/feature_a/Cargo.toml", r#"
+ [package]
+ name = "feature_a"
+ version = "0.1.0"
+ authors = []
+
+ [features]
+ default = ["mock_serde_codegen"]
+ nightly = ["mock_serde_derive"]
+
+ [dependencies]
+ mock_serde_derive = { path = "../mock_serde_derive", optional = true }
+
+ [build-dependencies]
+ mock_serde_codegen = { path = "../mock_serde_codegen", optional = true }
+ "#)
+ .file("libs/feature_a/src/lib.rs", r#"
+ #[cfg(feature = "mock_serde_derive")]
+ const MSG: &'static str = "This is safe";
+
+ #[cfg(feature = "mock_serde_codegen")]
+ const MSG: &'static str = "This is risky";
+
+ pub fn get() -> &'static str {
+ MSG
+ }
+ "#)
+ .file("libs/mock_serde_derive/Cargo.toml", r#"
+ [package]
+ name = "mock_serde_derive"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("libs/mock_serde_derive/src/lib.rs", "")
+ .file("libs/mock_serde_codegen/Cargo.toml", r#"
+ [package]
+ name = "mock_serde_codegen"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("libs/mock_serde_codegen/src/lib.rs", "");
+ let p = p.build();
+
+ assert_that(p.cargo("test")
+ .arg("--package").arg("feature_a")
+ .arg("--verbose"),
+ execs().with_status(0)
+ .with_stderr_contains("\
+[DOCTEST] feature_a
+[RUNNING] `rustdoc --test [..]mock_serde_codegen[..]`"));
+
+ assert_that(p.cargo("test")
+ .arg("--verbose"),
+ execs().with_status(0)
+ .with_stderr_contains("\
+[DOCTEST] foo
+[RUNNING] `rustdoc --test [..]feature_a[..]`"));
+}
+
+#[test]
+fn test_release_ignore_panic() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ a = { path = "a" }
+
+ [profile.test]
+ panic = 'abort'
+ [profile.release]
+ panic = 'abort'
+ "#)
+ .file("src/lib.rs", "#[allow(unused_extern_crates)] extern crate a;")
+ .file("a/Cargo.toml", r#"
+ [package]
+ name = "a"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("a/src/lib.rs", "");
+ let p = p.build();
+ println!("test");
+ assert_that(p.cargo("test").arg("-v"), execs().with_status(0));
+ println!("bench");
+ assert_that(p.cargo("bench").arg("-v"), execs().with_status(0));
+}
+
+#[test]
+fn test_many_with_features() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ a = { path = "a" }
+
+ [features]
+ foo = []
+
+ [workspace]
+ "#)
+ .file("src/lib.rs", "")
+ .file("a/Cargo.toml", r#"
+ [package]
+ name = "a"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("a/src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("test").arg("-v")
+ .arg("-p").arg("a")
+ .arg("-p").arg("foo")
+ .arg("--features").arg("foo"),
+ execs().with_status(0));
+}
+
+#[test]
+fn test_all_workspace() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+
+ [dependencies]
+ bar = { path = "bar" }
+
+ [workspace]
+ "#)
+ .file("src/main.rs", r#"
+ #[test]
+ fn foo_test() {}
+ "#)
+ .file("bar/Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.1.0"
+ "#)
+ .file("bar/src/lib.rs", r#"
+ #[test]
+ fn bar_test() {}
+ "#)
+ .build();
+
+ assert_that(p.cargo("test")
+ .arg("--all"),
+ execs().with_status(0)
+ .with_stdout_contains("test foo_test ... ok")
+ .with_stdout_contains("test bar_test ... ok"));
+}
+
+#[test]
+fn test_all_exclude() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+
+ [workspace]
+ members = ["bar", "baz"]
+ "#)
+ .file("src/main.rs", r#"
+ fn main() {}
+ "#)
+ .file("bar/Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.1.0"
+ "#)
+ .file("bar/src/lib.rs", r#"
+ #[test]
+ pub fn bar() {}
+ "#)
+ .file("baz/Cargo.toml", r#"
+ [project]
+ name = "baz"
+ version = "0.1.0"
+ "#)
+ .file("baz/src/lib.rs", r#"
+ #[test]
+ pub fn baz() {
+ assert!(false);
+ }
+ "#)
+ .build();
+
+ assert_that(p.cargo("test")
+ .arg("--all")
+ .arg("--exclude")
+ .arg("baz"),
+ execs().with_status(0)
+ .with_stdout_contains("running 1 test
+test bar ... ok"));
+}
+
+#[test]
+fn test_all_virtual_manifest() {
+ let p = project("workspace")
+ .file("Cargo.toml", r#"
+ [workspace]
+ members = ["a", "b"]
+ "#)
+ .file("a/Cargo.toml", r#"
+ [project]
+ name = "a"
+ version = "0.1.0"
+ "#)
+ .file("a/src/lib.rs", r#"
+ #[test]
+ fn a() {}
+ "#)
+ .file("b/Cargo.toml", r#"
+ [project]
+ name = "b"
+ version = "0.1.0"
+ "#)
+ .file("b/src/lib.rs", r#"
+ #[test]
+ fn b() {}
+ "#)
+ .build();
+
+ assert_that(p.cargo("test")
+ .arg("--all"),
+ execs().with_status(0)
+ .with_stdout_contains("test a ... ok")
+ .with_stdout_contains("test b ... ok"));
+}
+
+#[test]
+fn test_virtual_manifest_all_implied() {
+ let p = project("workspace")
+ .file("Cargo.toml", r#"
+ [workspace]
+ members = ["a", "b"]
+ "#)
+ .file("a/Cargo.toml", r#"
+ [project]
+ name = "a"
+ version = "0.1.0"
+ "#)
+ .file("a/src/lib.rs", r#"
+ #[test]
+ fn a() {}
+ "#)
+ .file("b/Cargo.toml", r#"
+ [project]
+ name = "b"
+ version = "0.1.0"
+ "#)
+ .file("b/src/lib.rs", r#"
+ #[test]
+ fn b() {}
+ "#)
+ .build();
+
+ assert_that(p.cargo("test"),
+ execs().with_status(0)
+ .with_stdout_contains("test a ... ok")
+ .with_stdout_contains("test b ... ok"));
+}
+
+#[test]
+fn test_all_member_dependency_same_name() {
+ let p = project("workspace")
+ .file("Cargo.toml", r#"
+ [workspace]
+ members = ["a"]
+ "#)
+ .file("a/Cargo.toml", r#"
+ [project]
+ name = "a"
+ version = "0.1.0"
+
+ [dependencies]
+ a = "0.1.0"
+ "#)
+ .file("a/src/lib.rs", r#"
+ #[test]
+ fn a() {}
+ "#)
+ .build();
+
+ Package::new("a", "0.1.0").publish();
+
+ assert_that(p.cargo("test")
+ .arg("--all"),
+ execs().with_status(0)
+ .with_stdout_contains("test a ... ok"));
+}
+
+#[test]
+fn doctest_only_with_dev_dep() {
+ let p = project("workspace")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "a"
+ version = "0.1.0"
+
+ [dev-dependencies]
+ b = { path = "b" }
+ "#)
+ .file("src/lib.rs", r#"
+ /// ```
+ /// extern crate b;
+ ///
+ /// b::b();
+ /// ```
+ pub fn a() {}
+ "#)
+ .file("b/Cargo.toml", r#"
+ [project]
+ name = "b"
+ version = "0.1.0"
+ "#)
+ .file("b/src/lib.rs", r#"
+ pub fn b() {}
+ "#)
+ .build();
+
+ assert_that(p.cargo("test").arg("--doc").arg("-v"),
+ execs().with_status(0));
+}
+
+#[test]
+fn test_many_targets() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+ "#)
+ .file("src/bin/a.rs", r#"
+ fn main() {}
+ #[test] fn bin_a() {}
+ "#)
+ .file("src/bin/b.rs", r#"
+ fn main() {}
+ #[test] fn bin_b() {}
+ "#)
+ .file("src/bin/c.rs", r#"
+ fn main() {}
+ #[test] fn bin_c() { panic!(); }
+ "#)
+ .file("examples/a.rs", r#"
+ fn main() {}
+ #[test] fn example_a() {}
+ "#)
+ .file("examples/b.rs", r#"
+ fn main() {}
+ #[test] fn example_b() {}
+ "#)
+ .file("examples/c.rs", r#"
+ #[test] fn example_c() { panic!(); }
+ "#)
+ .file("tests/a.rs", r#"
+ #[test] fn test_a() {}
+ "#)
+ .file("tests/b.rs", r#"
+ #[test] fn test_b() {}
+ "#)
+ .file("tests/c.rs", r#"
+ does not compile
+ "#)
+ .build();
+
+ assert_that(p.cargo("test").arg("--verbose")
+ .arg("--bin").arg("a").arg("--bin").arg("b")
+ .arg("--example").arg("a").arg("--example").arg("b")
+ .arg("--test").arg("a").arg("--test").arg("b"),
+ execs()
+ .with_status(0)
+ .with_stdout_contains("test bin_a ... ok")
+ .with_stdout_contains("test bin_b ... ok")
+ .with_stdout_contains("test test_a ... ok")
+ .with_stdout_contains("test test_b ... ok")
+ .with_stderr_contains("[RUNNING] `rustc --crate-name a examples[/]a.rs [..]`")
+ .with_stderr_contains("[RUNNING] `rustc --crate-name b examples[/]b.rs [..]`"))
+}
+
+#[test]
+fn doctest_and_registry() {
+ let p = project("workspace")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "a"
+ version = "0.1.0"
+
+ [dependencies]
+ b = { path = "b" }
+ c = { path = "c" }
+
+ [workspace]
+ "#)
+ .file("src/lib.rs", "")
+ .file("b/Cargo.toml", r#"
+ [project]
+ name = "b"
+ version = "0.1.0"
+ "#)
+ .file("b/src/lib.rs", "
+ /// ```
+ /// b::foo();
+ /// ```
+ pub fn foo() {}
+ ")
+ .file("c/Cargo.toml", r#"
+ [project]
+ name = "c"
+ version = "0.1.0"
+
+ [dependencies]
+ b = "0.1"
+ "#)
+ .file("c/src/lib.rs", "")
+ .build();
+
+ Package::new("b", "0.1.0").publish();
+
+ assert_that(p.cargo("test").arg("--all").arg("-v"),
+ execs().with_status(0));
+}
+
+#[test]
+fn cargo_test_env() {
+ let src = format!(r#"
+ #![crate_type = "rlib"]
+
+ #[test]
+ fn env_test() {{
+ use std::env;
+ println!("{{}}", env::var("{}").unwrap());
+ }}
+ "#, cargo::CARGO_ENV);
+
+ let p = project("env_test")
+ .file("Cargo.toml", &basic_lib_manifest("env_test"))
+ .file("src/lib.rs", &src)
+ .build();
+
+ let mut pr = p.cargo("test");
+ let cargo = cargo_exe().canonicalize().unwrap();
+ assert_that(pr.args(&["--lib", "--", "--nocapture"]),
+ execs().with_status(0)
+ .with_stdout_contains(format!("\
+{}
+test env_test ... ok
+", cargo.to_str().unwrap())));
+}
+
+#[test]
+fn test_order() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+ "#)
+ .file("src/lib.rs", r#"
+ #[test] fn test_lib() {}
+ "#)
+ .file("tests/a.rs", r#"
+ #[test] fn test_a() {}
+ "#)
+ .file("tests/z.rs", r#"
+ #[test] fn test_z() {}
+ "#)
+ .build();
+
+ assert_that(p.cargo("test").arg("--all"),
+ execs().with_status(0)
+ .with_stdout_contains("
+running 1 test
+test test_lib ... ok
+
+test result: ok. [..]
+
+
+running 1 test
+test test_a ... ok
+
+test result: ok. [..]
+
+
+running 1 test
+test test_z ... ok
+
+test result: ok. [..]
+"));
+
+}
+
+#[test]
+fn cyclic_dev() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+
+ [dev-dependencies]
+ foo = { path = "." }
+ "#)
+ .file("src/lib.rs", r#"
+ #[test] fn test_lib() {}
+ "#)
+ .file("tests/foo.rs", r#"
+ extern crate foo;
+ "#)
+ .build();
+
+ assert_that(p.cargo("test").arg("--all"),
+ execs().with_status(0));
+}
+
+#[test]
+fn publish_a_crate_without_tests() {
+ Package::new("testless", "0.1.0")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "testless"
+ version = "0.1.0"
+ exclude = ["tests/*"]
+
+ [[test]]
+ name = "a_test"
+ "#)
+ .file("src/lib.rs", "")
+
+ // In real life, the package will have a test,
+ // which would be excluded from .crate file by the
+ // `exclude` field. Our test harness does not honor
+ // exclude though, so let's just not add the file!
+ // .file("tests/a_test.rs", "")
+
+ .publish();
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+
+ [dependencies]
+ testless = "0.1.0"
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+
+ assert_that(p.cargo("test"), execs().with_status(0));
+ assert_that(p.cargo("test").arg("--package").arg("testless"),
+ execs().with_status(0));
+}
+
+#[test]
+fn find_dependency_of_proc_macro_dependency_with_target() {
+ let workspace = project("workspace")
+ .file("Cargo.toml", r#"
+ [workspace]
+ members = ["root", "proc_macro_dep"]
+ "#)
+ .file("root/Cargo.toml", r#"
+ [project]
+ name = "root"
+ version = "0.1.0"
+ authors = []
+
+ [dependencies]
+ proc_macro_dep = { path = "../proc_macro_dep" }
+ "#)
+ .file("root/src/lib.rs", r#"
+ #[macro_use]
+ extern crate proc_macro_dep;
+
+ #[derive(Noop)]
+ pub struct X;
+ "#)
+ .file("proc_macro_dep/Cargo.toml", r#"
+ [project]
+ name = "proc_macro_dep"
+ version = "0.1.0"
+ authors = []
+
+ [lib]
+ proc-macro = true
+
+ [dependencies]
+ bar = "^0.1"
+ "#)
+ .file("proc_macro_dep/src/lib.rs", r#"
+ extern crate bar;
+ extern crate proc_macro;
+ use proc_macro::TokenStream;
+
+ #[proc_macro_derive(Noop)]
+ pub fn noop(_input: TokenStream) -> TokenStream {
+ "".parse().unwrap()
+ }
+ "#)
+ .build();
+ Package::new("foo", "0.1.0").publish();
+ Package::new("bar", "0.1.0")
+ .dep("foo", "0.1")
+ .file("src/lib.rs", "extern crate foo;")
+ .publish();
+ assert_that(workspace.cargo("test").arg("--all").arg("--target").arg(rustc_host()),
+ execs().with_status(0));
+}
+
+#[test]
+fn test_hint_not_masked_by_doctest() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ "#)
+ .file("src/lib.rs", r#"
+ /// ```
+ /// assert_eq!(1, 1);
+ /// ```
+ pub fn this_works() {}
+ "#)
+ .file("tests/integ.rs", r#"
+ #[test]
+ fn this_fails() {
+ panic!();
+ }
+ "#)
+ .build();
+ assert_that(p.cargo("test")
+ .arg("--no-fail-fast"),
+ execs()
+ .with_status(101)
+ .with_stdout_contains("test this_fails ... FAILED")
+ .with_stdout_contains("[..]this_works (line [..]ok")
+ .with_stderr_contains("[ERROR] test failed, to rerun pass \
+ '--test integ'"));
+}
--- /dev/null
+use cargotest::rustc_host;
+use cargotest::support::{path2url, project, execs};
+use hamcrest::assert_that;
+
+#[test]
+fn pathless_tools() {
+ let target = rustc_host();
+
+ let foo = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [lib]
+ name = "foo"
+ "#)
+ .file("src/lib.rs", "")
+ .file(".cargo/config", &format!(r#"
+ [target.{}]
+ ar = "nonexistent-ar"
+ linker = "nonexistent-linker"
+ "#, target))
+ .build();
+
+ assert_that(foo.cargo("build").arg("--verbose"),
+ execs().with_stderr(&format!("\
+[COMPILING] foo v0.0.1 ({url})
+[RUNNING] `rustc [..] -C ar=nonexistent-ar -C linker=nonexistent-linker [..]`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+", url = foo.url())))
+}
+
+#[test]
+fn absolute_tools() {
+ let target = rustc_host();
+
+ // Escaped as they appear within a TOML config file
+ let config = if cfg!(windows) {
+ (r#"C:\\bogus\\nonexistent-ar"#, r#"C:\\bogus\\nonexistent-linker"#)
+ } else {
+ (r#"/bogus/nonexistent-ar"#, r#"/bogus/nonexistent-linker"#)
+ };
+
+ let foo = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [lib]
+ name = "foo"
+ "#)
+ .file("src/lib.rs", "")
+ .file(".cargo/config", &format!(r#"
+ [target.{target}]
+ ar = "{ar}"
+ linker = "{linker}"
+ "#, target = target, ar = config.0, linker = config.1))
+ .build();
+
+ let output = if cfg!(windows) {
+ (r#"C:\bogus\nonexistent-ar"#, r#"C:\bogus\nonexistent-linker"#)
+ } else {
+ (r#"/bogus/nonexistent-ar"#, r#"/bogus/nonexistent-linker"#)
+ };
+
+ assert_that(foo.cargo("build").arg("--verbose"),
+ execs().with_stderr(&format!("\
+[COMPILING] foo v0.0.1 ({url})
+[RUNNING] `rustc [..] -C ar={ar} -C linker={linker} [..]`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+", url = foo.url(), ar = output.0, linker = output.1)))
+}
+
+#[test]
+fn relative_tools() {
+ let target = rustc_host();
+
+ // Escaped as they appear within a TOML config file
+ let config = if cfg!(windows) {
+ (r#".\\nonexistent-ar"#, r#".\\tools\\nonexistent-linker"#)
+ } else {
+ (r#"./nonexistent-ar"#, r#"./tools/nonexistent-linker"#)
+ };
+
+ // Funky directory structure to test that relative tool paths are made absolute
+ // by reference to the `.cargo/..` directory and not to (for example) the CWD.
+ let origin = project("origin")
+ .file("foo/Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [lib]
+ name = "foo"
+ "#)
+ .file("foo/src/lib.rs", "")
+ .file(".cargo/config", &format!(r#"
+ [target.{target}]
+ ar = "{ar}"
+ linker = "{linker}"
+ "#, target = target, ar = config.0, linker = config.1))
+ .build();
+
+ let foo_path = origin.root().join("foo");
+ let foo_url = path2url(foo_path.clone());
+ let prefix = origin.root().into_os_string().into_string().unwrap();
+ let output = if cfg!(windows) {
+ (format!(r#"{}\.\nonexistent-ar"#, prefix),
+ format!(r#"{}\.\tools\nonexistent-linker"#, prefix))
+ } else {
+ (format!(r#"{}/./nonexistent-ar"#, prefix),
+ format!(r#"{}/./tools/nonexistent-linker"#, prefix))
+ };
+
+ assert_that(origin.cargo("build").cwd(foo_path).arg("--verbose"),
+ execs().with_stderr(&format!("\
+[COMPILING] foo v0.0.1 ({url})
+[RUNNING] `rustc [..] -C ar={ar} -C linker={linker} [..]`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+", url = foo_url, ar = output.0, linker = output.1)))
+}
+
+#[test]
+fn custom_runner() {
+ let target = rustc_host();
+
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .file("tests/test.rs", "")
+ .file("benches/bench.rs", "")
+ .file(".cargo/config", &format!(r#"
+ [target.{}]
+ runner = "nonexistent-runner -r"
+ "#, target))
+ .build();
+
+ assert_that(p.cargo("run").args(&["--", "--param"]),
+ execs().with_stderr_contains(&format!("\
+[COMPILING] foo v0.0.1 ({url})
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] `nonexistent-runner -r target[/]debug[/]foo[EXE] --param`
+", url = p.url())));
+
+ assert_that(p.cargo("test").args(&["--test", "test", "--verbose", "--", "--param"]),
+ execs().with_stderr_contains(&format!("\
+[COMPILING] foo v0.0.1 ({url})
+[RUNNING] `rustc [..]`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] `nonexistent-runner -r [..][/]target[/]debug[/]deps[/]test-[..][EXE] --param`
+", url = p.url())));
+
+ assert_that(p.cargo("bench").args(&["--bench", "bench", "--verbose", "--", "--param"]),
+ execs().with_stderr_contains(&format!("\
+[COMPILING] foo v0.0.1 ({url})
+[RUNNING] `rustc [..]`
+[RUNNING] `rustc [..]`
+[FINISHED] release [optimized] target(s) in [..]
+[RUNNING] `nonexistent-runner -r [..][/]target[/]release[/]deps[/]bench-[..][EXE] --param --bench`
+", url = p.url())));
+}
--- /dev/null
+use cargotest::support::{project, execs, main_file, basic_bin_manifest};
+use hamcrest::{assert_that};
+
+fn verify_project_success_output() -> String {
+ r#"{"success":"true"}"#.into()
+}
+
+#[test]
+fn cargo_verify_project_path_to_cargo_toml_relative() {
+ let p = project("foo")
+ .file("Cargo.toml", &basic_bin_manifest("foo"))
+ .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
+ .build();
+
+ assert_that(p.cargo("verify-project")
+ .arg("--manifest-path").arg("foo/Cargo.toml")
+ .cwd(p.root().parent().unwrap()),
+ execs().with_status(0)
+ .with_stdout(verify_project_success_output()));
+}
+
+#[test]
+fn cargo_verify_project_path_to_cargo_toml_absolute() {
+ let p = project("foo")
+ .file("Cargo.toml", &basic_bin_manifest("foo"))
+ .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
+ .build();
+
+ assert_that(p.cargo("verify-project")
+ .arg("--manifest-path").arg(p.root().join("Cargo.toml"))
+ .cwd(p.root().parent().unwrap()),
+ execs().with_status(0)
+ .with_stdout(verify_project_success_output()));
+}
+
+#[test]
+fn cargo_verify_project_cwd() {
+ let p = project("foo")
+ .file("Cargo.toml", &basic_bin_manifest("foo"))
+ .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
+ .build();
+
+ assert_that(p.cargo("verify-project")
+ .cwd(p.root()),
+ execs().with_status(0)
+ .with_stdout(verify_project_success_output()));
+}
--- /dev/null
+use cargo;
+use cargotest::support::{project, execs};
+use hamcrest::assert_that;
+
+#[test]
+fn simple() {
+ let p = project("foo").build();
+
+ assert_that(p.cargo("version"),
+ execs().with_status(0).with_stdout(&format!("{}\n",
+ cargo::version())));
+
+ assert_that(p.cargo("--version"),
+ execs().with_status(0).with_stdout(&format!("{}\n",
+ cargo::version())));
+
+}
+
+
+#[test]
+#[cfg_attr(target_os = "windows", ignore)]
+fn version_works_without_rustc() {
+ let p = project("foo").build();
+ assert_that(p.cargo("version").env("PATH", ""),
+ execs().with_status(0));
+}
+
+#[test]
+fn version_works_with_bad_config() {
+ let p = project("foo")
+ .file(".cargo/config", "this is not toml")
+ .build();
+ assert_that(p.cargo("version"),
+ execs().with_status(0));
+}
+
+#[test]
+fn version_works_with_bad_target_dir() {
+ let p = project("foo")
+ .file(".cargo/config", r#"
+ [build]
+ target-dir = 4
+ "#)
+ .build();
+ assert_that(p.cargo("version"),
+ execs().with_status(0));
+}
--- /dev/null
+use cargotest::support::{project, execs, Project};
+use cargotest::support::registry::Package;
+use hamcrest::assert_that;
+
+static WARNING1: &'static str = "Hello! I'm a warning. :)";
+static WARNING2: &'static str = "And one more!";
+
+fn make_lib(lib_src: &str) {
+ Package::new("foo", "0.0.1")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ authors = []
+ version = "0.0.1"
+ build = "build.rs"
+ "#)
+ .file("build.rs", &format!(r#"
+ fn main() {{
+ use std::io::Write;
+ println!("cargo:warning={{}}", "{}");
+ println!("hidden stdout");
+ write!(&mut ::std::io::stderr(), "hidden stderr");
+ println!("cargo:warning={{}}", "{}");
+ }}
+ "#, WARNING1, WARNING2))
+ .file("src/lib.rs", &format!("fn f() {{ {} }}", lib_src))
+ .publish();
+}
+
+fn make_upstream(main_src: &str) -> Project {
+ project("bar")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ foo = "*"
+ "#)
+ .file("src/main.rs", &format!("fn main() {{ {} }}", main_src))
+ .build()
+}
+
+#[test]
+fn no_warning_on_success() {
+ make_lib("");
+ let upstream = make_upstream("");
+ assert_that(upstream.cargo("build"),
+ execs().with_status(0)
+ .with_stderr("\
+[UPDATING] registry `[..]`
+[DOWNLOADING] foo v0.0.1 ([..])
+[COMPILING] foo v0.0.1
+[COMPILING] bar v0.0.1 ([..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+}
+
+#[test]
+fn no_warning_on_bin_failure() {
+ make_lib("");
+ let upstream = make_upstream("hi()");
+ assert_that(upstream.cargo("build"),
+ execs().with_status(101)
+ .with_stdout_does_not_contain("hidden stdout")
+ .with_stderr_does_not_contain("hidden stderr")
+ .with_stderr_does_not_contain(&format!("[WARNING] {}", WARNING1))
+ .with_stderr_does_not_contain(&format!("[WARNING] {}", WARNING2))
+ .with_stderr_contains("[UPDATING] registry `[..]`")
+ .with_stderr_contains("[DOWNLOADING] foo v0.0.1 ([..])")
+ .with_stderr_contains("[COMPILING] foo v0.0.1")
+ .with_stderr_contains("[COMPILING] bar v0.0.1 ([..])"));
+}
+
+#[test]
+fn warning_on_lib_failure() {
+ make_lib("err()");
+ let upstream = make_upstream("");
+ assert_that(upstream.cargo("build"),
+ execs().with_status(101)
+ .with_stdout_does_not_contain("hidden stdout")
+ .with_stderr_does_not_contain("hidden stderr")
+ .with_stderr_does_not_contain("[COMPILING] bar v0.0.1 ([..])")
+ .with_stderr_contains("[UPDATING] registry `[..]`")
+ .with_stderr_contains("[DOWNLOADING] foo v0.0.1 ([..])")
+ .with_stderr_contains("[COMPILING] foo v0.0.1")
+ .with_stderr_contains(&format!("[WARNING] {}", WARNING1))
+ .with_stderr_contains(&format!("[WARNING] {}", WARNING2)));
+}
--- /dev/null
+use std::env;
+use std::fs::{self, File};
+use std::io::{Read, Write};
+
+use cargotest::sleep_ms;
+use cargotest::support::{project, execs, git};
+use cargotest::support::registry::Package;
+use hamcrest::{assert_that, existing_file, existing_dir, is_not};
+
+#[test]
+fn simple_explicit() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+
+ [workspace]
+ members = ["bar"]
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .file("bar/Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+ workspace = ".."
+ "#)
+ .file("bar/src/main.rs", "fn main() {}");
+ let p = p.build();
+
+ assert_that(p.cargo("build"), execs().with_status(0));
+ assert_that(&p.bin("foo"), existing_file());
+ assert_that(&p.bin("bar"), is_not(existing_file()));
+
+ assert_that(p.cargo("build").cwd(p.root().join("bar")),
+ execs().with_status(0));
+ assert_that(&p.bin("foo"), existing_file());
+ assert_that(&p.bin("bar"), existing_file());
+
+ assert_that(&p.root().join("Cargo.lock"), existing_file());
+ assert_that(&p.root().join("bar/Cargo.lock"), is_not(existing_file()));
+}
+
+#[test]
+fn simple_explicit_default_members() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+
+ [workspace]
+ members = ["bar"]
+ default-members = ["bar"]
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .file("bar/Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+ workspace = ".."
+ "#)
+ .file("bar/src/main.rs", "fn main() {}");
+ let p = p.build();
+
+ assert_that(p.cargo("build"), execs().with_status(0));
+ assert_that(&p.bin("bar"), existing_file());
+ assert_that(&p.bin("foo"), is_not(existing_file()));
+}
+
+#[test]
+fn inferred_root() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+
+ [workspace]
+ members = ["bar"]
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .file("bar/Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("bar/src/main.rs", "fn main() {}");
+ let p = p.build();
+
+ assert_that(p.cargo("build"), execs().with_status(0));
+ assert_that(&p.bin("foo"), existing_file());
+ assert_that(&p.bin("bar"), is_not(existing_file()));
+
+ assert_that(p.cargo("build").cwd(p.root().join("bar")),
+ execs().with_status(0));
+ assert_that(&p.bin("foo"), existing_file());
+ assert_that(&p.bin("bar"), existing_file());
+
+ assert_that(&p.root().join("Cargo.lock"), existing_file());
+ assert_that(&p.root().join("bar/Cargo.lock"), is_not(existing_file()));
+}
+
+#[test]
+fn inferred_path_dep() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+
+ [dependencies]
+ bar = { path = "bar" }
+
+ [workspace]
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .file("bar/Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("bar/src/main.rs", "fn main() {}")
+ .file("bar/src/lib.rs", "");
+ let p = p.build();
+
+ assert_that(p.cargo("build"), execs().with_status(0));
+ assert_that(&p.bin("foo"), existing_file());
+ assert_that(&p.bin("bar"), is_not(existing_file()));
+
+ assert_that(p.cargo("build").cwd(p.root().join("bar")),
+ execs().with_status(0));
+ assert_that(&p.bin("foo"), existing_file());
+ assert_that(&p.bin("bar"), existing_file());
+
+ assert_that(&p.root().join("Cargo.lock"), existing_file());
+ assert_that(&p.root().join("bar/Cargo.lock"), is_not(existing_file()));
+}
+
+#[test]
+fn transitive_path_dep() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+
+ [dependencies]
+ bar = { path = "bar" }
+
+ [workspace]
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .file("bar/Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+
+ [dependencies]
+ baz = { path = "../baz" }
+ "#)
+ .file("bar/src/main.rs", "fn main() {}")
+ .file("bar/src/lib.rs", "")
+ .file("baz/Cargo.toml", r#"
+ [project]
+ name = "baz"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("baz/src/main.rs", "fn main() {}")
+ .file("baz/src/lib.rs", "");
+ let p = p.build();
+
+ assert_that(p.cargo("build"), execs().with_status(0));
+ assert_that(&p.bin("foo"), existing_file());
+ assert_that(&p.bin("bar"), is_not(existing_file()));
+ assert_that(&p.bin("baz"), is_not(existing_file()));
+
+ assert_that(p.cargo("build").cwd(p.root().join("bar")),
+ execs().with_status(0));
+ assert_that(&p.bin("foo"), existing_file());
+ assert_that(&p.bin("bar"), existing_file());
+ assert_that(&p.bin("baz"), is_not(existing_file()));
+
+ assert_that(p.cargo("build").cwd(p.root().join("baz")),
+ execs().with_status(0));
+ assert_that(&p.bin("foo"), existing_file());
+ assert_that(&p.bin("bar"), existing_file());
+ assert_that(&p.bin("baz"), existing_file());
+
+ assert_that(&p.root().join("Cargo.lock"), existing_file());
+ assert_that(&p.root().join("bar/Cargo.lock"), is_not(existing_file()));
+ assert_that(&p.root().join("baz/Cargo.lock"), is_not(existing_file()));
+}
+
+#[test]
+fn parent_pointer_works() {
+ let p = project("foo")
+ .file("foo/Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+
+ [dependencies]
+ bar = { path = "../bar" }
+
+ [workspace]
+ "#)
+ .file("foo/src/main.rs", "fn main() {}")
+ .file("bar/Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+ workspace = "../foo"
+ "#)
+ .file("bar/src/main.rs", "fn main() {}")
+ .file("bar/src/lib.rs", "");
+ let p = p.build();
+
+ assert_that(p.cargo("build").cwd(p.root().join("foo")),
+ execs().with_status(0));
+ assert_that(p.cargo("build").cwd(p.root().join("bar")),
+ execs().with_status(0));
+ assert_that(&p.root().join("foo/Cargo.lock"), existing_file());
+ assert_that(&p.root().join("bar/Cargo.lock"), is_not(existing_file()));
+}
+
+#[test]
+fn same_names_in_workspace() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+
+ [workspace]
+ members = ["bar"]
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .file("bar/Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ workspace = ".."
+ "#)
+ .file("bar/src/main.rs", "fn main() {}");
+ let p = p.build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101)
+ .with_stderr("\
+error: two packages named `foo` in this workspace:
+- [..]Cargo.toml
+- [..]Cargo.toml
+"));
+}
+
+#[test]
+fn parent_doesnt_point_to_child() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+
+ [workspace]
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .file("bar/Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("bar/src/main.rs", "fn main() {}");
+ let p = p.build();
+
+ assert_that(p.cargo("build").cwd(p.root().join("bar")),
+ execs().with_status(101)
+ .with_stderr("\
+error: current package believes it's in a workspace when it's not:
+current: [..]Cargo.toml
+workspace: [..]Cargo.toml
+
+this may be fixable [..]
+"));
+}
+
+#[test]
+fn invalid_parent_pointer() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ workspace = "foo"
+ "#)
+ .file("src/main.rs", "fn main() {}");
+ let p = p.build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101)
+ .with_stderr("\
+error: failed to read `[..]Cargo.toml`
+
+Caused by:
+ [..]
+"));
+}
+
+#[test]
+fn invalid_members() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+
+ [workspace]
+ members = ["foo"]
+ "#)
+ .file("src/main.rs", "fn main() {}");
+ let p = p.build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101)
+ .with_stderr("\
+error: failed to read `[..]Cargo.toml`
+
+Caused by:
+ [..]
+"));
+}
+
+#[test]
+fn bare_workspace_ok() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+
+ [workspace]
+ "#)
+ .file("src/main.rs", "fn main() {}");
+ let p = p.build();
+
+ assert_that(p.cargo("build"), execs().with_status(0));
+}
+
+#[test]
+fn two_roots() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+
+ [workspace]
+ members = ["bar"]
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .file("bar/Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+
+ [workspace]
+ members = [".."]
+ "#)
+ .file("bar/src/main.rs", "fn main() {}");
+ let p = p.build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101)
+ .with_stderr("\
+error: multiple workspace roots found in the same workspace:
+ [..]
+ [..]
+"));
+}
+
+#[test]
+fn workspace_isnt_root() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ workspace = "bar"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .file("bar/Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("bar/src/main.rs", "fn main() {}");
+ let p = p.build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101)
+ .with_stderr("\
+error: root of a workspace inferred but wasn't a root: [..]
+"));
+}
+
+#[test]
+fn dangling_member() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+
+ [workspace]
+ members = ["bar"]
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .file("bar/Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+ workspace = "../baz"
+ "#)
+ .file("bar/src/main.rs", "fn main() {}")
+ .file("baz/Cargo.toml", r#"
+ [project]
+ name = "baz"
+ version = "0.1.0"
+ authors = []
+ workspace = "../baz"
+ "#)
+ .file("baz/src/main.rs", "fn main() {}");
+ let p = p.build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101)
+ .with_stderr("\
+error: package `[..]` is a member of the wrong workspace
+expected: [..]
+actual: [..]
+"));
+}
+
+#[test]
+fn cycle() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ workspace = "bar"
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .file("bar/Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+ workspace = ".."
+ "#)
+ .file("bar/src/main.rs", "fn main() {}");
+ let p = p.build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101));
+}
+
+#[test]
+fn share_dependencies() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+
+ [dependencies]
+ dep1 = "0.1"
+
+ [workspace]
+ members = ["bar"]
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .file("bar/Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+
+ [dependencies]
+ dep1 = "< 0.1.5"
+ "#)
+ .file("bar/src/main.rs", "fn main() {}");
+ let p = p.build();
+
+ Package::new("dep1", "0.1.3").publish();
+ Package::new("dep1", "0.1.8").publish();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0)
+ .with_stderr("\
+[UPDATING] registry `[..]`
+[DOWNLOADING] dep1 v0.1.3 ([..])
+[COMPILING] dep1 v0.1.3
+[COMPILING] foo v0.1.0 ([..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+}
+
+#[test]
+fn fetch_fetches_all() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+
+ [workspace]
+ members = ["bar"]
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .file("bar/Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+
+ [dependencies]
+ dep1 = "*"
+ "#)
+ .file("bar/src/main.rs", "fn main() {}");
+ let p = p.build();
+
+ Package::new("dep1", "0.1.3").publish();
+
+ assert_that(p.cargo("fetch"),
+ execs().with_status(0)
+ .with_stderr("\
+[UPDATING] registry `[..]`
+[DOWNLOADING] dep1 v0.1.3 ([..])
+"));
+}
+
+#[test]
+fn lock_works_for_everyone() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+
+ [dependencies]
+ dep2 = "0.1"
+
+ [workspace]
+ members = ["bar"]
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .file("bar/Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+
+ [dependencies]
+ dep1 = "0.1"
+ "#)
+ .file("bar/src/main.rs", "fn main() {}");
+ let p = p.build();
+
+ Package::new("dep1", "0.1.0").publish();
+ Package::new("dep2", "0.1.0").publish();
+
+ assert_that(p.cargo("generate-lockfile"),
+ execs().with_status(0)
+ .with_stderr("\
+[UPDATING] registry `[..]`
+"));
+
+ Package::new("dep1", "0.1.1").publish();
+ Package::new("dep2", "0.1.1").publish();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0)
+ .with_stderr("\
+[DOWNLOADING] dep2 v0.1.0 ([..])
+[COMPILING] dep2 v0.1.0
+[COMPILING] foo v0.1.0 ([..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+
+ assert_that(p.cargo("build").cwd(p.root().join("bar")),
+ execs().with_status(0)
+ .with_stderr("\
+[DOWNLOADING] dep1 v0.1.0 ([..])
+[COMPILING] dep1 v0.1.0
+[COMPILING] bar v0.1.0 ([..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+}
+
+#[test]
+fn virtual_works() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [workspace]
+ members = ["bar"]
+ "#)
+ .file("bar/Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("bar/src/main.rs", "fn main() {}");
+ let p = p.build();
+ assert_that(p.cargo("build").cwd(p.root().join("bar")),
+ execs().with_status(0));
+ assert_that(&p.root().join("Cargo.lock"), existing_file());
+ assert_that(&p.bin("bar"), existing_file());
+ assert_that(&p.root().join("bar/Cargo.lock"), is_not(existing_file()));
+}
+
+#[test]
+fn explicit_package_argument_works_with_virtual_manifest() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [workspace]
+ members = ["bar"]
+ "#)
+ .file("bar/Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("bar/src/main.rs", "fn main() {}");
+ let p = p.build();
+ assert_that(p.cargo("build").cwd(p.root()).args(&["--package", "bar"]),
+ execs().with_status(0));
+ assert_that(&p.root().join("Cargo.lock"), existing_file());
+ assert_that(&p.bin("bar"), existing_file());
+ assert_that(&p.root().join("bar/Cargo.lock"), is_not(existing_file()));
+}
+
+#[test]
+fn virtual_misconfigure() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [workspace]
+ "#)
+ .file("bar/Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("bar/src/main.rs", "fn main() {}");
+ let p = p.build();
+ assert_that(p.cargo("build").cwd(p.root().join("bar")),
+ execs().with_status(101)
+ .with_stderr("\
+error: current package believes it's in a workspace when it's not:
+current: [..]bar[..]Cargo.toml
+workspace: [..]Cargo.toml
+
+this may be fixable by adding `bar` to the `workspace.members` array of the \
+manifest located at: [..]
+"));
+}
+
+#[test]
+fn virtual_build_all_implied() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [workspace]
+ members = ["bar"]
+ "#)
+ .file("bar/Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("bar/src/main.rs", "fn main() {}");
+ let p = p.build();
+ assert_that(p.cargo("build"),
+ execs().with_status(0));
+}
+
+#[test]
+fn virtual_default_members() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [workspace]
+ members = ["bar", "baz"]
+ default-members = ["bar"]
+ "#)
+ .file("bar/Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("baz/Cargo.toml", r#"
+ [project]
+ name = "baz"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("bar/src/main.rs", "fn main() {}")
+ .file("baz/src/main.rs", "fn main() {}");
+ let p = p.build();
+ assert_that(p.cargo("build"),
+ execs().with_status(0));
+ assert_that(&p.bin("bar"), existing_file());
+ assert_that(&p.bin("baz"), is_not(existing_file()));
+}
+
+#[test]
+fn virtual_default_member_is_not_a_member() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [workspace]
+ members = ["bar"]
+ default-members = ["something-else"]
+ "#)
+ .file("bar/Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("bar/src/main.rs", "fn main() {}");
+ let p = p.build();
+ assert_that(p.cargo("build"),
+ execs().with_status(101)
+ .with_stderr("\
+error: package `[..]something-else` is listed in workspace’s default-members \
+but is not a member.
+"));
+}
+
+#[test]
+fn virtual_build_no_members() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [workspace]
+ "#);
+ let p = p.build();
+ assert_that(p.cargo("build"),
+ execs().with_status(101)
+ .with_stderr("\
+error: manifest path `[..]` contains no package: The manifest is virtual, \
+and the workspace has no members.
+"));
+}
+
+#[test]
+fn include_virtual() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+ [workspace]
+ members = ["bar"]
+ "#)
+ .file("src/main.rs", "")
+ .file("bar/Cargo.toml", r#"
+ [workspace]
+ "#);
+ let p = p.build();
+ assert_that(p.cargo("build"),
+ execs().with_status(101)
+ .with_stderr("\
+error: multiple workspace roots found in the same workspace:
+ [..]
+ [..]
+"));
+}
+
+#[test]
+fn members_include_path_deps() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+
+ [workspace]
+ members = ["p1"]
+
+ [dependencies]
+ p3 = { path = "p3" }
+ "#)
+ .file("src/lib.rs", "")
+ .file("p1/Cargo.toml", r#"
+ [project]
+ name = "p1"
+ version = "0.1.0"
+ authors = []
+
+ [dependencies]
+ p2 = { path = "../p2" }
+ "#)
+ .file("p1/src/lib.rs", "")
+ .file("p2/Cargo.toml", r#"
+ [project]
+ name = "p2"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("p2/src/lib.rs", "")
+ .file("p3/Cargo.toml", r#"
+ [project]
+ name = "p3"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("p3/src/lib.rs", "");
+ let p = p.build();
+
+ assert_that(p.cargo("build").cwd(p.root().join("p1")),
+ execs().with_status(0));
+ assert_that(p.cargo("build").cwd(p.root().join("p2")),
+ execs().with_status(0));
+ assert_that(p.cargo("build").cwd(p.root().join("p3")),
+ execs().with_status(0));
+ assert_that(p.cargo("build"),
+ execs().with_status(0));
+
+ assert_that(&p.root().join("target"), existing_dir());
+ assert_that(&p.root().join("p1/target"), is_not(existing_dir()));
+ assert_that(&p.root().join("p2/target"), is_not(existing_dir()));
+ assert_that(&p.root().join("p3/target"), is_not(existing_dir()));
+}
+
+#[test]
+fn new_warns_you_this_will_not_work() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+
+ [workspace]
+ "#)
+ .file("src/lib.rs", "");
+ let p = p.build();
+
+ assert_that(p.cargo("new").arg("--lib").arg("bar").env("USER", "foo"),
+ execs().with_status(0)
+ .with_stderr("\
+warning: compiling this new crate may not work due to invalid workspace \
+configuration
+
+current package believes it's in a workspace when it's not:
+current: [..]
+workspace: [..]
+
+this may be fixable by ensuring that this crate is depended on by the workspace \
+root: [..]
+[CREATED] library `bar` project
+"));
+}
+
+#[test]
+fn lock_doesnt_change_depending_on_crate() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+
+ [workspace]
+ members = ['baz']
+
+ [dependencies]
+ foo = "*"
+ "#)
+ .file("src/lib.rs", "")
+ .file("baz/Cargo.toml", r#"
+ [project]
+ name = "baz"
+ version = "0.1.0"
+ authors = []
+
+ [dependencies]
+ bar = "*"
+ "#)
+ .file("baz/src/lib.rs", "");
+ let p = p.build();
+
+ Package::new("foo", "1.0.0").publish();
+ Package::new("bar", "1.0.0").publish();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0));
+
+ let mut lockfile = String::new();
+ t!(t!(File::open(p.root().join("Cargo.lock"))).read_to_string(&mut lockfile));
+
+ assert_that(p.cargo("build").cwd(p.root().join("baz")),
+ execs().with_status(0));
+
+ let mut lockfile2 = String::new();
+ t!(t!(File::open(p.root().join("Cargo.lock"))).read_to_string(&mut lockfile2));
+
+ assert_eq!(lockfile, lockfile2);
+}
+
+#[test]
+fn rebuild_please() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [workspace]
+ members = ['lib', 'bin']
+ "#)
+ .file("lib/Cargo.toml", r#"
+ [package]
+ name = "lib"
+ version = "0.1.0"
+ "#)
+ .file("lib/src/lib.rs", r#"
+ pub fn foo() -> u32 { 0 }
+ "#)
+ .file("bin/Cargo.toml", r#"
+ [package]
+ name = "bin"
+ version = "0.1.0"
+
+ [dependencies]
+ lib = { path = "../lib" }
+ "#)
+ .file("bin/src/main.rs", r#"
+ extern crate lib;
+
+ fn main() {
+ assert_eq!(lib::foo(), 0);
+ }
+ "#);
+ let p = p.build();
+
+ assert_that(p.cargo("run").cwd(p.root().join("bin")),
+ execs().with_status(0));
+
+ sleep_ms(1000);
+
+ t!(t!(File::create(p.root().join("lib/src/lib.rs"))).write_all(br#"
+ pub fn foo() -> u32 { 1 }
+ "#));
+
+ assert_that(p.cargo("build").cwd(p.root().join("lib")),
+ execs().with_status(0));
+
+ assert_that(p.cargo("run").cwd(p.root().join("bin")),
+ execs().with_status(101));
+}
+
+#[test]
+fn workspace_in_git() {
+ let git_project = git::new("dep1", |project| {
+ project
+ .file("Cargo.toml", r#"
+ [workspace]
+ members = ["foo"]
+ "#)
+ .file("foo/Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ "#)
+ .file("foo/src/lib.rs", "")
+ }).unwrap();
+ let p = project("foo")
+ .file("Cargo.toml", &format!(r#"
+ [package]
+ name = "lib"
+ version = "0.1.0"
+
+ [dependencies.foo]
+ git = '{}'
+ "#, git_project.url()))
+ .file("src/lib.rs", r#"
+ pub fn foo() -> u32 { 0 }
+ "#);
+ let p = p.build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0));
+}
+
+
+#[test]
+fn lockfile_can_specify_nonexistant_members() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [workspace]
+ members = ["a"]
+ "#)
+ .file("a/Cargo.toml", r#"
+ [project]
+ name = "a"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("a/src/main.rs", "fn main() {}")
+ .file("Cargo.lock", r#"
+ [[package]]
+ name = "a"
+ version = "0.1.0"
+
+ [[package]]
+ name = "b"
+ version = "0.1.0"
+ "#);
+
+ let p = p.build();
+
+ assert_that(p.cargo("build").cwd(p.root().join("a")), execs().with_status(0));
+}
+
+#[test]
+fn you_cannot_generate_lockfile_for_empty_workspaces() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [workspace]
+ "#)
+ .file("bar/Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("bar/src/main.rs", "fn main() {}");
+ let p = p.build();
+
+ assert_that(p.cargo("update"),
+ execs().with_status(101)
+ .with_stderr("\
+error: you can't generate a lockfile for an empty workspace.
+"));
+}
+
+#[test]
+fn workspace_with_transitive_dev_deps() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+ authors = ["mbrubeck@example.com"]
+
+ [dependencies.bar]
+ path = "bar"
+
+ [workspace]
+ "#)
+ .file("src/main.rs", r#"fn main() {}"#)
+ .file("bar/Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.5.0"
+ authors = ["mbrubeck@example.com"]
+
+ [dev-dependencies.baz]
+ path = "../baz"
+ "#)
+ .file("bar/src/lib.rs", r#"
+ pub fn init() {}
+
+ #[cfg(test)]
+
+ #[test]
+ fn test() {
+ extern crate baz;
+ baz::do_stuff();
+ }
+ "#)
+ .file("baz/Cargo.toml", r#"
+ [project]
+ name = "baz"
+ version = "0.5.0"
+ authors = ["mbrubeck@example.com"]
+ "#)
+ .file("baz/src/lib.rs", r#"pub fn do_stuff() {}"#);
+ let p = p.build();
+
+ assert_that(p.cargo("test").args(&["-p", "bar"]),
+ execs().with_status(0));
+}
+
+#[test]
+fn error_if_parent_cargo_toml_is_invalid() {
+ let p = project("foo")
+ .file("Cargo.toml", "Totally not a TOML file")
+ .file("bar/Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("bar/src/main.rs", "fn main() {}");
+ let p = p.build();
+
+ assert_that(p.cargo("build").cwd(p.root().join("bar")),
+ execs().with_status(101)
+ .with_stderr_contains("\
+[ERROR] failed to parse manifest at `[..]`"));
+}
+
+#[test]
+fn relative_path_for_member_works() {
+ let p = project("foo")
+ .file("foo/Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+
+ [workspace]
+ members = ["../bar"]
+ "#)
+ .file("foo/src/main.rs", "fn main() {}")
+ .file("bar/Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+ workspace = "../foo"
+ "#)
+ .file("bar/src/main.rs", "fn main() {}");
+ let p = p.build();
+
+ assert_that(p.cargo("build").cwd(p.root().join("foo")), execs().with_status(0));
+ assert_that(p.cargo("build").cwd(p.root().join("bar")), execs().with_status(0));
+}
+
+#[test]
+fn relative_path_for_root_works() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+
+ [workspace]
+
+ [dependencies]
+ subproj = { path = "./subproj" }
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .file("subproj/Cargo.toml", r#"
+ [project]
+ name = "subproj"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("subproj/src/main.rs", "fn main() {}");
+ let p = p.build();
+
+ assert_that(p.cargo("build").cwd(p.root())
+ .arg("--manifest-path").arg("./Cargo.toml"),
+ execs().with_status(0));
+
+ assert_that(p.cargo("build").cwd(p.root().join("subproj"))
+ .arg("--manifest-path").arg("../Cargo.toml"),
+ execs().with_status(0));
+}
+
+#[test]
+fn path_dep_outside_workspace_is_not_member() {
+ let p = project("foo")
+ .file("ws/Cargo.toml", r#"
+ [project]
+ name = "ws"
+ version = "0.1.0"
+ authors = []
+
+ [dependencies]
+ foo = { path = "../foo" }
+
+ [workspace]
+ "#)
+ .file("ws/src/lib.rs", r"extern crate foo;")
+ .file("foo/Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("foo/src/lib.rs", "");
+ let p = p.build();
+
+ assert_that(p.cargo("build").cwd(p.root().join("ws")),
+ execs().with_status(0));
+}
+
+#[test]
+fn test_in_and_out_of_workspace() {
+ let p = project("foo")
+ .file("ws/Cargo.toml", r#"
+ [project]
+ name = "ws"
+ version = "0.1.0"
+ authors = []
+
+ [dependencies]
+ foo = { path = "../foo" }
+
+ [workspace]
+ members = [ "../bar" ]
+ "#)
+ .file("ws/src/lib.rs", r"extern crate foo; pub fn f() { foo::f() }")
+ .file("foo/Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+
+ [dependencies]
+ bar = { path = "../bar" }
+ "#)
+ .file("foo/src/lib.rs", "extern crate bar; pub fn f() { bar::f() }")
+ .file("bar/Cargo.toml", r#"
+ [project]
+ workspace = "../ws"
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("bar/src/lib.rs", "pub fn f() { }");
+ let p = p.build();
+
+ assert_that(p.cargo("build").cwd(p.root().join("ws")),
+ execs().with_status(0));
+
+ assert_that(&p.root().join("ws/Cargo.lock"), existing_file());
+ assert_that(&p.root().join("ws/target"), existing_dir());
+ assert_that(&p.root().join("foo/Cargo.lock"), is_not(existing_file()));
+ assert_that(&p.root().join("foo/target"), is_not(existing_dir()));
+ assert_that(&p.root().join("bar/Cargo.lock"), is_not(existing_file()));
+ assert_that(&p.root().join("bar/target"), is_not(existing_dir()));
+
+ assert_that(p.cargo("build").cwd(p.root().join("foo")),
+ execs().with_status(0));
+ assert_that(&p.root().join("foo/Cargo.lock"), existing_file());
+ assert_that(&p.root().join("foo/target"), existing_dir());
+ assert_that(&p.root().join("bar/Cargo.lock"), is_not(existing_file()));
+ assert_that(&p.root().join("bar/target"), is_not(existing_dir()));
+}
+
+#[test]
+fn test_path_dependency_under_member() {
+ let p = project("foo")
+ .file("ws/Cargo.toml", r#"
+ [project]
+ name = "ws"
+ version = "0.1.0"
+ authors = []
+
+ [dependencies]
+ foo = { path = "../foo" }
+
+ [workspace]
+ "#)
+ .file("ws/src/lib.rs", r"extern crate foo; pub fn f() { foo::f() }")
+ .file("foo/Cargo.toml", r#"
+ [project]
+ workspace = "../ws"
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+
+ [dependencies]
+ bar = { path = "./bar" }
+ "#)
+ .file("foo/src/lib.rs", "extern crate bar; pub fn f() { bar::f() }")
+ .file("foo/bar/Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("foo/bar/src/lib.rs", "pub fn f() { }");
+ let p = p.build();
+
+ assert_that(p.cargo("build").cwd(p.root().join("ws")),
+ execs().with_status(0));
+
+ assert_that(&p.root().join("foo/bar/Cargo.lock"), is_not(existing_file()));
+ assert_that(&p.root().join("foo/bar/target"), is_not(existing_dir()));
+
+ assert_that(p.cargo("build").cwd(p.root().join("foo/bar")),
+ execs().with_status(0));
+
+ assert_that(&p.root().join("foo/bar/Cargo.lock"), is_not(existing_file()));
+ assert_that(&p.root().join("foo/bar/target"), is_not(existing_dir()));
+}
+
+#[test]
+fn excluded_simple() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "ws"
+ version = "0.1.0"
+ authors = []
+
+ [workspace]
+ exclude = ["foo"]
+ "#)
+ .file("src/lib.rs", "")
+ .file("foo/Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("foo/src/lib.rs", "");
+ let p = p.build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0));
+ assert_that(&p.root().join("target"), existing_dir());
+ assert_that(p.cargo("build").cwd(p.root().join("foo")),
+ execs().with_status(0));
+ assert_that(&p.root().join("foo/target"), existing_dir());
+}
+
+#[test]
+fn exclude_members_preferred() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "ws"
+ version = "0.1.0"
+ authors = []
+
+ [workspace]
+ members = ["foo/bar"]
+ exclude = ["foo"]
+ "#)
+ .file("src/lib.rs", "")
+ .file("foo/Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("foo/src/lib.rs", "")
+ .file("foo/bar/Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("foo/bar/src/lib.rs", "");
+ let p = p.build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0));
+ assert_that(&p.root().join("target"), existing_dir());
+ assert_that(p.cargo("build").cwd(p.root().join("foo")),
+ execs().with_status(0));
+ assert_that(&p.root().join("foo/target"), existing_dir());
+ assert_that(p.cargo("build").cwd(p.root().join("foo/bar")),
+ execs().with_status(0));
+ assert_that(&p.root().join("foo/bar/target"), is_not(existing_dir()));
+}
+
+#[test]
+fn exclude_but_also_depend() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "ws"
+ version = "0.1.0"
+ authors = []
+
+ [dependencies]
+ bar = { path = "foo/bar" }
+
+ [workspace]
+ exclude = ["foo"]
+ "#)
+ .file("src/lib.rs", "")
+ .file("foo/Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("foo/src/lib.rs", "")
+ .file("foo/bar/Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("foo/bar/src/lib.rs", "");
+ let p = p.build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(0));
+ assert_that(&p.root().join("target"), existing_dir());
+ assert_that(p.cargo("build").cwd(p.root().join("foo")),
+ execs().with_status(0));
+ assert_that(&p.root().join("foo/target"), existing_dir());
+ assert_that(p.cargo("build").cwd(p.root().join("foo/bar")),
+ execs().with_status(0));
+ assert_that(&p.root().join("foo/bar/target"), existing_dir());
+}
+
+#[test]
+fn glob_syntax() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+
+ [workspace]
+ members = ["crates/*"]
+ exclude = ["crates/qux"]
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .file("crates/bar/Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+ workspace = "../.."
+ "#)
+ .file("crates/bar/src/main.rs", "fn main() {}")
+ .file("crates/baz/Cargo.toml", r#"
+ [project]
+ name = "baz"
+ version = "0.1.0"
+ authors = []
+ workspace = "../.."
+ "#)
+ .file("crates/baz/src/main.rs", "fn main() {}")
+ .file("crates/qux/Cargo.toml", r#"
+ [project]
+ name = "qux"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("crates/qux/src/main.rs", "fn main() {}");
+ let p = p.build();
+
+ assert_that(p.cargo("build"), execs().with_status(0));
+ assert_that(&p.bin("foo"), existing_file());
+ assert_that(&p.bin("bar"), is_not(existing_file()));
+ assert_that(&p.bin("baz"), is_not(existing_file()));
+
+ assert_that(p.cargo("build").cwd(p.root().join("crates/bar")),
+ execs().with_status(0));
+ assert_that(&p.bin("foo"), existing_file());
+ assert_that(&p.bin("bar"), existing_file());
+
+ assert_that(p.cargo("build").cwd(p.root().join("crates/baz")),
+ execs().with_status(0));
+ assert_that(&p.bin("foo"), existing_file());
+ assert_that(&p.bin("baz"), existing_file());
+
+ assert_that(p.cargo("build").cwd(p.root().join("crates/qux")),
+ execs().with_status(0));
+ assert_that(&p.bin("qux"), is_not(existing_file()));
+
+ assert_that(&p.root().join("Cargo.lock"), existing_file());
+ assert_that(&p.root().join("crates/bar/Cargo.lock"), is_not(existing_file()));
+ assert_that(&p.root().join("crates/baz/Cargo.lock"), is_not(existing_file()));
+ assert_that(&p.root().join("crates/qux/Cargo.lock"), existing_file());
+}
+
+/*FIXME: This fails because of how workspace.exclude and workspace.members are working.
+#[test]
+fn glob_syntax_2() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+
+ [workspace]
+ members = ["crates/b*"]
+ exclude = ["crates/q*"]
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .file("crates/bar/Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+ workspace = "../.."
+ "#)
+ .file("crates/bar/src/main.rs", "fn main() {}")
+ .file("crates/baz/Cargo.toml", r#"
+ [project]
+ name = "baz"
+ version = "0.1.0"
+ authors = []
+ workspace = "../.."
+ "#)
+ .file("crates/baz/src/main.rs", "fn main() {}")
+ .file("crates/qux/Cargo.toml", r#"
+ [project]
+ name = "qux"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("crates/qux/src/main.rs", "fn main() {}");
+ p.build();
+
+ assert_that(p.cargo("build"), execs().with_status(0));
+ assert_that(&p.bin("foo"), existing_file());
+ assert_that(&p.bin("bar"), is_not(existing_file()));
+ assert_that(&p.bin("baz"), is_not(existing_file()));
+
+ assert_that(p.cargo("build").cwd(p.root().join("crates/bar")),
+ execs().with_status(0));
+ assert_that(&p.bin("foo"), existing_file());
+ assert_that(&p.bin("bar"), existing_file());
+
+ assert_that(p.cargo("build").cwd(p.root().join("crates/baz")),
+ execs().with_status(0));
+ assert_that(&p.bin("foo"), existing_file());
+ assert_that(&p.bin("baz"), existing_file());
+
+ assert_that(p.cargo("build").cwd(p.root().join("crates/qux")),
+ execs().with_status(0));
+ assert_that(&p.bin("qux"), is_not(existing_file()));
+
+ assert_that(&p.root().join("Cargo.lock"), existing_file());
+ assert_that(&p.root().join("crates/bar/Cargo.lock"), is_not(existing_file()));
+ assert_that(&p.root().join("crates/baz/Cargo.lock"), is_not(existing_file()));
+ assert_that(&p.root().join("crates/qux/Cargo.lock"), existing_file());
+}
+*/
+
+#[test]
+fn glob_syntax_invalid_members() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+
+ [workspace]
+ members = ["crates/*"]
+ "#)
+ .file("src/main.rs", "fn main() {}")
+ .file("crates/bar/src/main.rs", "fn main() {}");
+ let p = p.build();
+
+ assert_that(p.cargo("build"),
+ execs().with_status(101)
+ .with_stderr("\
+error: failed to read `[..]Cargo.toml`
+
+Caused by:
+ [..]
+"));
+}
+
+/// This is a freshness test for feature use with workspaces
+///
+/// feat_lib is used by caller1 and caller2, but with different features enabled.
+/// This test ensures that alternating building caller1, caller2 doesn't force
+/// recompile of feat_lib.
+///
+/// Ideally once we solve https://github.com/rust-lang/cargo/issues/3620, then
+/// a single cargo build at the top level will be enough.
+#[test]
+fn dep_used_with_separate_features() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [workspace]
+ members = ["feat_lib", "caller1", "caller2"]
+ "#)
+ .file("feat_lib/Cargo.toml", r#"
+ [project]
+ name = "feat_lib"
+ version = "0.1.0"
+ authors = []
+
+ [features]
+ myfeature = []
+ "#)
+ .file("feat_lib/src/lib.rs", "")
+ .file("caller1/Cargo.toml", r#"
+ [project]
+ name = "caller1"
+ version = "0.1.0"
+ authors = []
+
+ [dependencies]
+ feat_lib = { path = "../feat_lib" }
+ "#)
+ .file("caller1/src/main.rs", "fn main() {}")
+ .file("caller1/src/lib.rs", "")
+ .file("caller2/Cargo.toml", r#"
+ [project]
+ name = "caller2"
+ version = "0.1.0"
+ authors = []
+
+ [dependencies]
+ feat_lib = { path = "../feat_lib", features = ["myfeature"] }
+ caller1 = { path = "../caller1" }
+ "#)
+ .file("caller2/src/main.rs", "fn main() {}")
+ .file("caller2/src/lib.rs", "");
+ let p = p.build();
+
+ // Build the entire workspace
+ assert_that(p.cargo("build").arg("--all"),
+ execs().with_status(0)
+ .with_stderr("\
+[..]Compiling feat_lib v0.1.0 ([..])
+[..]Compiling caller1 v0.1.0 ([..])
+[..]Compiling caller2 v0.1.0 ([..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+ assert_that(&p.bin("caller1"), existing_file());
+ assert_that(&p.bin("caller2"), existing_file());
+
+
+ // Build caller1. should build the dep library. Because the features
+ // are different than the full workspace, it rebuilds.
+ // Ideally once we solve https://github.com/rust-lang/cargo/issues/3620, then
+ // a single cargo build at the top level will be enough.
+ assert_that(p.cargo("build").cwd(p.root().join("caller1")),
+ execs().with_status(0)
+ .with_stderr("\
+[..]Compiling feat_lib v0.1.0 ([..])
+[..]Compiling caller1 v0.1.0 ([..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+
+ // Alternate building caller2/caller1 a few times, just to make sure
+ // features are being built separately. Should not rebuild anything
+ assert_that(p.cargo("build").cwd(p.root().join("caller2")),
+ execs().with_status(0)
+ .with_stderr("\
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+ assert_that(p.cargo("build").cwd(p.root().join("caller1")),
+ execs().with_status(0)
+ .with_stderr("\
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+ assert_that(p.cargo("build").cwd(p.root().join("caller2")),
+ execs().with_status(0)
+ .with_stderr("\
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+"));
+}
+
+#[test]
+fn dont_recurse_out_of_cargo_home() {
+ let git_project = git::new("dep", |project| {
+ project
+ .file("Cargo.toml", r#"
+ [package]
+ name = "dep"
+ version = "0.1.0"
+ "#)
+ .file("src/lib.rs", "")
+ .file("build.rs", r#"
+ use std::env;
+ use std::path::Path;
+ use std::process::{self, Command};
+
+ fn main() {
+ let cargo = env::var_os("CARGO").unwrap();
+ let cargo_manifest_dir = env::var_os("CARGO_MANIFEST_DIR").unwrap();
+ let output = Command::new(cargo)
+ .args(&["metadata", "--format-version", "1", "--manifest-path"])
+ .arg(&Path::new(&cargo_manifest_dir).join("Cargo.toml"))
+ .output()
+ .unwrap();
+ if !output.status.success() {
+ eprintln!("{}", String::from_utf8(output.stderr).unwrap());
+ process::exit(1);
+ }
+ }
+ "#)
+ }).unwrap();
+ let p = project("lib")
+ .file("Cargo.toml", &format!(r#"
+ [package]
+ name = "lib"
+ version = "0.1.0"
+
+ [dependencies.dep]
+ git = "{}"
+
+ [workspace]
+ "#, git_project.url()))
+ .file("src/lib.rs", "");
+ let p = p.build();
+
+ assert_that(p.cargo("build").env("CARGO_HOME", p.root().join(".cargo")),
+ execs().with_status(0));
+}
+
+/*FIXME: This fails because of how workspace.exclude and workspace.members are working.
+#[test]
+fn include_and_exclude() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [workspace]
+ members = ["foo"]
+ exclude = ["foo/bar"]
+ "#)
+ .file("foo/Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("foo/src/lib.rs", "")
+ .file("foo/bar/Cargo.toml", r#"
+ [project]
+ name = "bar"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("foo/bar/src/lib.rs", "");
+ p.build();
+
+ assert_that(p.cargo("build").cwd(p.root().join("foo")),
+ execs().with_status(0));
+ assert_that(&p.root().join("target"), existing_dir());
+ assert_that(&p.root().join("foo/target"), is_not(existing_dir()));
+ assert_that(p.cargo("build").cwd(p.root().join("foo/bar")),
+ execs().with_status(0));
+ assert_that(&p.root().join("foo/bar/target"), existing_dir());
+}
+*/
+
+#[test]
+fn cargo_home_at_root_works() {
+ let p = project("lib")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "lib"
+ version = "0.1.0"
+
+ [workspace]
+ members = ["a"]
+ "#)
+ .file("src/lib.rs", "")
+ .file("a/Cargo.toml", r#"
+ [package]
+ name = "a"
+ version = "0.1.0"
+ "#)
+ .file("a/src/lib.rs", "");
+ let p = p.build();
+
+ assert_that(p.cargo("build"), execs().with_status(0));
+ assert_that(p.cargo("build").arg("--frozen").env("CARGO_HOME", p.root()),
+ execs().with_status(0));
+}
+
+#[test]
+fn relative_rustc() {
+ let p = project("the_exe")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ "#)
+ .file("src/main.rs", r#"
+ use std::process::Command;
+ use std::env;
+
+ fn main() {
+ let mut cmd = Command::new("rustc");
+ for arg in env::args_os().skip(1) {
+ cmd.arg(arg);
+ }
+ std::process::exit(cmd.status().unwrap().code().unwrap());
+ }
+ "#)
+ .build();
+ assert_that(p.cargo("build"), execs().with_status(0));
+
+ let src = p.root()
+ .join("target/debug/foo")
+ .with_extension(env::consts::EXE_EXTENSION);
+
+ Package::new("a", "0.1.0").publish();
+
+ let p = project("lib")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "lib"
+ version = "0.1.0"
+
+ [dependencies]
+ a = "0.1"
+ "#)
+ .file("src/lib.rs", "")
+ .build();
+
+ fs::copy(&src, p.root().join(src.file_name().unwrap())).unwrap();
+
+ let file = format!("./foo{}", env::consts::EXE_SUFFIX);
+ assert_that(p.cargo("build").env("RUSTC", &file),
+ execs().with_status(0));
+}
+++ /dev/null
-extern crate cargotest;
-extern crate hamcrest;
-
-use cargotest::rustc_host;
-use cargotest::support::{path2url, project, execs};
-use hamcrest::assert_that;
-
-#[test]
-fn pathless_tools() {
- let target = rustc_host();
-
- let foo = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [lib]
- name = "foo"
- "#)
- .file("src/lib.rs", "")
- .file(".cargo/config", &format!(r#"
- [target.{}]
- ar = "nonexistent-ar"
- linker = "nonexistent-linker"
- "#, target))
- .build();
-
- assert_that(foo.cargo("build").arg("--verbose"),
- execs().with_stderr(&format!("\
-[COMPILING] foo v0.0.1 ({url})
-[RUNNING] `rustc [..] -C ar=nonexistent-ar -C linker=nonexistent-linker [..]`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-", url = foo.url())))
-}
-
-#[test]
-fn absolute_tools() {
- let target = rustc_host();
-
- // Escaped as they appear within a TOML config file
- let config = if cfg!(windows) {
- (r#"C:\\bogus\\nonexistent-ar"#, r#"C:\\bogus\\nonexistent-linker"#)
- } else {
- (r#"/bogus/nonexistent-ar"#, r#"/bogus/nonexistent-linker"#)
- };
-
- let foo = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [lib]
- name = "foo"
- "#)
- .file("src/lib.rs", "")
- .file(".cargo/config", &format!(r#"
- [target.{target}]
- ar = "{ar}"
- linker = "{linker}"
- "#, target = target, ar = config.0, linker = config.1))
- .build();
-
- let output = if cfg!(windows) {
- (r#"C:\bogus\nonexistent-ar"#, r#"C:\bogus\nonexistent-linker"#)
- } else {
- (r#"/bogus/nonexistent-ar"#, r#"/bogus/nonexistent-linker"#)
- };
-
- assert_that(foo.cargo("build").arg("--verbose"),
- execs().with_stderr(&format!("\
-[COMPILING] foo v0.0.1 ({url})
-[RUNNING] `rustc [..] -C ar={ar} -C linker={linker} [..]`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-", url = foo.url(), ar = output.0, linker = output.1)))
-}
-
-#[test]
-fn relative_tools() {
- let target = rustc_host();
-
- // Escaped as they appear within a TOML config file
- let config = if cfg!(windows) {
- (r#".\\nonexistent-ar"#, r#".\\tools\\nonexistent-linker"#)
- } else {
- (r#"./nonexistent-ar"#, r#"./tools/nonexistent-linker"#)
- };
-
- // Funky directory structure to test that relative tool paths are made absolute
- // by reference to the `.cargo/..` directory and not to (for example) the CWD.
- let origin = project("origin")
- .file("foo/Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [lib]
- name = "foo"
- "#)
- .file("foo/src/lib.rs", "")
- .file(".cargo/config", &format!(r#"
- [target.{target}]
- ar = "{ar}"
- linker = "{linker}"
- "#, target = target, ar = config.0, linker = config.1))
- .build();
-
- let foo_path = origin.root().join("foo");
- let foo_url = path2url(foo_path.clone());
- let prefix = origin.root().into_os_string().into_string().unwrap();
- let output = if cfg!(windows) {
- (format!(r#"{}\.\nonexistent-ar"#, prefix),
- format!(r#"{}\.\tools\nonexistent-linker"#, prefix))
- } else {
- (format!(r#"{}/./nonexistent-ar"#, prefix),
- format!(r#"{}/./tools/nonexistent-linker"#, prefix))
- };
-
- assert_that(origin.cargo("build").cwd(foo_path).arg("--verbose"),
- execs().with_stderr(&format!("\
-[COMPILING] foo v0.0.1 ({url})
-[RUNNING] `rustc [..] -C ar={ar} -C linker={linker} [..]`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-", url = foo_url, ar = output.0, linker = output.1)))
-}
-
-#[test]
-fn custom_runner() {
- let target = rustc_host();
-
- let p = project("foo")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.0.1"
- "#)
- .file("src/main.rs", "fn main() {}")
- .file("tests/test.rs", "")
- .file("benches/bench.rs", "")
- .file(".cargo/config", &format!(r#"
- [target.{}]
- runner = "nonexistent-runner -r"
- "#, target))
- .build();
-
- assert_that(p.cargo("run").args(&["--", "--param"]),
- execs().with_stderr_contains(&format!("\
-[COMPILING] foo v0.0.1 ({url})
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] `nonexistent-runner -r target[/]debug[/]foo[EXE] --param`
-", url = p.url())));
-
- assert_that(p.cargo("test").args(&["--test", "test", "--verbose", "--", "--param"]),
- execs().with_stderr_contains(&format!("\
-[COMPILING] foo v0.0.1 ({url})
-[RUNNING] `rustc [..]`
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-[RUNNING] `nonexistent-runner -r [..][/]target[/]debug[/]deps[/]test-[..][EXE] --param`
-", url = p.url())));
-
- assert_that(p.cargo("bench").args(&["--bench", "bench", "--verbose", "--", "--param"]),
- execs().with_stderr_contains(&format!("\
-[COMPILING] foo v0.0.1 ({url})
-[RUNNING] `rustc [..]`
-[RUNNING] `rustc [..]`
-[FINISHED] release [optimized] target(s) in [..]
-[RUNNING] `nonexistent-runner -r [..][/]target[/]release[/]deps[/]bench-[..][EXE] --param --bench`
-", url = p.url())));
-}
+++ /dev/null
-extern crate cargotest;
-extern crate hamcrest;
-
-use cargotest::support::{project, execs, main_file, basic_bin_manifest};
-use hamcrest::{assert_that};
-
-fn verify_project_success_output() -> String {
- r#"{"success":"true"}"#.into()
-}
-
-#[test]
-fn cargo_verify_project_path_to_cargo_toml_relative() {
- let p = project("foo")
- .file("Cargo.toml", &basic_bin_manifest("foo"))
- .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
- .build();
-
- assert_that(p.cargo("verify-project")
- .arg("--manifest-path").arg("foo/Cargo.toml")
- .cwd(p.root().parent().unwrap()),
- execs().with_status(0)
- .with_stdout(verify_project_success_output()));
-}
-
-#[test]
-fn cargo_verify_project_path_to_cargo_toml_absolute() {
- let p = project("foo")
- .file("Cargo.toml", &basic_bin_manifest("foo"))
- .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
- .build();
-
- assert_that(p.cargo("verify-project")
- .arg("--manifest-path").arg(p.root().join("Cargo.toml"))
- .cwd(p.root().parent().unwrap()),
- execs().with_status(0)
- .with_stdout(verify_project_success_output()));
-}
-
-#[test]
-fn cargo_verify_project_cwd() {
- let p = project("foo")
- .file("Cargo.toml", &basic_bin_manifest("foo"))
- .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
- .build();
-
- assert_that(p.cargo("verify-project")
- .cwd(p.root()),
- execs().with_status(0)
- .with_stdout(verify_project_success_output()));
-}
+++ /dev/null
-extern crate cargo;
-extern crate cargotest;
-extern crate hamcrest;
-
-use cargotest::support::{project, execs};
-use hamcrest::assert_that;
-
-#[test]
-fn simple() {
- let p = project("foo").build();
-
- assert_that(p.cargo("version"),
- execs().with_status(0).with_stdout(&format!("{}\n",
- cargo::version())));
-
- assert_that(p.cargo("--version"),
- execs().with_status(0).with_stdout(&format!("{}\n",
- cargo::version())));
-
-}
-
-
-#[test]
-#[cfg_attr(target_os = "windows", ignore)]
-fn version_works_without_rustc() {
- let p = project("foo").build();
- assert_that(p.cargo("version").env("PATH", ""),
- execs().with_status(0));
-}
-
-#[test]
-fn version_works_with_bad_config() {
- let p = project("foo")
- .file(".cargo/config", "this is not toml")
- .build();
- assert_that(p.cargo("version"),
- execs().with_status(0));
-}
-
-#[test]
-fn version_works_with_bad_target_dir() {
- let p = project("foo")
- .file(".cargo/config", r#"
- [build]
- target-dir = 4
- "#)
- .build();
- assert_that(p.cargo("version"),
- execs().with_status(0));
-}
+++ /dev/null
-extern crate cargotest;
-extern crate hamcrest;
-
-use cargotest::support::{project, execs, Project};
-use cargotest::support::registry::Package;
-use hamcrest::assert_that;
-
-static WARNING1: &'static str = "Hello! I'm a warning. :)";
-static WARNING2: &'static str = "And one more!";
-
-fn make_lib(lib_src: &str) {
- Package::new("foo", "0.0.1")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- authors = []
- version = "0.0.1"
- build = "build.rs"
- "#)
- .file("build.rs", &format!(r#"
- fn main() {{
- use std::io::Write;
- println!("cargo:warning={{}}", "{}");
- println!("hidden stdout");
- write!(&mut ::std::io::stderr(), "hidden stderr");
- println!("cargo:warning={{}}", "{}");
- }}
- "#, WARNING1, WARNING2))
- .file("src/lib.rs", &format!("fn f() {{ {} }}", lib_src))
- .publish();
-}
-
-fn make_upstream(main_src: &str) -> Project {
- project("bar")
- .file("Cargo.toml", r#"
- [package]
- name = "bar"
- version = "0.0.1"
- authors = []
-
- [dependencies]
- foo = "*"
- "#)
- .file("src/main.rs", &format!("fn main() {{ {} }}", main_src))
- .build()
-}
-
-#[test]
-fn no_warning_on_success() {
- make_lib("");
- let upstream = make_upstream("");
- assert_that(upstream.cargo("build"),
- execs().with_status(0)
- .with_stderr("\
-[UPDATING] registry `[..]`
-[DOWNLOADING] foo v0.0.1 ([..])
-[COMPILING] foo v0.0.1
-[COMPILING] bar v0.0.1 ([..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-}
-
-#[test]
-fn no_warning_on_bin_failure() {
- make_lib("");
- let upstream = make_upstream("hi()");
- assert_that(upstream.cargo("build"),
- execs().with_status(101)
- .with_stdout_does_not_contain("hidden stdout")
- .with_stderr_does_not_contain("hidden stderr")
- .with_stderr_does_not_contain(&format!("[WARNING] {}", WARNING1))
- .with_stderr_does_not_contain(&format!("[WARNING] {}", WARNING2))
- .with_stderr_contains("[UPDATING] registry `[..]`")
- .with_stderr_contains("[DOWNLOADING] foo v0.0.1 ([..])")
- .with_stderr_contains("[COMPILING] foo v0.0.1")
- .with_stderr_contains("[COMPILING] bar v0.0.1 ([..])"));
-}
-
-#[test]
-fn warning_on_lib_failure() {
- make_lib("err()");
- let upstream = make_upstream("");
- assert_that(upstream.cargo("build"),
- execs().with_status(101)
- .with_stdout_does_not_contain("hidden stdout")
- .with_stderr_does_not_contain("hidden stderr")
- .with_stderr_does_not_contain("[COMPILING] bar v0.0.1 ([..])")
- .with_stderr_contains("[UPDATING] registry `[..]`")
- .with_stderr_contains("[DOWNLOADING] foo v0.0.1 ([..])")
- .with_stderr_contains("[COMPILING] foo v0.0.1")
- .with_stderr_contains(&format!("[WARNING] {}", WARNING1))
- .with_stderr_contains(&format!("[WARNING] {}", WARNING2)));
-}
+++ /dev/null
-#[macro_use]
-extern crate cargotest;
-extern crate hamcrest;
-
-use std::env;
-use std::fs::{self, File};
-use std::io::{Read, Write};
-
-use cargotest::sleep_ms;
-use cargotest::support::{project, execs, git};
-use cargotest::support::registry::Package;
-use hamcrest::{assert_that, existing_file, existing_dir, is_not};
-
-#[test]
-fn simple_explicit() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.1.0"
- authors = []
-
- [workspace]
- members = ["bar"]
- "#)
- .file("src/main.rs", "fn main() {}")
- .file("bar/Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.1.0"
- authors = []
- workspace = ".."
- "#)
- .file("bar/src/main.rs", "fn main() {}");
- let p = p.build();
-
- assert_that(p.cargo("build"), execs().with_status(0));
- assert_that(&p.bin("foo"), existing_file());
- assert_that(&p.bin("bar"), is_not(existing_file()));
-
- assert_that(p.cargo("build").cwd(p.root().join("bar")),
- execs().with_status(0));
- assert_that(&p.bin("foo"), existing_file());
- assert_that(&p.bin("bar"), existing_file());
-
- assert_that(&p.root().join("Cargo.lock"), existing_file());
- assert_that(&p.root().join("bar/Cargo.lock"), is_not(existing_file()));
-}
-
-#[test]
-fn simple_explicit_default_members() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.1.0"
- authors = []
-
- [workspace]
- members = ["bar"]
- default-members = ["bar"]
- "#)
- .file("src/main.rs", "fn main() {}")
- .file("bar/Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.1.0"
- authors = []
- workspace = ".."
- "#)
- .file("bar/src/main.rs", "fn main() {}");
- let p = p.build();
-
- assert_that(p.cargo("build"), execs().with_status(0));
- assert_that(&p.bin("bar"), existing_file());
- assert_that(&p.bin("foo"), is_not(existing_file()));
-}
-
-#[test]
-fn inferred_root() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.1.0"
- authors = []
-
- [workspace]
- members = ["bar"]
- "#)
- .file("src/main.rs", "fn main() {}")
- .file("bar/Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.1.0"
- authors = []
- "#)
- .file("bar/src/main.rs", "fn main() {}");
- let p = p.build();
-
- assert_that(p.cargo("build"), execs().with_status(0));
- assert_that(&p.bin("foo"), existing_file());
- assert_that(&p.bin("bar"), is_not(existing_file()));
-
- assert_that(p.cargo("build").cwd(p.root().join("bar")),
- execs().with_status(0));
- assert_that(&p.bin("foo"), existing_file());
- assert_that(&p.bin("bar"), existing_file());
-
- assert_that(&p.root().join("Cargo.lock"), existing_file());
- assert_that(&p.root().join("bar/Cargo.lock"), is_not(existing_file()));
-}
-
-#[test]
-fn inferred_path_dep() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.1.0"
- authors = []
-
- [dependencies]
- bar = { path = "bar" }
-
- [workspace]
- "#)
- .file("src/main.rs", "fn main() {}")
- .file("bar/Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.1.0"
- authors = []
- "#)
- .file("bar/src/main.rs", "fn main() {}")
- .file("bar/src/lib.rs", "");
- let p = p.build();
-
- assert_that(p.cargo("build"), execs().with_status(0));
- assert_that(&p.bin("foo"), existing_file());
- assert_that(&p.bin("bar"), is_not(existing_file()));
-
- assert_that(p.cargo("build").cwd(p.root().join("bar")),
- execs().with_status(0));
- assert_that(&p.bin("foo"), existing_file());
- assert_that(&p.bin("bar"), existing_file());
-
- assert_that(&p.root().join("Cargo.lock"), existing_file());
- assert_that(&p.root().join("bar/Cargo.lock"), is_not(existing_file()));
-}
-
-#[test]
-fn transitive_path_dep() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.1.0"
- authors = []
-
- [dependencies]
- bar = { path = "bar" }
-
- [workspace]
- "#)
- .file("src/main.rs", "fn main() {}")
- .file("bar/Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.1.0"
- authors = []
-
- [dependencies]
- baz = { path = "../baz" }
- "#)
- .file("bar/src/main.rs", "fn main() {}")
- .file("bar/src/lib.rs", "")
- .file("baz/Cargo.toml", r#"
- [project]
- name = "baz"
- version = "0.1.0"
- authors = []
- "#)
- .file("baz/src/main.rs", "fn main() {}")
- .file("baz/src/lib.rs", "");
- let p = p.build();
-
- assert_that(p.cargo("build"), execs().with_status(0));
- assert_that(&p.bin("foo"), existing_file());
- assert_that(&p.bin("bar"), is_not(existing_file()));
- assert_that(&p.bin("baz"), is_not(existing_file()));
-
- assert_that(p.cargo("build").cwd(p.root().join("bar")),
- execs().with_status(0));
- assert_that(&p.bin("foo"), existing_file());
- assert_that(&p.bin("bar"), existing_file());
- assert_that(&p.bin("baz"), is_not(existing_file()));
-
- assert_that(p.cargo("build").cwd(p.root().join("baz")),
- execs().with_status(0));
- assert_that(&p.bin("foo"), existing_file());
- assert_that(&p.bin("bar"), existing_file());
- assert_that(&p.bin("baz"), existing_file());
-
- assert_that(&p.root().join("Cargo.lock"), existing_file());
- assert_that(&p.root().join("bar/Cargo.lock"), is_not(existing_file()));
- assert_that(&p.root().join("baz/Cargo.lock"), is_not(existing_file()));
-}
-
-#[test]
-fn parent_pointer_works() {
- let p = project("foo")
- .file("foo/Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.1.0"
- authors = []
-
- [dependencies]
- bar = { path = "../bar" }
-
- [workspace]
- "#)
- .file("foo/src/main.rs", "fn main() {}")
- .file("bar/Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.1.0"
- authors = []
- workspace = "../foo"
- "#)
- .file("bar/src/main.rs", "fn main() {}")
- .file("bar/src/lib.rs", "");
- let p = p.build();
-
- assert_that(p.cargo("build").cwd(p.root().join("foo")),
- execs().with_status(0));
- assert_that(p.cargo("build").cwd(p.root().join("bar")),
- execs().with_status(0));
- assert_that(&p.root().join("foo/Cargo.lock"), existing_file());
- assert_that(&p.root().join("bar/Cargo.lock"), is_not(existing_file()));
-}
-
-#[test]
-fn same_names_in_workspace() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.1.0"
- authors = []
-
- [workspace]
- members = ["bar"]
- "#)
- .file("src/main.rs", "fn main() {}")
- .file("bar/Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.1.0"
- authors = []
- workspace = ".."
- "#)
- .file("bar/src/main.rs", "fn main() {}");
- let p = p.build();
-
- assert_that(p.cargo("build"),
- execs().with_status(101)
- .with_stderr("\
-error: two packages named `foo` in this workspace:
-- [..]Cargo.toml
-- [..]Cargo.toml
-"));
-}
-
-#[test]
-fn parent_doesnt_point_to_child() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.1.0"
- authors = []
-
- [workspace]
- "#)
- .file("src/main.rs", "fn main() {}")
- .file("bar/Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.1.0"
- authors = []
- "#)
- .file("bar/src/main.rs", "fn main() {}");
- let p = p.build();
-
- assert_that(p.cargo("build").cwd(p.root().join("bar")),
- execs().with_status(101)
- .with_stderr("\
-error: current package believes it's in a workspace when it's not:
-current: [..]Cargo.toml
-workspace: [..]Cargo.toml
-
-this may be fixable [..]
-"));
-}
-
-#[test]
-fn invalid_parent_pointer() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.1.0"
- authors = []
- workspace = "foo"
- "#)
- .file("src/main.rs", "fn main() {}");
- let p = p.build();
-
- assert_that(p.cargo("build"),
- execs().with_status(101)
- .with_stderr("\
-error: failed to read `[..]Cargo.toml`
-
-Caused by:
- [..]
-"));
-}
-
-#[test]
-fn invalid_members() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.1.0"
- authors = []
-
- [workspace]
- members = ["foo"]
- "#)
- .file("src/main.rs", "fn main() {}");
- let p = p.build();
-
- assert_that(p.cargo("build"),
- execs().with_status(101)
- .with_stderr("\
-error: failed to read `[..]Cargo.toml`
-
-Caused by:
- [..]
-"));
-}
-
-#[test]
-fn bare_workspace_ok() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.1.0"
- authors = []
-
- [workspace]
- "#)
- .file("src/main.rs", "fn main() {}");
- let p = p.build();
-
- assert_that(p.cargo("build"), execs().with_status(0));
-}
-
-#[test]
-fn two_roots() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.1.0"
- authors = []
-
- [workspace]
- members = ["bar"]
- "#)
- .file("src/main.rs", "fn main() {}")
- .file("bar/Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.1.0"
- authors = []
-
- [workspace]
- members = [".."]
- "#)
- .file("bar/src/main.rs", "fn main() {}");
- let p = p.build();
-
- assert_that(p.cargo("build"),
- execs().with_status(101)
- .with_stderr("\
-error: multiple workspace roots found in the same workspace:
- [..]
- [..]
-"));
-}
-
-#[test]
-fn workspace_isnt_root() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.1.0"
- authors = []
- workspace = "bar"
- "#)
- .file("src/main.rs", "fn main() {}")
- .file("bar/Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.1.0"
- authors = []
- "#)
- .file("bar/src/main.rs", "fn main() {}");
- let p = p.build();
-
- assert_that(p.cargo("build"),
- execs().with_status(101)
- .with_stderr("\
-error: root of a workspace inferred but wasn't a root: [..]
-"));
-}
-
-#[test]
-fn dangling_member() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.1.0"
- authors = []
-
- [workspace]
- members = ["bar"]
- "#)
- .file("src/main.rs", "fn main() {}")
- .file("bar/Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.1.0"
- authors = []
- workspace = "../baz"
- "#)
- .file("bar/src/main.rs", "fn main() {}")
- .file("baz/Cargo.toml", r#"
- [project]
- name = "baz"
- version = "0.1.0"
- authors = []
- workspace = "../baz"
- "#)
- .file("baz/src/main.rs", "fn main() {}");
- let p = p.build();
-
- assert_that(p.cargo("build"),
- execs().with_status(101)
- .with_stderr("\
-error: package `[..]` is a member of the wrong workspace
-expected: [..]
-actual: [..]
-"));
-}
-
-#[test]
-fn cycle() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.1.0"
- authors = []
- workspace = "bar"
- "#)
- .file("src/main.rs", "fn main() {}")
- .file("bar/Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.1.0"
- authors = []
- workspace = ".."
- "#)
- .file("bar/src/main.rs", "fn main() {}");
- let p = p.build();
-
- assert_that(p.cargo("build"),
- execs().with_status(101));
-}
-
-#[test]
-fn share_dependencies() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.1.0"
- authors = []
-
- [dependencies]
- dep1 = "0.1"
-
- [workspace]
- members = ["bar"]
- "#)
- .file("src/main.rs", "fn main() {}")
- .file("bar/Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.1.0"
- authors = []
-
- [dependencies]
- dep1 = "< 0.1.5"
- "#)
- .file("bar/src/main.rs", "fn main() {}");
- let p = p.build();
-
- Package::new("dep1", "0.1.3").publish();
- Package::new("dep1", "0.1.8").publish();
-
- assert_that(p.cargo("build"),
- execs().with_status(0)
- .with_stderr("\
-[UPDATING] registry `[..]`
-[DOWNLOADING] dep1 v0.1.3 ([..])
-[COMPILING] dep1 v0.1.3
-[COMPILING] foo v0.1.0 ([..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-}
-
-#[test]
-fn fetch_fetches_all() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.1.0"
- authors = []
-
- [workspace]
- members = ["bar"]
- "#)
- .file("src/main.rs", "fn main() {}")
- .file("bar/Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.1.0"
- authors = []
-
- [dependencies]
- dep1 = "*"
- "#)
- .file("bar/src/main.rs", "fn main() {}");
- let p = p.build();
-
- Package::new("dep1", "0.1.3").publish();
-
- assert_that(p.cargo("fetch"),
- execs().with_status(0)
- .with_stderr("\
-[UPDATING] registry `[..]`
-[DOWNLOADING] dep1 v0.1.3 ([..])
-"));
-}
-
-#[test]
-fn lock_works_for_everyone() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.1.0"
- authors = []
-
- [dependencies]
- dep2 = "0.1"
-
- [workspace]
- members = ["bar"]
- "#)
- .file("src/main.rs", "fn main() {}")
- .file("bar/Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.1.0"
- authors = []
-
- [dependencies]
- dep1 = "0.1"
- "#)
- .file("bar/src/main.rs", "fn main() {}");
- let p = p.build();
-
- Package::new("dep1", "0.1.0").publish();
- Package::new("dep2", "0.1.0").publish();
-
- assert_that(p.cargo("generate-lockfile"),
- execs().with_status(0)
- .with_stderr("\
-[UPDATING] registry `[..]`
-"));
-
- Package::new("dep1", "0.1.1").publish();
- Package::new("dep2", "0.1.1").publish();
-
- assert_that(p.cargo("build"),
- execs().with_status(0)
- .with_stderr("\
-[DOWNLOADING] dep2 v0.1.0 ([..])
-[COMPILING] dep2 v0.1.0
-[COMPILING] foo v0.1.0 ([..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-
- assert_that(p.cargo("build").cwd(p.root().join("bar")),
- execs().with_status(0)
- .with_stderr("\
-[DOWNLOADING] dep1 v0.1.0 ([..])
-[COMPILING] dep1 v0.1.0
-[COMPILING] bar v0.1.0 ([..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-}
-
-#[test]
-fn virtual_works() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [workspace]
- members = ["bar"]
- "#)
- .file("bar/Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.1.0"
- authors = []
- "#)
- .file("bar/src/main.rs", "fn main() {}");
- let p = p.build();
- assert_that(p.cargo("build").cwd(p.root().join("bar")),
- execs().with_status(0));
- assert_that(&p.root().join("Cargo.lock"), existing_file());
- assert_that(&p.bin("bar"), existing_file());
- assert_that(&p.root().join("bar/Cargo.lock"), is_not(existing_file()));
-}
-
-#[test]
-fn explicit_package_argument_works_with_virtual_manifest() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [workspace]
- members = ["bar"]
- "#)
- .file("bar/Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.1.0"
- authors = []
- "#)
- .file("bar/src/main.rs", "fn main() {}");
- let p = p.build();
- assert_that(p.cargo("build").cwd(p.root()).args(&["--package", "bar"]),
- execs().with_status(0));
- assert_that(&p.root().join("Cargo.lock"), existing_file());
- assert_that(&p.bin("bar"), existing_file());
- assert_that(&p.root().join("bar/Cargo.lock"), is_not(existing_file()));
-}
-
-#[test]
-fn virtual_misconfigure() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [workspace]
- "#)
- .file("bar/Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.1.0"
- authors = []
- "#)
- .file("bar/src/main.rs", "fn main() {}");
- let p = p.build();
- assert_that(p.cargo("build").cwd(p.root().join("bar")),
- execs().with_status(101)
- .with_stderr("\
-error: current package believes it's in a workspace when it's not:
-current: [..]bar[..]Cargo.toml
-workspace: [..]Cargo.toml
-
-this may be fixable by adding `bar` to the `workspace.members` array of the \
-manifest located at: [..]
-"));
-}
-
-#[test]
-fn virtual_build_all_implied() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [workspace]
- members = ["bar"]
- "#)
- .file("bar/Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.1.0"
- authors = []
- "#)
- .file("bar/src/main.rs", "fn main() {}");
- let p = p.build();
- assert_that(p.cargo("build"),
- execs().with_status(0));
-}
-
-#[test]
-fn virtual_default_members() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [workspace]
- members = ["bar", "baz"]
- default-members = ["bar"]
- "#)
- .file("bar/Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.1.0"
- authors = []
- "#)
- .file("baz/Cargo.toml", r#"
- [project]
- name = "baz"
- version = "0.1.0"
- authors = []
- "#)
- .file("bar/src/main.rs", "fn main() {}")
- .file("baz/src/main.rs", "fn main() {}");
- let p = p.build();
- assert_that(p.cargo("build"),
- execs().with_status(0));
- assert_that(&p.bin("bar"), existing_file());
- assert_that(&p.bin("baz"), is_not(existing_file()));
-}
-
-#[test]
-fn virtual_default_member_is_not_a_member() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [workspace]
- members = ["bar"]
- default-members = ["something-else"]
- "#)
- .file("bar/Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.1.0"
- authors = []
- "#)
- .file("bar/src/main.rs", "fn main() {}");
- let p = p.build();
- assert_that(p.cargo("build"),
- execs().with_status(101)
- .with_stderr("\
-error: package `[..]something-else` is listed in workspace’s default-members \
-but is not a member.
-"));
-}
-
-#[test]
-fn virtual_build_no_members() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [workspace]
- "#);
- let p = p.build();
- assert_that(p.cargo("build"),
- execs().with_status(101)
- .with_stderr("\
-error: manifest path `[..]` contains no package: The manifest is virtual, \
-and the workspace has no members.
-"));
-}
-
-#[test]
-fn include_virtual() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.1.0"
- authors = []
- [workspace]
- members = ["bar"]
- "#)
- .file("src/main.rs", "")
- .file("bar/Cargo.toml", r#"
- [workspace]
- "#);
- let p = p.build();
- assert_that(p.cargo("build"),
- execs().with_status(101)
- .with_stderr("\
-error: multiple workspace roots found in the same workspace:
- [..]
- [..]
-"));
-}
-
-#[test]
-fn members_include_path_deps() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.1.0"
- authors = []
-
- [workspace]
- members = ["p1"]
-
- [dependencies]
- p3 = { path = "p3" }
- "#)
- .file("src/lib.rs", "")
- .file("p1/Cargo.toml", r#"
- [project]
- name = "p1"
- version = "0.1.0"
- authors = []
-
- [dependencies]
- p2 = { path = "../p2" }
- "#)
- .file("p1/src/lib.rs", "")
- .file("p2/Cargo.toml", r#"
- [project]
- name = "p2"
- version = "0.1.0"
- authors = []
- "#)
- .file("p2/src/lib.rs", "")
- .file("p3/Cargo.toml", r#"
- [project]
- name = "p3"
- version = "0.1.0"
- authors = []
- "#)
- .file("p3/src/lib.rs", "");
- let p = p.build();
-
- assert_that(p.cargo("build").cwd(p.root().join("p1")),
- execs().with_status(0));
- assert_that(p.cargo("build").cwd(p.root().join("p2")),
- execs().with_status(0));
- assert_that(p.cargo("build").cwd(p.root().join("p3")),
- execs().with_status(0));
- assert_that(p.cargo("build"),
- execs().with_status(0));
-
- assert_that(&p.root().join("target"), existing_dir());
- assert_that(&p.root().join("p1/target"), is_not(existing_dir()));
- assert_that(&p.root().join("p2/target"), is_not(existing_dir()));
- assert_that(&p.root().join("p3/target"), is_not(existing_dir()));
-}
-
-#[test]
-fn new_warns_you_this_will_not_work() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.1.0"
- authors = []
-
- [workspace]
- "#)
- .file("src/lib.rs", "");
- let p = p.build();
-
- assert_that(p.cargo("new").arg("--lib").arg("bar").env("USER", "foo"),
- execs().with_status(0)
- .with_stderr("\
-warning: compiling this new crate may not work due to invalid workspace \
-configuration
-
-current package believes it's in a workspace when it's not:
-current: [..]
-workspace: [..]
-
-this may be fixable by ensuring that this crate is depended on by the workspace \
-root: [..]
-[CREATED] library `bar` project
-"));
-}
-
-#[test]
-fn lock_doesnt_change_depending_on_crate() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.1.0"
- authors = []
-
- [workspace]
- members = ['baz']
-
- [dependencies]
- foo = "*"
- "#)
- .file("src/lib.rs", "")
- .file("baz/Cargo.toml", r#"
- [project]
- name = "baz"
- version = "0.1.0"
- authors = []
-
- [dependencies]
- bar = "*"
- "#)
- .file("baz/src/lib.rs", "");
- let p = p.build();
-
- Package::new("foo", "1.0.0").publish();
- Package::new("bar", "1.0.0").publish();
-
- assert_that(p.cargo("build"),
- execs().with_status(0));
-
- let mut lockfile = String::new();
- t!(t!(File::open(p.root().join("Cargo.lock"))).read_to_string(&mut lockfile));
-
- assert_that(p.cargo("build").cwd(p.root().join("baz")),
- execs().with_status(0));
-
- let mut lockfile2 = String::new();
- t!(t!(File::open(p.root().join("Cargo.lock"))).read_to_string(&mut lockfile2));
-
- assert_eq!(lockfile, lockfile2);
-}
-
-#[test]
-fn rebuild_please() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [workspace]
- members = ['lib', 'bin']
- "#)
- .file("lib/Cargo.toml", r#"
- [package]
- name = "lib"
- version = "0.1.0"
- "#)
- .file("lib/src/lib.rs", r#"
- pub fn foo() -> u32 { 0 }
- "#)
- .file("bin/Cargo.toml", r#"
- [package]
- name = "bin"
- version = "0.1.0"
-
- [dependencies]
- lib = { path = "../lib" }
- "#)
- .file("bin/src/main.rs", r#"
- extern crate lib;
-
- fn main() {
- assert_eq!(lib::foo(), 0);
- }
- "#);
- let p = p.build();
-
- assert_that(p.cargo("run").cwd(p.root().join("bin")),
- execs().with_status(0));
-
- sleep_ms(1000);
-
- t!(t!(File::create(p.root().join("lib/src/lib.rs"))).write_all(br#"
- pub fn foo() -> u32 { 1 }
- "#));
-
- assert_that(p.cargo("build").cwd(p.root().join("lib")),
- execs().with_status(0));
-
- assert_that(p.cargo("run").cwd(p.root().join("bin")),
- execs().with_status(101));
-}
-
-#[test]
-fn workspace_in_git() {
- let git_project = git::new("dep1", |project| {
- project
- .file("Cargo.toml", r#"
- [workspace]
- members = ["foo"]
- "#)
- .file("foo/Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- "#)
- .file("foo/src/lib.rs", "")
- }).unwrap();
- let p = project("foo")
- .file("Cargo.toml", &format!(r#"
- [package]
- name = "lib"
- version = "0.1.0"
-
- [dependencies.foo]
- git = '{}'
- "#, git_project.url()))
- .file("src/lib.rs", r#"
- pub fn foo() -> u32 { 0 }
- "#);
- let p = p.build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0));
-}
-
-
-#[test]
-fn lockfile_can_specify_nonexistant_members() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [workspace]
- members = ["a"]
- "#)
- .file("a/Cargo.toml", r#"
- [project]
- name = "a"
- version = "0.1.0"
- authors = []
- "#)
- .file("a/src/main.rs", "fn main() {}")
- .file("Cargo.lock", r#"
- [[package]]
- name = "a"
- version = "0.1.0"
-
- [[package]]
- name = "b"
- version = "0.1.0"
- "#);
-
- let p = p.build();
-
- assert_that(p.cargo("build").cwd(p.root().join("a")), execs().with_status(0));
-}
-
-#[test]
-fn you_cannot_generate_lockfile_for_empty_workspaces() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [workspace]
- "#)
- .file("bar/Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.1.0"
- authors = []
- "#)
- .file("bar/src/main.rs", "fn main() {}");
- let p = p.build();
-
- assert_that(p.cargo("update"),
- execs().with_status(101)
- .with_stderr("\
-error: you can't generate a lockfile for an empty workspace.
-"));
-}
-
-#[test]
-fn workspace_with_transitive_dev_deps() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.5.0"
- authors = ["mbrubeck@example.com"]
-
- [dependencies.bar]
- path = "bar"
-
- [workspace]
- "#)
- .file("src/main.rs", r#"fn main() {}"#)
- .file("bar/Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.5.0"
- authors = ["mbrubeck@example.com"]
-
- [dev-dependencies.baz]
- path = "../baz"
- "#)
- .file("bar/src/lib.rs", r#"
- pub fn init() {}
-
- #[cfg(test)]
-
- #[test]
- fn test() {
- extern crate baz;
- baz::do_stuff();
- }
- "#)
- .file("baz/Cargo.toml", r#"
- [project]
- name = "baz"
- version = "0.5.0"
- authors = ["mbrubeck@example.com"]
- "#)
- .file("baz/src/lib.rs", r#"pub fn do_stuff() {}"#);
- let p = p.build();
-
- assert_that(p.cargo("test").args(&["-p", "bar"]),
- execs().with_status(0));
-}
-
-#[test]
-fn error_if_parent_cargo_toml_is_invalid() {
- let p = project("foo")
- .file("Cargo.toml", "Totally not a TOML file")
- .file("bar/Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.1.0"
- authors = []
- "#)
- .file("bar/src/main.rs", "fn main() {}");
- let p = p.build();
-
- assert_that(p.cargo("build").cwd(p.root().join("bar")),
- execs().with_status(101)
- .with_stderr_contains("\
-[ERROR] failed to parse manifest at `[..]`"));
-}
-
-#[test]
-fn relative_path_for_member_works() {
- let p = project("foo")
- .file("foo/Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.1.0"
- authors = []
-
- [workspace]
- members = ["../bar"]
- "#)
- .file("foo/src/main.rs", "fn main() {}")
- .file("bar/Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.1.0"
- authors = []
- workspace = "../foo"
- "#)
- .file("bar/src/main.rs", "fn main() {}");
- let p = p.build();
-
- assert_that(p.cargo("build").cwd(p.root().join("foo")), execs().with_status(0));
- assert_that(p.cargo("build").cwd(p.root().join("bar")), execs().with_status(0));
-}
-
-#[test]
-fn relative_path_for_root_works() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.1.0"
- authors = []
-
- [workspace]
-
- [dependencies]
- subproj = { path = "./subproj" }
- "#)
- .file("src/main.rs", "fn main() {}")
- .file("subproj/Cargo.toml", r#"
- [project]
- name = "subproj"
- version = "0.1.0"
- authors = []
- "#)
- .file("subproj/src/main.rs", "fn main() {}");
- let p = p.build();
-
- assert_that(p.cargo("build").cwd(p.root())
- .arg("--manifest-path").arg("./Cargo.toml"),
- execs().with_status(0));
-
- assert_that(p.cargo("build").cwd(p.root().join("subproj"))
- .arg("--manifest-path").arg("../Cargo.toml"),
- execs().with_status(0));
-}
-
-#[test]
-fn path_dep_outside_workspace_is_not_member() {
- let p = project("foo")
- .file("ws/Cargo.toml", r#"
- [project]
- name = "ws"
- version = "0.1.0"
- authors = []
-
- [dependencies]
- foo = { path = "../foo" }
-
- [workspace]
- "#)
- .file("ws/src/lib.rs", r"extern crate foo;")
- .file("foo/Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.1.0"
- authors = []
- "#)
- .file("foo/src/lib.rs", "");
- let p = p.build();
-
- assert_that(p.cargo("build").cwd(p.root().join("ws")),
- execs().with_status(0));
-}
-
-#[test]
-fn test_in_and_out_of_workspace() {
- let p = project("foo")
- .file("ws/Cargo.toml", r#"
- [project]
- name = "ws"
- version = "0.1.0"
- authors = []
-
- [dependencies]
- foo = { path = "../foo" }
-
- [workspace]
- members = [ "../bar" ]
- "#)
- .file("ws/src/lib.rs", r"extern crate foo; pub fn f() { foo::f() }")
- .file("foo/Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.1.0"
- authors = []
-
- [dependencies]
- bar = { path = "../bar" }
- "#)
- .file("foo/src/lib.rs", "extern crate bar; pub fn f() { bar::f() }")
- .file("bar/Cargo.toml", r#"
- [project]
- workspace = "../ws"
- name = "bar"
- version = "0.1.0"
- authors = []
- "#)
- .file("bar/src/lib.rs", "pub fn f() { }");
- let p = p.build();
-
- assert_that(p.cargo("build").cwd(p.root().join("ws")),
- execs().with_status(0));
-
- assert_that(&p.root().join("ws/Cargo.lock"), existing_file());
- assert_that(&p.root().join("ws/target"), existing_dir());
- assert_that(&p.root().join("foo/Cargo.lock"), is_not(existing_file()));
- assert_that(&p.root().join("foo/target"), is_not(existing_dir()));
- assert_that(&p.root().join("bar/Cargo.lock"), is_not(existing_file()));
- assert_that(&p.root().join("bar/target"), is_not(existing_dir()));
-
- assert_that(p.cargo("build").cwd(p.root().join("foo")),
- execs().with_status(0));
- assert_that(&p.root().join("foo/Cargo.lock"), existing_file());
- assert_that(&p.root().join("foo/target"), existing_dir());
- assert_that(&p.root().join("bar/Cargo.lock"), is_not(existing_file()));
- assert_that(&p.root().join("bar/target"), is_not(existing_dir()));
-}
-
-#[test]
-fn test_path_dependency_under_member() {
- let p = project("foo")
- .file("ws/Cargo.toml", r#"
- [project]
- name = "ws"
- version = "0.1.0"
- authors = []
-
- [dependencies]
- foo = { path = "../foo" }
-
- [workspace]
- "#)
- .file("ws/src/lib.rs", r"extern crate foo; pub fn f() { foo::f() }")
- .file("foo/Cargo.toml", r#"
- [project]
- workspace = "../ws"
- name = "foo"
- version = "0.1.0"
- authors = []
-
- [dependencies]
- bar = { path = "./bar" }
- "#)
- .file("foo/src/lib.rs", "extern crate bar; pub fn f() { bar::f() }")
- .file("foo/bar/Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.1.0"
- authors = []
- "#)
- .file("foo/bar/src/lib.rs", "pub fn f() { }");
- let p = p.build();
-
- assert_that(p.cargo("build").cwd(p.root().join("ws")),
- execs().with_status(0));
-
- assert_that(&p.root().join("foo/bar/Cargo.lock"), is_not(existing_file()));
- assert_that(&p.root().join("foo/bar/target"), is_not(existing_dir()));
-
- assert_that(p.cargo("build").cwd(p.root().join("foo/bar")),
- execs().with_status(0));
-
- assert_that(&p.root().join("foo/bar/Cargo.lock"), is_not(existing_file()));
- assert_that(&p.root().join("foo/bar/target"), is_not(existing_dir()));
-}
-
-#[test]
-fn excluded_simple() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "ws"
- version = "0.1.0"
- authors = []
-
- [workspace]
- exclude = ["foo"]
- "#)
- .file("src/lib.rs", "")
- .file("foo/Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.1.0"
- authors = []
- "#)
- .file("foo/src/lib.rs", "");
- let p = p.build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0));
- assert_that(&p.root().join("target"), existing_dir());
- assert_that(p.cargo("build").cwd(p.root().join("foo")),
- execs().with_status(0));
- assert_that(&p.root().join("foo/target"), existing_dir());
-}
-
-#[test]
-fn exclude_members_preferred() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "ws"
- version = "0.1.0"
- authors = []
-
- [workspace]
- members = ["foo/bar"]
- exclude = ["foo"]
- "#)
- .file("src/lib.rs", "")
- .file("foo/Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.1.0"
- authors = []
- "#)
- .file("foo/src/lib.rs", "")
- .file("foo/bar/Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.1.0"
- authors = []
- "#)
- .file("foo/bar/src/lib.rs", "");
- let p = p.build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0));
- assert_that(&p.root().join("target"), existing_dir());
- assert_that(p.cargo("build").cwd(p.root().join("foo")),
- execs().with_status(0));
- assert_that(&p.root().join("foo/target"), existing_dir());
- assert_that(p.cargo("build").cwd(p.root().join("foo/bar")),
- execs().with_status(0));
- assert_that(&p.root().join("foo/bar/target"), is_not(existing_dir()));
-}
-
-#[test]
-fn exclude_but_also_depend() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "ws"
- version = "0.1.0"
- authors = []
-
- [dependencies]
- bar = { path = "foo/bar" }
-
- [workspace]
- exclude = ["foo"]
- "#)
- .file("src/lib.rs", "")
- .file("foo/Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.1.0"
- authors = []
- "#)
- .file("foo/src/lib.rs", "")
- .file("foo/bar/Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.1.0"
- authors = []
- "#)
- .file("foo/bar/src/lib.rs", "");
- let p = p.build();
-
- assert_that(p.cargo("build"),
- execs().with_status(0));
- assert_that(&p.root().join("target"), existing_dir());
- assert_that(p.cargo("build").cwd(p.root().join("foo")),
- execs().with_status(0));
- assert_that(&p.root().join("foo/target"), existing_dir());
- assert_that(p.cargo("build").cwd(p.root().join("foo/bar")),
- execs().with_status(0));
- assert_that(&p.root().join("foo/bar/target"), existing_dir());
-}
-
-#[test]
-fn glob_syntax() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.1.0"
- authors = []
-
- [workspace]
- members = ["crates/*"]
- exclude = ["crates/qux"]
- "#)
- .file("src/main.rs", "fn main() {}")
- .file("crates/bar/Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.1.0"
- authors = []
- workspace = "../.."
- "#)
- .file("crates/bar/src/main.rs", "fn main() {}")
- .file("crates/baz/Cargo.toml", r#"
- [project]
- name = "baz"
- version = "0.1.0"
- authors = []
- workspace = "../.."
- "#)
- .file("crates/baz/src/main.rs", "fn main() {}")
- .file("crates/qux/Cargo.toml", r#"
- [project]
- name = "qux"
- version = "0.1.0"
- authors = []
- "#)
- .file("crates/qux/src/main.rs", "fn main() {}");
- let p = p.build();
-
- assert_that(p.cargo("build"), execs().with_status(0));
- assert_that(&p.bin("foo"), existing_file());
- assert_that(&p.bin("bar"), is_not(existing_file()));
- assert_that(&p.bin("baz"), is_not(existing_file()));
-
- assert_that(p.cargo("build").cwd(p.root().join("crates/bar")),
- execs().with_status(0));
- assert_that(&p.bin("foo"), existing_file());
- assert_that(&p.bin("bar"), existing_file());
-
- assert_that(p.cargo("build").cwd(p.root().join("crates/baz")),
- execs().with_status(0));
- assert_that(&p.bin("foo"), existing_file());
- assert_that(&p.bin("baz"), existing_file());
-
- assert_that(p.cargo("build").cwd(p.root().join("crates/qux")),
- execs().with_status(0));
- assert_that(&p.bin("qux"), is_not(existing_file()));
-
- assert_that(&p.root().join("Cargo.lock"), existing_file());
- assert_that(&p.root().join("crates/bar/Cargo.lock"), is_not(existing_file()));
- assert_that(&p.root().join("crates/baz/Cargo.lock"), is_not(existing_file()));
- assert_that(&p.root().join("crates/qux/Cargo.lock"), existing_file());
-}
-
-/*FIXME: This fails because of how workspace.exclude and workspace.members are working.
-#[test]
-fn glob_syntax_2() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.1.0"
- authors = []
-
- [workspace]
- members = ["crates/b*"]
- exclude = ["crates/q*"]
- "#)
- .file("src/main.rs", "fn main() {}")
- .file("crates/bar/Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.1.0"
- authors = []
- workspace = "../.."
- "#)
- .file("crates/bar/src/main.rs", "fn main() {}")
- .file("crates/baz/Cargo.toml", r#"
- [project]
- name = "baz"
- version = "0.1.0"
- authors = []
- workspace = "../.."
- "#)
- .file("crates/baz/src/main.rs", "fn main() {}")
- .file("crates/qux/Cargo.toml", r#"
- [project]
- name = "qux"
- version = "0.1.0"
- authors = []
- "#)
- .file("crates/qux/src/main.rs", "fn main() {}");
- p.build();
-
- assert_that(p.cargo("build"), execs().with_status(0));
- assert_that(&p.bin("foo"), existing_file());
- assert_that(&p.bin("bar"), is_not(existing_file()));
- assert_that(&p.bin("baz"), is_not(existing_file()));
-
- assert_that(p.cargo("build").cwd(p.root().join("crates/bar")),
- execs().with_status(0));
- assert_that(&p.bin("foo"), existing_file());
- assert_that(&p.bin("bar"), existing_file());
-
- assert_that(p.cargo("build").cwd(p.root().join("crates/baz")),
- execs().with_status(0));
- assert_that(&p.bin("foo"), existing_file());
- assert_that(&p.bin("baz"), existing_file());
-
- assert_that(p.cargo("build").cwd(p.root().join("crates/qux")),
- execs().with_status(0));
- assert_that(&p.bin("qux"), is_not(existing_file()));
-
- assert_that(&p.root().join("Cargo.lock"), existing_file());
- assert_that(&p.root().join("crates/bar/Cargo.lock"), is_not(existing_file()));
- assert_that(&p.root().join("crates/baz/Cargo.lock"), is_not(existing_file()));
- assert_that(&p.root().join("crates/qux/Cargo.lock"), existing_file());
-}
-*/
-
-#[test]
-fn glob_syntax_invalid_members() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.1.0"
- authors = []
-
- [workspace]
- members = ["crates/*"]
- "#)
- .file("src/main.rs", "fn main() {}")
- .file("crates/bar/src/main.rs", "fn main() {}");
- let p = p.build();
-
- assert_that(p.cargo("build"),
- execs().with_status(101)
- .with_stderr("\
-error: failed to read `[..]Cargo.toml`
-
-Caused by:
- [..]
-"));
-}
-
-/// This is a freshness test for feature use with workspaces
-///
-/// feat_lib is used by caller1 and caller2, but with different features enabled.
-/// This test ensures that alternating building caller1, caller2 doesn't force
-/// recompile of feat_lib.
-///
-/// Ideally once we solve https://github.com/rust-lang/cargo/issues/3620, then
-/// a single cargo build at the top level will be enough.
-#[test]
-fn dep_used_with_separate_features() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [workspace]
- members = ["feat_lib", "caller1", "caller2"]
- "#)
- .file("feat_lib/Cargo.toml", r#"
- [project]
- name = "feat_lib"
- version = "0.1.0"
- authors = []
-
- [features]
- myfeature = []
- "#)
- .file("feat_lib/src/lib.rs", "")
- .file("caller1/Cargo.toml", r#"
- [project]
- name = "caller1"
- version = "0.1.0"
- authors = []
-
- [dependencies]
- feat_lib = { path = "../feat_lib" }
- "#)
- .file("caller1/src/main.rs", "fn main() {}")
- .file("caller1/src/lib.rs", "")
- .file("caller2/Cargo.toml", r#"
- [project]
- name = "caller2"
- version = "0.1.0"
- authors = []
-
- [dependencies]
- feat_lib = { path = "../feat_lib", features = ["myfeature"] }
- caller1 = { path = "../caller1" }
- "#)
- .file("caller2/src/main.rs", "fn main() {}")
- .file("caller2/src/lib.rs", "");
- let p = p.build();
-
- // Build the entire workspace
- assert_that(p.cargo("build").arg("--all"),
- execs().with_status(0)
- .with_stderr("\
-[..]Compiling feat_lib v0.1.0 ([..])
-[..]Compiling caller1 v0.1.0 ([..])
-[..]Compiling caller2 v0.1.0 ([..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
- assert_that(&p.bin("caller1"), existing_file());
- assert_that(&p.bin("caller2"), existing_file());
-
-
- // Build caller1. should build the dep library. Because the features
- // are different than the full workspace, it rebuilds.
- // Ideally once we solve https://github.com/rust-lang/cargo/issues/3620, then
- // a single cargo build at the top level will be enough.
- assert_that(p.cargo("build").cwd(p.root().join("caller1")),
- execs().with_status(0)
- .with_stderr("\
-[..]Compiling feat_lib v0.1.0 ([..])
-[..]Compiling caller1 v0.1.0 ([..])
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-
- // Alternate building caller2/caller1 a few times, just to make sure
- // features are being built separately. Should not rebuild anything
- assert_that(p.cargo("build").cwd(p.root().join("caller2")),
- execs().with_status(0)
- .with_stderr("\
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
- assert_that(p.cargo("build").cwd(p.root().join("caller1")),
- execs().with_status(0)
- .with_stderr("\
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
- assert_that(p.cargo("build").cwd(p.root().join("caller2")),
- execs().with_status(0)
- .with_stderr("\
-[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
-"));
-}
-
-#[test]
-fn dont_recurse_out_of_cargo_home() {
- let git_project = git::new("dep", |project| {
- project
- .file("Cargo.toml", r#"
- [package]
- name = "dep"
- version = "0.1.0"
- "#)
- .file("src/lib.rs", "")
- .file("build.rs", r#"
- use std::env;
- use std::path::Path;
- use std::process::{self, Command};
-
- fn main() {
- let cargo = env::var_os("CARGO").unwrap();
- let cargo_manifest_dir = env::var_os("CARGO_MANIFEST_DIR").unwrap();
- let output = Command::new(cargo)
- .args(&["metadata", "--format-version", "1", "--manifest-path"])
- .arg(&Path::new(&cargo_manifest_dir).join("Cargo.toml"))
- .output()
- .unwrap();
- if !output.status.success() {
- eprintln!("{}", String::from_utf8(output.stderr).unwrap());
- process::exit(1);
- }
- }
- "#)
- }).unwrap();
- let p = project("lib")
- .file("Cargo.toml", &format!(r#"
- [package]
- name = "lib"
- version = "0.1.0"
-
- [dependencies.dep]
- git = "{}"
-
- [workspace]
- "#, git_project.url()))
- .file("src/lib.rs", "");
- let p = p.build();
-
- assert_that(p.cargo("build").env("CARGO_HOME", p.root().join(".cargo")),
- execs().with_status(0));
-}
-
-/*FIXME: This fails because of how workspace.exclude and workspace.members are working.
-#[test]
-fn include_and_exclude() {
- let p = project("foo")
- .file("Cargo.toml", r#"
- [workspace]
- members = ["foo"]
- exclude = ["foo/bar"]
- "#)
- .file("foo/Cargo.toml", r#"
- [project]
- name = "foo"
- version = "0.1.0"
- authors = []
- "#)
- .file("foo/src/lib.rs", "")
- .file("foo/bar/Cargo.toml", r#"
- [project]
- name = "bar"
- version = "0.1.0"
- authors = []
- "#)
- .file("foo/bar/src/lib.rs", "");
- p.build();
-
- assert_that(p.cargo("build").cwd(p.root().join("foo")),
- execs().with_status(0));
- assert_that(&p.root().join("target"), existing_dir());
- assert_that(&p.root().join("foo/target"), is_not(existing_dir()));
- assert_that(p.cargo("build").cwd(p.root().join("foo/bar")),
- execs().with_status(0));
- assert_that(&p.root().join("foo/bar/target"), existing_dir());
-}
-*/
-
-#[test]
-fn cargo_home_at_root_works() {
- let p = project("lib")
- .file("Cargo.toml", r#"
- [package]
- name = "lib"
- version = "0.1.0"
-
- [workspace]
- members = ["a"]
- "#)
- .file("src/lib.rs", "")
- .file("a/Cargo.toml", r#"
- [package]
- name = "a"
- version = "0.1.0"
- "#)
- .file("a/src/lib.rs", "");
- let p = p.build();
-
- assert_that(p.cargo("build"), execs().with_status(0));
- assert_that(p.cargo("build").arg("--frozen").env("CARGO_HOME", p.root()),
- execs().with_status(0));
-}
-
-#[test]
-fn relative_rustc() {
- let p = project("the_exe")
- .file("Cargo.toml", r#"
- [package]
- name = "foo"
- version = "0.1.0"
- "#)
- .file("src/main.rs", r#"
- use std::process::Command;
- use std::env;
-
- fn main() {
- let mut cmd = Command::new("rustc");
- for arg in env::args_os().skip(1) {
- cmd.arg(arg);
- }
- std::process::exit(cmd.status().unwrap().code().unwrap());
- }
- "#)
- .build();
- assert_that(p.cargo("build"), execs().with_status(0));
-
- let src = p.root()
- .join("target/debug/foo")
- .with_extension(env::consts::EXE_EXTENSION);
-
- Package::new("a", "0.1.0").publish();
-
- let p = project("lib")
- .file("Cargo.toml", r#"
- [package]
- name = "lib"
- version = "0.1.0"
-
- [dependencies]
- a = "0.1"
- "#)
- .file("src/lib.rs", "")
- .build();
-
- fs::copy(&src, p.root().join(src.file_name().unwrap())).unwrap();
-
- let file = format!("./foo{}", env::consts::EXE_SUFFIX);
- assert_that(p.cargo("build").env("RUSTC", &file),
- execs().with_status(0));
-}