summaryrefslogtreecommitdiffstats
path: root/src/tools/cargo/tests/testsuite/test.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 12:41:41 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 12:41:41 +0000
commit10ee2acdd26a7f1298c6f6d6b7af9b469fe29b87 (patch)
treebdffd5d80c26cf4a7a518281a204be1ace85b4c1 /src/tools/cargo/tests/testsuite/test.rs
parentReleasing progress-linux version 1.70.0+dfsg1-9~progress7.99u1. (diff)
downloadrustc-10ee2acdd26a7f1298c6f6d6b7af9b469fe29b87.tar.xz
rustc-10ee2acdd26a7f1298c6f6d6b7af9b469fe29b87.zip
Merging upstream version 1.70.0+dfsg2.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/tools/cargo/tests/testsuite/test.rs')
-rw-r--r--src/tools/cargo/tests/testsuite/test.rs4820
1 files changed, 4820 insertions, 0 deletions
diff --git a/src/tools/cargo/tests/testsuite/test.rs b/src/tools/cargo/tests/testsuite/test.rs
new file mode 100644
index 000000000..add0a991f
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/test.rs
@@ -0,0 +1,4820 @@
+//! Tests for the `cargo test` command.
+
+use cargo_test_support::paths::CargoPathExt;
+use cargo_test_support::registry::Package;
+use cargo_test_support::{
+ basic_bin_manifest, basic_lib_manifest, basic_manifest, cargo_exe, project,
+};
+use cargo_test_support::{cross_compile, paths};
+use cargo_test_support::{rustc_host, rustc_host_env, sleep_ms};
+use std::fs;
+
+#[cargo_test]
+fn cargo_test_simple() {
+ let p = project()
+ .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();
+
+ p.cargo("build").run();
+ assert!(p.bin("foo").is_file());
+
+ p.process(&p.bin("foo")).with_stdout("hello\n").run();
+
+ p.cargo("test")
+ .with_stderr(
+ "\
+[COMPILING] foo v0.5.0 ([CWD])
+[FINISHED] test [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] [..] (target/debug/deps/foo-[..][EXE])",
+ )
+ .with_stdout_contains("test test_hello ... ok")
+ .run();
+}
+
+#[cargo_test]
+fn cargo_test_release() {
+ let p = project()
+ .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", &basic_manifest("bar", "0.0.1"))
+ .file("bar/src/lib.rs", "pub fn bar() {}")
+ .build();
+
+ p.cargo("test -v --release")
+ .with_stderr(
+ "\
+[COMPILING] bar v0.0.1 ([CWD]/bar)
+[RUNNING] [..] -C opt-level=3 [..]
+[COMPILING] foo v0.1.0 ([CWD])
+[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[..]`",
+ )
+ .with_stdout_contains_n("test test ... ok", 2)
+ .with_stdout_contains("running 0 tests")
+ .run();
+}
+
+#[cargo_test]
+fn cargo_test_overflow_checks() {
+ let p = project()
+ .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].iter().sum::<i32>();
+ });
+ assert!(r.is_err());
+ }
+ "#,
+ )
+ .build();
+
+ p.cargo("build --release").run();
+ assert!(p.release_bin("foo").is_file());
+
+ p.process(&p.release_bin("foo")).with_stdout("").run();
+}
+
+#[cargo_test]
+fn cargo_test_quiet_with_harness() {
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+
+ [[test]]
+ name = "foo"
+ path = "src/foo.rs"
+ harness = true
+ "#,
+ )
+ .file(
+ "src/foo.rs",
+ r#"
+ fn main() {}
+ #[test] fn test_hello() {}
+ "#,
+ )
+ .build();
+
+ p.cargo("test -q")
+ .with_stdout(
+ "
+running 1 test
+.
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out[..]
+
+",
+ )
+ .with_stderr("")
+ .run();
+}
+
+#[cargo_test]
+fn cargo_test_quiet_no_harness() {
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+
+ [[bin]]
+ name = "foo"
+ test = false
+
+ [[test]]
+ name = "foo"
+ path = "src/main.rs"
+ harness = false
+ "#,
+ )
+ .file(
+ "src/main.rs",
+ r#"
+ fn main() {}
+ #[test] fn test_hello() {}
+ "#,
+ )
+ .build();
+
+ p.cargo("test -q").with_stdout("").with_stderr("").run();
+}
+
+#[cargo_test]
+fn cargo_doc_test_quiet() {
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ "#,
+ )
+ .file(
+ "src/lib.rs",
+ r#"
+ /// ```
+ /// let result = foo::add(2, 3);
+ /// assert_eq!(result, 5);
+ /// ```
+ pub fn add(a: i32, b: i32) -> i32 {
+ a + b
+ }
+
+ /// ```
+ /// let result = foo::div(10, 2);
+ /// assert_eq!(result, 5);
+ /// ```
+ ///
+ /// # Panics
+ ///
+ /// The function panics if the second argument is zero.
+ ///
+ /// ```rust,should_panic
+ /// // panics on division by zero
+ /// foo::div(10, 0);
+ /// ```
+ pub fn div(a: i32, b: i32) -> i32 {
+ if b == 0 {
+ panic!("Divide-by-zero error");
+ }
+
+ a / b
+ }
+
+ #[test] fn test_hello() {}
+ "#,
+ )
+ .build();
+
+ p.cargo("test -q")
+ .with_stdout(
+ "
+running 1 test
+.
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out[..]
+
+
+running 3 tests
+...
+test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out[..]
+
+",
+ )
+ .with_stderr("")
+ .run();
+}
+
+#[cargo_test]
+fn cargo_test_verbose() {
+ let p = project()
+ .file("Cargo.toml", &basic_bin_manifest("foo"))
+ .file(
+ "src/main.rs",
+ r#"
+ fn main() {}
+ #[test] fn test_hello() {}
+ "#,
+ )
+ .build();
+
+ p.cargo("test -v hello")
+ .with_stderr(
+ "\
+[COMPILING] foo v0.5.0 ([CWD])
+[RUNNING] `rustc [..] src/main.rs [..]`
+[FINISHED] test [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] `[CWD]/target/debug/deps/foo-[..] hello`
+",
+ )
+ .with_stdout_contains("test test_hello ... ok")
+ .run();
+}
+
+#[cargo_test]
+fn many_similar_names() {
+ let p = project()
+ .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();
+
+ p.cargo("test -v")
+ .with_stdout_contains("test bin_test ... ok")
+ .with_stdout_contains("test lib_test ... ok")
+ .with_stdout_contains("test test_test ... ok")
+ .run();
+}
+
+#[cargo_test]
+fn cargo_test_failing_test_in_bin() {
+ let p = project()
+ .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();
+
+ p.cargo("build").run();
+ assert!(p.bin("foo").is_file());
+
+ p.process(&p.bin("foo")).with_stdout("hello\n").run();
+
+ p.cargo("test")
+ .with_stderr(
+ "\
+[COMPILING] foo v0.5.0 ([CWD])
+[FINISHED] test [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] [..] (target/debug/deps/foo-[..][EXE])
+[ERROR] test failed, to rerun pass `--bin foo`",
+ )
+ .with_stdout_contains(
+ "
+running 1 test
+test test_hello ... FAILED
+
+failures:
+
+---- test_hello stdout ----
+[..]thread '[..]' 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)
+ .run();
+}
+
+#[cargo_test]
+fn cargo_test_failing_test_in_test() {
+ let p = project()
+ .file("Cargo.toml", &basic_bin_manifest("foo"))
+ .file("src/main.rs", r#"pub fn main() { println!("hello"); }"#)
+ .file(
+ "tests/footest.rs",
+ "#[test] fn test_hello() { assert!(false) }",
+ )
+ .build();
+
+ p.cargo("build").run();
+ assert!(p.bin("foo").is_file());
+
+ p.process(&p.bin("foo")).with_stdout("hello\n").run();
+
+ p.cargo("test")
+ .with_stderr(
+ "\
+[COMPILING] foo v0.5.0 ([CWD])
+[FINISHED] test [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`",
+ )
+ .with_stdout_contains("running 0 tests")
+ .with_stdout_contains(
+ "\
+running 1 test
+test test_hello ... FAILED
+
+failures:
+
+---- test_hello stdout ----
+[..]thread '[..]' panicked at 'assertion failed: false', \
+ tests/footest.rs:1[..]
+",
+ )
+ .with_stdout_contains(
+ "\
+failures:
+ test_hello
+",
+ )
+ .with_status(101)
+ .run();
+}
+
+#[cargo_test]
+fn cargo_test_failing_test_in_lib() {
+ let p = project()
+ .file("Cargo.toml", &basic_lib_manifest("foo"))
+ .file("src/lib.rs", "#[test] fn test_hello() { assert!(false) }")
+ .build();
+
+ p.cargo("test")
+ .with_stderr(
+ "\
+[COMPILING] foo v0.5.0 ([CWD])
+[FINISHED] test [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] [..] (target/debug/deps/foo-[..][EXE])
+[ERROR] test failed, to rerun pass `--lib`",
+ )
+ .with_stdout_contains(
+ "\
+test test_hello ... FAILED
+
+failures:
+
+---- test_hello stdout ----
+[..]thread '[..]' panicked at 'assertion failed: false', \
+ src/lib.rs:1[..]
+",
+ )
+ .with_stdout_contains(
+ "\
+failures:
+ test_hello
+",
+ )
+ .with_status(101)
+ .run();
+}
+
+#[cargo_test]
+fn test_with_lib_dep() {
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ 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();
+
+ p.cargo("test")
+ .with_stderr(
+ "\
+[COMPILING] foo v0.0.1 ([CWD])
+[FINISHED] test [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] [..] (target/debug/deps/foo-[..][EXE])
+[RUNNING] [..] (target/debug/deps/baz-[..][EXE])
+[DOCTEST] foo",
+ )
+ .with_stdout_contains("test lib_test ... ok")
+ .with_stdout_contains("test bin_test ... ok")
+ .with_stdout_contains_n("test [..] ... ok", 3)
+ .run();
+}
+
+#[cargo_test]
+fn test_with_deep_lib_dep() {
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.bar]
+ path = "../bar"
+ "#,
+ )
+ .file(
+ "src/lib.rs",
+ "
+ #[cfg(test)]
+ extern crate bar;
+ /// ```
+ /// foo::foo();
+ /// ```
+ pub fn foo() {}
+
+ #[test]
+ fn bar_test() {
+ bar::bar();
+ }
+ ",
+ )
+ .build();
+ let _p2 = project()
+ .at("bar")
+ .file("Cargo.toml", &basic_manifest("bar", "0.0.1"))
+ .file("src/lib.rs", "pub fn bar() {} #[test] fn foo_test() {}")
+ .build();
+
+ p.cargo("test")
+ .with_stderr(
+ "\
+[COMPILING] bar v0.0.1 ([..])
+[COMPILING] foo v0.0.1 ([CWD])
+[FINISHED] test [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] [..] (target[..])
+[DOCTEST] foo",
+ )
+ .with_stdout_contains("test bar_test ... ok")
+ .with_stdout_contains_n("test [..] ... ok", 2)
+ .run();
+}
+
+#[cargo_test]
+fn external_test_explicit() {
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ 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();
+
+ p.cargo("test")
+ .with_stderr(
+ "\
+[COMPILING] foo v0.0.1 ([CWD])
+[FINISHED] test [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] [..] (target/debug/deps/foo-[..][EXE])
+[RUNNING] [..] (target/debug/deps/test-[..][EXE])
+[DOCTEST] foo",
+ )
+ .with_stdout_contains("test internal_test ... ok")
+ .with_stdout_contains("test external_test ... ok")
+ .with_stdout_contains("running 0 tests")
+ .run();
+}
+
+#[cargo_test]
+fn external_test_named_test() {
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [[test]]
+ name = "test"
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .file("tests/test.rs", "#[test] fn foo() {}")
+ .build();
+
+ p.cargo("test").run();
+}
+
+#[cargo_test]
+fn external_test_implicit() {
+ let p = project()
+ .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();
+
+ p.cargo("test")
+ .with_stderr(
+ "\
+[COMPILING] foo v0.0.1 ([CWD])
+[FINISHED] test [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] [..] (target/debug/deps/foo-[..][EXE])
+[RUNNING] [..] (target/debug/deps/external-[..][EXE])
+[DOCTEST] foo",
+ )
+ .with_stdout_contains("test internal_test ... ok")
+ .with_stdout_contains("test external_test ... ok")
+ .with_stdout_contains("running 0 tests")
+ .run();
+}
+
+#[cargo_test]
+fn dont_run_examples() {
+ let p = project()
+ .file("src/lib.rs", "")
+ .file(
+ "examples/dont-run-me-i-will-fail.rs",
+ r#"
+ fn main() { panic!("Examples should not be run by 'cargo test'"); }
+ "#,
+ )
+ .build();
+ p.cargo("test").run();
+}
+
+#[cargo_test]
+fn pass_through_escaped() {
+ let p = project()
+ .file(
+ "src/lib.rs",
+ "
+ /// ```rust
+ /// assert!(foo::foo());
+ /// ```
+ pub fn foo() -> bool {
+ true
+ }
+
+ /// ```rust
+ /// assert!(!foo::bar());
+ /// ```
+ pub fn bar() -> bool {
+ false
+ }
+
+ #[test] fn test_foo() {
+ assert!(foo());
+ }
+ #[test] fn test_bar() {
+ assert!(!bar());
+ }
+ ",
+ )
+ .build();
+
+ p.cargo("test -- bar")
+ .with_stderr(
+ "\
+[COMPILING] foo v0.0.1 ([CWD])
+[FINISHED] test [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] [..] (target/debug/deps/foo-[..][EXE])
+[DOCTEST] foo
+",
+ )
+ .with_stdout_contains("running 1 test")
+ .with_stdout_contains("test test_bar ... ok")
+ .run();
+
+ p.cargo("test -- foo")
+ .with_stderr(
+ "\
+[FINISHED] test [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] [..] (target/debug/deps/foo-[..][EXE])
+[DOCTEST] foo
+",
+ )
+ .with_stdout_contains("running 1 test")
+ .with_stdout_contains("test test_foo ... ok")
+ .run();
+
+ p.cargo("test -- foo bar")
+ .with_stderr(
+ "\
+[FINISHED] test [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] [..] (target/debug/deps/foo-[..][EXE])
+[DOCTEST] foo
+",
+ )
+ .with_stdout_contains("running 2 tests")
+ .with_stdout_contains("test test_foo ... ok")
+ .with_stdout_contains("test test_bar ... ok")
+ .run();
+}
+
+// Unlike `pass_through_escaped`, doctests won't run when using `testname` as an optimization
+#[cargo_test]
+fn pass_through_testname() {
+ let p = project()
+ .file(
+ "src/lib.rs",
+ "
+ /// ```rust
+ /// assert!(foo::foo());
+ /// ```
+ pub fn foo() -> bool {
+ true
+ }
+
+ /// ```rust
+ /// assert!(!foo::bar());
+ /// ```
+ pub fn bar() -> bool {
+ false
+ }
+
+ #[test] fn test_foo() {
+ assert!(foo());
+ }
+ #[test] fn test_bar() {
+ assert!(!bar());
+ }
+ ",
+ )
+ .build();
+
+ p.cargo("test bar")
+ .with_stderr(
+ "\
+[COMPILING] foo v0.0.1 ([CWD])
+[FINISHED] test [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] [..] (target/debug/deps/foo-[..][EXE])
+",
+ )
+ .with_stdout_contains("running 1 test")
+ .with_stdout_contains("test test_bar ... ok")
+ .run();
+
+ p.cargo("test foo")
+ .with_stderr(
+ "\
+[FINISHED] test [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] [..] (target/debug/deps/foo-[..][EXE])
+",
+ )
+ .with_stdout_contains("running 1 test")
+ .with_stdout_contains("test test_foo ... ok")
+ .run();
+
+ p.cargo("test foo -- bar")
+ .with_stderr(
+ "\
+[FINISHED] test [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] [..] (target/debug/deps/foo-[..][EXE])
+",
+ )
+ .with_stdout_contains("running 2 tests")
+ .with_stdout_contains("test test_foo ... ok")
+ .with_stdout_contains("test test_bar ... ok")
+ .run();
+}
+
+// Regression test for running cargo-test twice with
+// tests in an rlib
+#[cargo_test]
+fn cargo_test_twice() {
+ let p = project()
+ .file("Cargo.toml", &basic_lib_manifest("foo"))
+ .file(
+ "src/foo.rs",
+ r#"
+ #![crate_type = "rlib"]
+
+ #[test]
+ fn dummy_test() { }
+ "#,
+ )
+ .build();
+
+ for _ in 0..2 {
+ p.cargo("test").run();
+ }
+}
+
+#[cargo_test]
+fn lib_bin_same_name() {
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ 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();
+
+ p.cargo("test")
+ .with_stderr(
+ "\
+[COMPILING] foo v0.0.1 ([CWD])
+[FINISHED] test [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] [..] (target/debug/deps/foo-[..][EXE])
+[RUNNING] [..] (target/debug/deps/foo-[..][EXE])
+[DOCTEST] foo",
+ )
+ .with_stdout_contains_n("test [..] ... ok", 2)
+ .with_stdout_contains("running 0 tests")
+ .run();
+}
+
+#[cargo_test]
+fn lib_with_standard_name() {
+ let p = project()
+ .file("Cargo.toml", &basic_manifest("syntax", "0.0.1"))
+ .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();
+
+ p.cargo("test")
+ .with_stderr(
+ "\
+[COMPILING] syntax v0.0.1 ([CWD])
+[FINISHED] test [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] [..] (target/debug/deps/syntax-[..][EXE])
+[RUNNING] [..] (target/debug/deps/test-[..][EXE])
+[DOCTEST] syntax",
+ )
+ .with_stdout_contains("test foo_test ... ok")
+ .with_stdout_contains("test test ... ok")
+ .with_stdout_contains_n("test [..] ... ok", 3)
+ .run();
+}
+
+#[cargo_test]
+fn lib_with_standard_name2() {
+ let p = project()
+ .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();
+
+ p.cargo("test")
+ .with_stderr(
+ "\
+[COMPILING] syntax v0.0.1 ([CWD])
+[FINISHED] test [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] [..] (target/debug/deps/syntax-[..][EXE])",
+ )
+ .with_stdout_contains("test test ... ok")
+ .run();
+}
+
+#[cargo_test]
+fn lib_without_name() {
+ let p = project()
+ .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();
+
+ p.cargo("test")
+ .with_stderr(
+ "\
+[COMPILING] syntax v0.0.1 ([CWD])
+[FINISHED] test [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] [..] (target/debug/deps/syntax-[..][EXE])",
+ )
+ .with_stdout_contains("test test ... ok")
+ .run();
+}
+
+#[cargo_test]
+fn bin_without_name() {
+ let p = project()
+ .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();
+
+ p.cargo("test")
+ .with_status(101)
+ .with_stderr(
+ "\
+[ERROR] failed to parse manifest at `[..]`
+
+Caused by:
+ binary target bin.name is required",
+ )
+ .run();
+}
+
+#[cargo_test]
+fn bench_without_name() {
+ let p = project()
+ .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();
+
+ p.cargo("test")
+ .with_status(101)
+ .with_stderr(
+ "\
+[ERROR] failed to parse manifest at `[..]`
+
+Caused by:
+ benchmark target bench.name is required",
+ )
+ .run();
+}
+
+#[cargo_test]
+fn test_without_name() {
+ let p = project()
+ .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();
+
+ p.cargo("test")
+ .with_status(101)
+ .with_stderr(
+ "\
+[ERROR] failed to parse manifest at `[..]`
+
+Caused by:
+ test target test.name is required",
+ )
+ .run();
+}
+
+#[cargo_test]
+fn example_without_name() {
+ let p = project()
+ .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();
+
+ p.cargo("test")
+ .with_status(101)
+ .with_stderr(
+ "\
+[ERROR] failed to parse manifest at `[..]`
+
+Caused by:
+ example target example.name is required",
+ )
+ .run();
+}
+
+#[cargo_test]
+fn bin_there_for_integration() {
+ let p = project()
+ .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();
+
+ p.cargo("test -v")
+ .with_stdout_contains("test main_test ... ok")
+ .with_stdout_contains("test test_test ... ok")
+ .run();
+}
+
+#[cargo_test]
+fn test_dylib() {
+ let p = project()
+ .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();
+
+ p.cargo("test")
+ .with_stderr(
+ "\
+[COMPILING] bar v0.0.1 ([CWD]/bar)
+[COMPILING] foo v0.0.1 ([CWD])
+[FINISHED] test [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)
+ .run();
+
+ p.root().move_into_the_past();
+ p.cargo("test")
+ .with_stderr(
+ "\
+[FINISHED] test [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)
+ .run();
+}
+
+#[cargo_test]
+fn test_twice_with_build_cmd() {
+ let p = project()
+ .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();
+
+ p.cargo("test")
+ .with_stderr(
+ "\
+[COMPILING] foo v0.0.1 ([CWD])
+[FINISHED] test [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")
+ .run();
+
+ p.cargo("test")
+ .with_stderr(
+ "\
+[FINISHED] test [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")
+ .run();
+}
+
+#[cargo_test]
+fn test_then_build() {
+ let p = project().file("src/lib.rs", "#[test] fn foo() {}").build();
+
+ p.cargo("test")
+ .with_stderr(
+ "\
+[COMPILING] foo v0.0.1 ([CWD])
+[FINISHED] test [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")
+ .run();
+
+ p.cargo("build").with_stdout("").run();
+}
+
+#[cargo_test]
+fn test_no_run() {
+ let p = project()
+ .file("src/lib.rs", "#[test] fn foo() { panic!() }")
+ .build();
+
+ p.cargo("test --no-run")
+ .with_stderr(
+ "\
+[COMPILING] foo v0.0.1 ([CWD])
+[FINISHED] test [unoptimized + debuginfo] target(s) in [..]
+[EXECUTABLE] unittests src/lib.rs (target/debug/deps/foo-[..][EXE])
+",
+ )
+ .run();
+}
+
+#[cargo_test]
+fn test_no_run_emit_json() {
+ let p = project()
+ .file("src/lib.rs", "#[test] fn foo() { panic!() }")
+ .build();
+
+ p.cargo("test --no-run --message-format json")
+ .with_stderr(
+ "\
+[COMPILING] foo v0.0.1 ([CWD])
+[FINISHED] test [unoptimized + debuginfo] target(s) in [..]
+",
+ )
+ .run();
+}
+
+#[cargo_test]
+fn test_run_specific_bin_target() {
+ let prj = project()
+ .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();
+
+ prj.cargo("test --bin bin2")
+ .with_stderr(
+ "\
+[COMPILING] foo v0.0.1 ([CWD])
+[FINISHED] test [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] [..] (target/debug/deps/bin2-[..][EXE])",
+ )
+ .with_stdout_contains("test test2 ... ok")
+ .run();
+}
+
+#[cargo_test]
+fn test_run_implicit_bin_target() {
+ let prj = project()
+ .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();
+
+ prj.cargo("test --bins")
+ .with_stderr(
+ "\
+[COMPILING] foo v0.0.1 ([CWD])
+[FINISHED] test [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] [..] (target/debug/deps/mybin-[..][EXE])",
+ )
+ .with_stdout_contains("test test_in_bin ... ok")
+ .run();
+}
+
+#[cargo_test]
+fn test_run_specific_test_target() {
+ let prj = project()
+ .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();
+
+ prj.cargo("test --test b")
+ .with_stderr(
+ "\
+[COMPILING] foo v0.0.1 ([CWD])
+[FINISHED] test [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] [..] (target/debug/deps/b-[..][EXE])",
+ )
+ .with_stdout_contains("test test_b ... ok")
+ .run();
+}
+
+#[cargo_test]
+fn test_run_implicit_test_target() {
+ let prj = project()
+ .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",
+ "fn main() { compile_error!(\"Don't build me!\"); }",
+ )
+ .build();
+
+ prj.cargo("test --tests")
+ .with_stderr(
+ "\
+[COMPILING] foo v0.0.1 ([CWD])
+[FINISHED] test [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] [..] (target/debug/deps/mybin-[..][EXE])
+[RUNNING] [..] (target/debug/deps/mytest-[..][EXE])",
+ )
+ .with_stdout_contains("test test_in_test ... ok")
+ .run();
+}
+
+#[cargo_test]
+fn test_run_implicit_bench_target() {
+ let prj = project()
+ .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",
+ "fn main() { compile_error!(\"Don't build me!\"); }",
+ )
+ .build();
+
+ prj.cargo("test --benches")
+ .with_stderr(
+ "\
+[COMPILING] foo v0.0.1 ([CWD])
+[FINISHED] test [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] [..] (target/debug/deps/mybin-[..][EXE])
+[RUNNING] [..] (target/debug/deps/mybench-[..][EXE])",
+ )
+ .with_stdout_contains("test test_in_bench ... ok")
+ .run();
+}
+
+#[cargo_test]
+fn test_run_implicit_example_target() {
+ let prj = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [[bin]]
+ name = "mybin"
+ path = "src/mybin.rs"
+
+ [[example]]
+ name = "myexm1"
+
+ [[example]]
+ name = "myexm2"
+ test = true
+ "#,
+ )
+ .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/myexm1.rs",
+ "#[test] fn test_in_exm() { }
+ fn main() { panic!(\"Don't execute me!\"); }",
+ )
+ .file(
+ "examples/myexm2.rs",
+ "#[test] fn test_in_exm() { }
+ fn main() { panic!(\"Don't execute me!\"); }",
+ )
+ .build();
+
+ // Compiles myexm1 as normal, but does not run it.
+ prj.cargo("test -v")
+ .with_stderr_contains("[RUNNING] `rustc [..]myexm1.rs [..]--crate-type bin[..]")
+ .with_stderr_contains("[RUNNING] `rustc [..]myexm2.rs [..]--test[..]")
+ .with_stderr_does_not_contain("[RUNNING] [..]myexm1-[..]")
+ .with_stderr_contains("[RUNNING] [..]target/debug/examples/myexm2-[..]")
+ .run();
+
+ // Only tests myexm2.
+ prj.cargo("test --tests")
+ .with_stderr_does_not_contain("[RUNNING] [..]myexm1-[..]")
+ .with_stderr_contains("[RUNNING] [..]target/debug/examples/myexm2-[..]")
+ .run();
+
+ // Tests all examples.
+ prj.cargo("test --examples")
+ .with_stderr_contains("[RUNNING] [..]target/debug/examples/myexm1-[..]")
+ .with_stderr_contains("[RUNNING] [..]target/debug/examples/myexm2-[..]")
+ .run();
+
+ // Test an example, even without `test` set.
+ prj.cargo("test --example myexm1")
+ .with_stderr_contains("[RUNNING] [..]target/debug/examples/myexm1-[..]")
+ .run();
+
+ // Tests all examples.
+ prj.cargo("test --all-targets")
+ .with_stderr_contains("[RUNNING] [..]target/debug/examples/myexm1-[..]")
+ .with_stderr_contains("[RUNNING] [..]target/debug/examples/myexm2-[..]")
+ .run();
+}
+
+#[cargo_test]
+fn test_filtered_excludes_compiling_examples() {
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [[bin]]
+ name = "mybin"
+ test = false
+ "#,
+ )
+ .file(
+ "src/lib.rs",
+ "#[cfg(test)] mod tests { #[test] fn test_in_lib() { } }",
+ )
+ .file(
+ "src/bin/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() { assert!(false) }",
+ )
+ .file(
+ "examples/myexm1.rs",
+ "#[test] fn test_in_exm() { assert!(false) }
+ fn main() { panic!(\"Don't execute me!\"); }",
+ )
+ .build();
+
+ p.cargo("test -v test_in_")
+ .with_stdout(
+ "
+running 1 test
+test tests::test_in_lib ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out[..]
+
+
+running 1 test
+test test_in_test ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out[..]
+
+",
+ )
+ .with_stderr_unordered(
+ "\
+[COMPILING] foo v0.0.1 ([CWD])
+[RUNNING] `rustc --crate-name foo src/lib.rs [..] --crate-type lib [..]`
+[RUNNING] `rustc --crate-name foo src/lib.rs [..] --test [..]`
+[RUNNING] `rustc --crate-name mybin src/bin/mybin.rs [..] --crate-type bin [..]`
+[RUNNING] `rustc --crate-name mytest tests/mytest.rs [..] --test [..]`
+[FINISHED] test [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] `[CWD]/target/debug/deps/foo-[..] test_in_`
+[RUNNING] `[CWD]/target/debug/deps/mytest-[..] test_in_`
+",
+ )
+ .with_stderr_does_not_contain("[RUNNING][..]rustc[..]myexm1[..]")
+ .with_stderr_does_not_contain("[RUNNING][..]deps/mybin-[..] test_in_")
+ .run();
+}
+
+#[cargo_test]
+fn test_no_harness() {
+ let p = project()
+ .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();
+
+ p.cargo("test -- --nocapture")
+ .with_stderr(
+ "\
+[COMPILING] foo v0.0.1 ([CWD])
+[FINISHED] test [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] [..] (target/debug/deps/bar-[..][EXE])
+",
+ )
+ .run();
+}
+
+#[cargo_test]
+fn selective_testing() {
+ let p = project()
+ .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");
+ p.cargo("test -p d1")
+ .with_stderr(
+ "\
+[COMPILING] d1 v0.0.1 ([CWD]/d1)
+[FINISHED] test [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] [..] (target/debug/deps/d1-[..][EXE])
+[RUNNING] [..] (target/debug/deps/d1-[..][EXE])",
+ )
+ .with_stdout_contains_n("running 0 tests", 2)
+ .run();
+
+ println!("d2");
+ p.cargo("test -p d2")
+ .with_stderr(
+ "\
+[COMPILING] d2 v0.0.1 ([CWD]/d2)
+[FINISHED] test [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] [..] (target/debug/deps/d2-[..][EXE])
+[RUNNING] [..] (target/debug/deps/d2-[..][EXE])",
+ )
+ .with_stdout_contains_n("running 0 tests", 2)
+ .run();
+
+ println!("whole");
+ p.cargo("test")
+ .with_stderr(
+ "\
+[COMPILING] foo v0.0.1 ([CWD])
+[FINISHED] test [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] [..] (target/debug/deps/foo-[..][EXE])",
+ )
+ .with_stdout_contains("running 0 tests")
+ .run();
+}
+
+#[cargo_test]
+fn almost_cyclic_but_not_quite() {
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ 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.foo]
+ path = ".."
+ "#,
+ )
+ .file(
+ "b/src/lib.rs",
+ r#"
+ #[allow(unused_extern_crates)]
+ extern crate foo;
+ "#,
+ )
+ .file("c/Cargo.toml", &basic_manifest("c", "0.0.1"))
+ .file("c/src/lib.rs", "")
+ .build();
+
+ p.cargo("build").run();
+ p.cargo("test").run();
+}
+
+#[cargo_test]
+fn build_then_selective_test() {
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ 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 foo;
+ fn main() {}
+ "#,
+ )
+ .file("b/Cargo.toml", &basic_manifest("b", "0.0.1"))
+ .file("b/src/lib.rs", "")
+ .build();
+
+ p.cargo("build").run();
+ p.root().move_into_the_past();
+ p.cargo("test -p b").run();
+}
+
+#[cargo_test]
+fn example_dev_dep() {
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dev-dependencies.bar]
+ path = "bar"
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .file("examples/e1.rs", "extern crate bar; fn main() {}")
+ .file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1"))
+ .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();
+ p.cargo("test").run();
+ p.cargo("run --example e1 --release -v").run();
+}
+
+#[cargo_test]
+fn selective_testing_with_docs() {
+ let p = project()
+ .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();
+
+ p.cargo("test -p d1")
+ .with_stderr(
+ "\
+[COMPILING] d1 v0.0.1 ([CWD]/d1)
+[FINISHED] test [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] [..] (target/debug/deps/d1[..][EXE])
+[DOCTEST] d1",
+ )
+ .with_stdout_contains_n("running 0 tests", 2)
+ .run();
+}
+
+#[cargo_test]
+fn example_bin_same_name() {
+ let p = project()
+ .file("src/bin/foo.rs", r#"fn main() { println!("bin"); }"#)
+ .file("examples/foo.rs", r#"fn main() { println!("example"); }"#)
+ .build();
+
+ p.cargo("test --no-run -v")
+ .with_stderr(
+ "\
+[COMPILING] foo v0.0.1 ([CWD])
+[RUNNING] `rustc [..]`
+[RUNNING] `rustc [..]`
+[FINISHED] test [unoptimized + debuginfo] target(s) in [..]
+[EXECUTABLE] `[..]/target/debug/deps/foo-[..][EXE]`
+",
+ )
+ .run();
+
+ assert!(!p.bin("foo").is_file());
+ assert!(p.bin("examples/foo").is_file());
+
+ p.process(&p.bin("examples/foo"))
+ .with_stdout("example\n")
+ .run();
+
+ p.cargo("run")
+ .with_stderr(
+ "\
+[COMPILING] foo v0.0.1 ([..])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] [..]",
+ )
+ .with_stdout("bin")
+ .run();
+ assert!(p.bin("foo").is_file());
+}
+
+#[cargo_test]
+fn test_with_example_twice() {
+ let p = project()
+ .file("src/bin/foo.rs", r#"fn main() { println!("bin"); }"#)
+ .file("examples/foo.rs", r#"fn main() { println!("example"); }"#)
+ .build();
+
+ println!("first");
+ p.cargo("test -v").run();
+ assert!(p.bin("examples/foo").is_file());
+ println!("second");
+ p.cargo("test -v").run();
+ assert!(p.bin("examples/foo").is_file());
+}
+
+#[cargo_test]
+fn example_with_dev_dep() {
+ let p = project()
+ .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", &basic_manifest("a", "0.0.1"))
+ .file("a/src/lib.rs", "")
+ .build();
+
+ p.cargo("test -v")
+ .with_stderr(
+ "\
+[..]
+[..]
+[..]
+[..]
+[RUNNING] `rustc --crate-name ex [..] --extern a=[..]`
+[FINISHED] test [unoptimized + debuginfo] target(s) in [..]
+",
+ )
+ .run();
+}
+
+#[cargo_test]
+fn bin_is_preserved() {
+ let p = project()
+ .file("src/lib.rs", "")
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ p.cargo("build -v").run();
+ assert!(p.bin("foo").is_file());
+
+ println!("test");
+ p.cargo("test -v").run();
+ assert!(p.bin("foo").is_file());
+}
+
+#[cargo_test]
+fn bad_example() {
+ let p = project().file("src/lib.rs", "");
+ let p = p.build();
+
+ p.cargo("run --example foo")
+ .with_status(101)
+ .with_stderr(
+ "\
+[ERROR] no example target named `foo`.
+
+",
+ )
+ .run();
+ p.cargo("run --bin foo")
+ .with_status(101)
+ .with_stderr(
+ "\
+[ERROR] no bin target named `foo`.
+
+",
+ )
+ .run();
+}
+
+#[cargo_test]
+fn doctest_feature() {
+ let p = project()
+ .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();
+
+ p.cargo("test --features bar")
+ .with_stderr(
+ "\
+[COMPILING] foo [..]
+[FINISHED] test [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] [..] (target/debug/deps/foo[..][EXE])
+[DOCTEST] foo",
+ )
+ .with_stdout_contains("running 0 tests")
+ .with_stdout_contains("test [..] ... ok")
+ .run();
+}
+
+#[cargo_test]
+fn dashes_to_underscores() {
+ let p = project()
+ .file("Cargo.toml", &basic_manifest("foo-bar", "0.0.1"))
+ .file(
+ "src/lib.rs",
+ r#"
+ /// ```
+ /// assert_eq!(foo_bar::foo(), 1);
+ /// ```
+ pub fn foo() -> i32 { 1 }
+ "#,
+ )
+ .build();
+
+ p.cargo("test -v").run();
+}
+
+#[cargo_test]
+fn doctest_dev_dep() {
+ let p = project()
+ .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", &basic_manifest("b", "0.0.1"))
+ .file("b/src/lib.rs", "")
+ .build();
+
+ p.cargo("test -v").run();
+}
+
+#[cargo_test]
+fn filter_no_doc_tests() {
+ let p = project()
+ .file(
+ "src/lib.rs",
+ r#"
+ /// ```
+ /// extern crate b;
+ /// ```
+ pub fn foo() {}
+ "#,
+ )
+ .file("tests/foo.rs", "")
+ .build();
+
+ p.cargo("test --test=foo")
+ .with_stderr(
+ "\
+[COMPILING] foo v0.0.1 ([..])
+[FINISHED] test [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] [..] (target/debug/deps/foo[..][EXE])",
+ )
+ .with_stdout_contains("running 0 tests")
+ .run();
+}
+
+#[cargo_test]
+fn dylib_doctest() {
+ let p = project()
+ .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();
+
+ p.cargo("test")
+ .with_stderr(
+ "\
+[COMPILING] foo v0.0.1 ([..])
+[FINISHED] test [unoptimized + debuginfo] target(s) in [..]
+[DOCTEST] foo",
+ )
+ .with_stdout_contains("test [..] ... ok")
+ .run();
+}
+
+#[cargo_test]
+fn dylib_doctest2() {
+ // Can't doc-test dylibs, as they're statically linked together.
+ let p = project()
+ .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();
+
+ p.cargo("test").with_stdout("").run();
+}
+
+#[cargo_test]
+fn cyclic_dev_dep_doc_test() {
+ let p = project()
+ .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();
+ p.cargo("test")
+ .with_stderr(
+ "\
+[COMPILING] foo v0.0.1 ([..])
+[COMPILING] bar v0.0.1 ([..])
+[FINISHED] test [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] [..] (target/debug/deps/foo[..][EXE])
+[DOCTEST] foo",
+ )
+ .with_stdout_contains("running 0 tests")
+ .with_stdout_contains("test [..] ... ok")
+ .run();
+}
+
+#[cargo_test]
+fn dev_dep_with_build_script() {
+ let p = project()
+ .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();
+ p.cargo("test").run();
+}
+
+#[cargo_test]
+fn no_fail_fast() {
+ let p = project()
+ .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();
+ p.cargo("test --no-fail-fast")
+ .with_status(101)
+ .with_stderr(
+ "\
+[COMPILING] foo v0.0.1 [..]
+[FINISHED] test [..]
+[RUNNING] unittests src/lib.rs (target/debug/deps/foo[..])
+[RUNNING] tests/test_add_one.rs (target/debug/deps/test_add_one[..])
+[ERROR] test failed, to rerun pass `--test test_add_one`
+[RUNNING] tests/test_sub_one.rs (target/debug/deps/test_sub_one[..])
+[DOCTEST] foo
+[ERROR] 1 target failed:
+ `--test test_add_one`
+",
+ )
+ .with_stdout_contains("running 0 tests")
+ .with_stdout_contains("test result: FAILED. [..]")
+ .with_stdout_contains("test sub_one_test ... ok")
+ .with_stdout_contains_n("test [..] ... ok", 3)
+ .run();
+}
+
+#[cargo_test]
+fn test_multiple_packages() {
+ let p = project()
+ .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();
+
+ p.cargo("test -p d1 -p d2")
+ .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)
+ .run();
+}
+
+#[cargo_test]
+fn bin_does_not_rebuild_tests() {
+ let p = project()
+ .file("src/lib.rs", "")
+ .file("src/main.rs", "fn main() {}")
+ .file("tests/foo.rs", "");
+ let p = p.build();
+
+ p.cargo("test -v").run();
+
+ sleep_ms(1000);
+ fs::write(p.root().join("src/main.rs"), "fn main() { 3; }").unwrap();
+
+ p.cargo("test -v --no-run")
+ .with_stderr(
+ "\
+[DIRTY] foo v0.0.1 ([..]): the file `src/main.rs` has changed ([..])
+[COMPILING] foo v0.0.1 ([..])
+[RUNNING] `rustc [..] src/main.rs [..]`
+[RUNNING] `rustc [..] src/main.rs [..]`
+[FINISHED] test [unoptimized + debuginfo] target(s) in [..]
+[EXECUTABLE] `[..]/target/debug/deps/foo-[..][EXE]`
+[EXECUTABLE] `[..]/target/debug/deps/foo-[..][EXE]`
+[EXECUTABLE] `[..]/target/debug/deps/foo-[..][EXE]`
+",
+ )
+ .run();
+}
+
+#[cargo_test]
+fn selective_test_wonky_profile() {
+ let p = project()
+ .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", &basic_manifest("a", "0.0.1"))
+ .file("a/src/lib.rs", "");
+ let p = p.build();
+
+ p.cargo("test -v --no-run --release -p foo -p a").run();
+}
+
+#[cargo_test]
+fn selective_test_optional_dep() {
+ let p = project()
+ .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", &basic_manifest("a", "0.0.1"))
+ .file("a/src/lib.rs", "");
+ let p = p.build();
+
+ p.cargo("test -v --no-run --features a -p a")
+ .with_stderr(
+ "\
+[COMPILING] a v0.0.1 ([..])
+[RUNNING] `rustc [..] a/src/lib.rs [..]`
+[RUNNING] `rustc [..] a/src/lib.rs [..]`
+[FINISHED] test [unoptimized + debuginfo] target(s) in [..]
+[EXECUTABLE] `[..]/target/debug/deps/a-[..][EXE]`
+",
+ )
+ .run();
+}
+
+#[cargo_test]
+fn only_test_docs() {
+ let p = project()
+ .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();
+
+ p.cargo("test --doc")
+ .with_stderr(
+ "\
+[COMPILING] foo v0.0.1 ([..])
+[FINISHED] test [unoptimized + debuginfo] target(s) in [..]
+[DOCTEST] foo",
+ )
+ .with_stdout_contains("test [..] ... ok")
+ .run();
+}
+
+#[cargo_test]
+fn test_panic_abort_with_dep() {
+ let p = project()
+ .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", &basic_manifest("bar", "0.0.1"))
+ .file("bar/src/lib.rs", "")
+ .build();
+ p.cargo("test -v").run();
+}
+
+#[cargo_test]
+fn cfg_test_even_with_no_harness() {
+ let p = project()
+ .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();
+ p.cargo("test -v")
+ .with_stdout("hello!\n")
+ .with_stderr(
+ "\
+[COMPILING] foo v0.0.1 ([..])
+[RUNNING] `rustc [..]`
+[FINISHED] test [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] `[..]`
+",
+ )
+ .run();
+}
+
+#[cargo_test]
+fn panic_abort_multiple() {
+ let p = project()
+ .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", &basic_manifest("a", "0.0.1"))
+ .file("a/src/lib.rs", "")
+ .build();
+ p.cargo("test --release -v -p foo -p a").run();
+}
+
+#[cargo_test]
+fn pass_correct_cfgs_flags_to_rustdoc() {
+ let p = project()
+ .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",
+ &basic_manifest("mock_serde_derive", "0.1.0"),
+ )
+ .file("libs/mock_serde_derive/src/lib.rs", "")
+ .file(
+ "libs/mock_serde_codegen/Cargo.toml",
+ &basic_manifest("mock_serde_codegen", "0.1.0"),
+ )
+ .file("libs/mock_serde_codegen/src/lib.rs", "");
+ let p = p.build();
+
+ p.cargo("test --package feature_a --verbose")
+ .with_stderr_contains(
+ "\
+[DOCTEST] feature_a
+[RUNNING] `rustdoc [..]--test [..]mock_serde_codegen[..]`",
+ )
+ .run();
+
+ p.cargo("test --verbose")
+ .with_stderr_contains(
+ "\
+[DOCTEST] foo
+[RUNNING] `rustdoc [..]--test [..]feature_a[..]`",
+ )
+ .run();
+}
+
+#[cargo_test]
+fn test_release_ignore_panic() {
+ let p = project()
+ .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", &basic_manifest("a", "0.0.1"))
+ .file("a/src/lib.rs", "");
+ let p = p.build();
+ println!("test");
+ p.cargo("test -v").run();
+ println!("bench");
+ p.cargo("bench -v").run();
+}
+
+#[cargo_test]
+fn test_many_with_features() {
+ let p = project()
+ .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", &basic_manifest("a", "0.0.1"))
+ .file("a/src/lib.rs", "")
+ .build();
+
+ p.cargo("test -v -p a -p foo --features foo").run();
+}
+
+#[cargo_test]
+fn test_all_workspace() {
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+
+ [dependencies]
+ bar = { path = "bar" }
+
+ [workspace]
+ "#,
+ )
+ .file("src/main.rs", "#[test] fn foo_test() {}")
+ .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0"))
+ .file("bar/src/lib.rs", "#[test] fn bar_test() {}")
+ .build();
+
+ p.cargo("test --workspace")
+ .with_stdout_contains("test foo_test ... ok")
+ .with_stdout_contains("test bar_test ... ok")
+ .run();
+}
+
+#[cargo_test]
+fn test_all_exclude() {
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+
+ [workspace]
+ members = ["bar", "baz"]
+ "#,
+ )
+ .file("src/main.rs", "fn main() {}")
+ .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0"))
+ .file("bar/src/lib.rs", "#[test] pub fn bar() {}")
+ .file("baz/Cargo.toml", &basic_manifest("baz", "0.1.0"))
+ .file("baz/src/lib.rs", "#[test] pub fn baz() { assert!(false); }")
+ .build();
+
+ p.cargo("test --workspace --exclude baz")
+ .with_stdout_contains(
+ "running 1 test
+test bar ... ok",
+ )
+ .run();
+}
+
+#[cargo_test]
+fn test_all_exclude_not_found() {
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+
+ [workspace]
+ members = ["bar"]
+ "#,
+ )
+ .file("src/main.rs", "fn main() {}")
+ .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0"))
+ .file("bar/src/lib.rs", "#[test] pub fn bar() {}")
+ .build();
+
+ p.cargo("test --workspace --exclude baz")
+ .with_stderr_contains("[WARNING] excluded package(s) `baz` not found in workspace [..]")
+ .with_stdout_contains(
+ "running 1 test
+test bar ... ok",
+ )
+ .run();
+}
+
+#[cargo_test]
+fn test_all_exclude_glob() {
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+
+ [workspace]
+ members = ["bar", "baz"]
+ "#,
+ )
+ .file("src/main.rs", "fn main() {}")
+ .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0"))
+ .file("bar/src/lib.rs", "#[test] pub fn bar() {}")
+ .file("baz/Cargo.toml", &basic_manifest("baz", "0.1.0"))
+ .file("baz/src/lib.rs", "#[test] pub fn baz() { assert!(false); }")
+ .build();
+
+ p.cargo("test --workspace --exclude '*z'")
+ .with_stdout_contains(
+ "running 1 test
+test bar ... ok",
+ )
+ .run();
+}
+
+#[cargo_test]
+fn test_all_exclude_glob_not_found() {
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+
+ [workspace]
+ members = ["bar"]
+ "#,
+ )
+ .file("src/main.rs", "fn main() {}")
+ .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0"))
+ .file("bar/src/lib.rs", "#[test] pub fn bar() {}")
+ .build();
+
+ p.cargo("test --workspace --exclude '*z'")
+ .with_stderr_contains(
+ "[WARNING] excluded package pattern(s) `*z` not found in workspace [..]",
+ )
+ .with_stdout_contains(
+ "running 1 test
+test bar ... ok",
+ )
+ .run();
+}
+
+#[cargo_test]
+fn test_all_exclude_broken_glob() {
+ let p = project().file("src/main.rs", "fn main() {}").build();
+
+ p.cargo("test --workspace --exclude '[*z'")
+ .with_status(101)
+ .with_stderr_contains("[ERROR] cannot build glob pattern from `[*z`")
+ .run();
+}
+
+#[cargo_test]
+fn test_all_virtual_manifest() {
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [workspace]
+ members = ["a", "b"]
+ "#,
+ )
+ .file("a/Cargo.toml", &basic_manifest("a", "0.1.0"))
+ .file("a/src/lib.rs", "#[test] fn a() {}")
+ .file("b/Cargo.toml", &basic_manifest("b", "0.1.0"))
+ .file("b/src/lib.rs", "#[test] fn b() {}")
+ .build();
+
+ p.cargo("test --workspace")
+ .with_stdout_contains("running 1 test\ntest a ... ok")
+ .with_stdout_contains("running 1 test\ntest b ... ok")
+ .run();
+}
+
+#[cargo_test]
+fn test_virtual_manifest_all_implied() {
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [workspace]
+ members = ["a", "b"]
+ "#,
+ )
+ .file("a/Cargo.toml", &basic_manifest("a", "0.1.0"))
+ .file("a/src/lib.rs", "#[test] fn a() {}")
+ .file("b/Cargo.toml", &basic_manifest("b", "0.1.0"))
+ .file("b/src/lib.rs", "#[test] fn b() {}")
+ .build();
+
+ p.cargo("test")
+ .with_stdout_contains("running 1 test\ntest a ... ok")
+ .with_stdout_contains("running 1 test\ntest b ... ok")
+ .run();
+}
+
+#[cargo_test]
+fn test_virtual_manifest_one_project() {
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [workspace]
+ members = ["bar", "baz"]
+ "#,
+ )
+ .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0"))
+ .file("bar/src/lib.rs", "#[test] fn bar() {}")
+ .file("baz/Cargo.toml", &basic_manifest("baz", "0.1.0"))
+ .file("baz/src/lib.rs", "#[test] fn baz() { assert!(false); }")
+ .build();
+
+ p.cargo("test -p bar")
+ .with_stdout_contains("running 1 test\ntest bar ... ok")
+ .with_stdout_does_not_contain("running 1 test\ntest baz ... ok")
+ .run();
+}
+
+#[cargo_test]
+fn test_virtual_manifest_glob() {
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [workspace]
+ members = ["bar", "baz"]
+ "#,
+ )
+ .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0"))
+ .file("bar/src/lib.rs", "#[test] fn bar() { assert!(false); }")
+ .file("baz/Cargo.toml", &basic_manifest("baz", "0.1.0"))
+ .file("baz/src/lib.rs", "#[test] fn baz() {}")
+ .build();
+
+ p.cargo("test -p '*z'")
+ .with_stdout_does_not_contain("running 1 test\ntest bar ... ok")
+ .with_stdout_contains("running 1 test\ntest baz ... ok")
+ .run();
+}
+
+#[cargo_test]
+fn test_virtual_manifest_glob_not_found() {
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [workspace]
+ members = ["bar"]
+ "#,
+ )
+ .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0"))
+ .file("bar/src/lib.rs", "#[test] fn bar() {}")
+ .build();
+
+ p.cargo("test -p bar -p '*z'")
+ .with_status(101)
+ .with_stderr("[ERROR] package pattern(s) `*z` not found in workspace [..]")
+ .run();
+}
+
+#[cargo_test]
+fn test_virtual_manifest_broken_glob() {
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [workspace]
+ members = ["bar"]
+ "#,
+ )
+ .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0"))
+ .file("bar/src/lib.rs", "#[test] fn bar() {}")
+ .build();
+
+ p.cargo("test -p '[*z'")
+ .with_status(101)
+ .with_stderr_contains("[ERROR] cannot build glob pattern from `[*z`")
+ .run();
+}
+
+#[cargo_test]
+fn test_all_member_dependency_same_name() {
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [workspace]
+ members = ["a"]
+ "#,
+ )
+ .file(
+ "a/Cargo.toml",
+ r#"
+ [package]
+ name = "a"
+ version = "0.1.0"
+
+ [dependencies]
+ a = "0.1.0"
+ "#,
+ )
+ .file("a/src/lib.rs", "#[test] fn a() {}")
+ .build();
+
+ Package::new("a", "0.1.0").publish();
+
+ p.cargo("test --workspace")
+ .with_stdout_contains("test a ... ok")
+ .run();
+}
+
+#[cargo_test]
+fn doctest_only_with_dev_dep() {
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ 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", &basic_manifest("b", "0.1.0"))
+ .file("b/src/lib.rs", "pub fn b() {}")
+ .build();
+
+ p.cargo("test --doc -v").run();
+}
+
+#[cargo_test]
+fn test_many_targets() {
+ let p = project()
+ .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", "#[test] fn example_c() { panic!(); }")
+ .file("tests/a.rs", "#[test] fn test_a() {}")
+ .file("tests/b.rs", "#[test] fn test_b() {}")
+ .file("tests/c.rs", "does not compile")
+ .build();
+
+ p.cargo("test --verbose --bin a --bin b --example a --example b --test a --test b")
+ .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 [..]`")
+ .run();
+}
+
+#[cargo_test]
+fn doctest_and_registry() {
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "a"
+ version = "0.1.0"
+
+ [dependencies]
+ b = { path = "b" }
+ c = { path = "c" }
+
+ [workspace]
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .file("b/Cargo.toml", &basic_manifest("b", "0.1.0"))
+ .file(
+ "b/src/lib.rs",
+ "
+ /// ```
+ /// b::foo();
+ /// ```
+ pub fn foo() {}
+ ",
+ )
+ .file(
+ "c/Cargo.toml",
+ r#"
+ [package]
+ name = "c"
+ version = "0.1.0"
+
+ [dependencies]
+ b = "0.1"
+ "#,
+ )
+ .file("c/src/lib.rs", "")
+ .build();
+
+ Package::new("b", "0.1.0").publish();
+
+ p.cargo("test --workspace -v").run();
+}
+
+#[cargo_test]
+fn cargo_test_env() {
+ let src = format!(
+ r#"
+ #![crate_type = "rlib"]
+
+ #[test]
+ fn env_test() {{
+ use std::env;
+ eprintln!("{{}}", env::var("{}").unwrap());
+ }}
+ "#,
+ cargo::CARGO_ENV
+ );
+
+ let p = project()
+ .file("Cargo.toml", &basic_lib_manifest("foo"))
+ .file("src/lib.rs", &src)
+ .build();
+
+ let cargo = cargo_exe().canonicalize().unwrap();
+ p.cargo("test --lib -- --nocapture")
+ .with_stderr_contains(cargo.to_str().unwrap())
+ .with_stdout_contains("test env_test ... ok")
+ .run();
+
+ // Check that `cargo test` propagates the environment's $CARGO
+ let rustc = cargo_util::paths::resolve_executable("rustc".as_ref())
+ .unwrap()
+ .canonicalize()
+ .unwrap();
+ let rustc = rustc.to_str().unwrap();
+ p.cargo("test --lib -- --nocapture")
+ // we use rustc since $CARGO is only used if it points to a path that exists
+ .env(cargo::CARGO_ENV, rustc)
+ .with_stderr_contains(rustc)
+ .with_stdout_contains("test env_test ... ok")
+ .run();
+}
+
+#[cargo_test]
+fn test_order() {
+ let p = project()
+ .file("src/lib.rs", "#[test] fn test_lib() {}")
+ .file("tests/a.rs", "#[test] fn test_a() {}")
+ .file("tests/z.rs", "#[test] fn test_z() {}")
+ .build();
+
+ p.cargo("test --workspace")
+ .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. [..]
+",
+ )
+ .run();
+}
+
+#[cargo_test]
+fn cyclic_dev() {
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+
+ [dev-dependencies]
+ foo = { path = "." }
+ "#,
+ )
+ .file("src/lib.rs", "#[test] fn test_lib() {}")
+ .file("tests/foo.rs", "extern crate foo;")
+ .build();
+
+ p.cargo("test --workspace").run();
+}
+
+#[cargo_test]
+fn publish_a_crate_without_tests() {
+ Package::new("testless", "0.1.0")
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ 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()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+
+ [dependencies]
+ testless = "0.1.0"
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .build();
+
+ p.cargo("test").run();
+ p.cargo("test --package testless").run();
+}
+
+#[cargo_test]
+fn find_dependency_of_proc_macro_dependency_with_target() {
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [workspace]
+ members = ["root", "proc_macro_dep"]
+ "#,
+ )
+ .file(
+ "root/Cargo.toml",
+ r#"
+ [package]
+ 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#"
+ [package]
+ name = "proc_macro_dep"
+ version = "0.1.0"
+ authors = []
+
+ [lib]
+ proc-macro = true
+
+ [dependencies]
+ baz = "^0.1"
+ "#,
+ )
+ .file(
+ "proc_macro_dep/src/lib.rs",
+ r#"
+ extern crate baz;
+ extern crate proc_macro;
+ use proc_macro::TokenStream;
+
+ #[proc_macro_derive(Noop)]
+ pub fn noop(_input: TokenStream) -> TokenStream {
+ "".parse().unwrap()
+ }
+ "#,
+ )
+ .build();
+ Package::new("bar", "0.1.0").publish();
+ Package::new("baz", "0.1.0")
+ .dep("bar", "0.1")
+ .file("src/lib.rs", "extern crate bar;")
+ .publish();
+ p.cargo("test --workspace --target").arg(rustc_host()).run();
+}
+
+#[cargo_test]
+fn test_hint_not_masked_by_doctest() {
+ let p = project()
+ .file(
+ "src/lib.rs",
+ r#"
+ /// ```
+ /// assert_eq!(1, 1);
+ /// ```
+ pub fn this_works() {}
+ "#,
+ )
+ .file(
+ "tests/integ.rs",
+ r#"
+ #[test]
+ fn this_fails() {
+ panic!();
+ }
+ "#,
+ )
+ .build();
+ p.cargo("test --no-fail-fast")
+ .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`")
+ .run();
+}
+
+#[cargo_test]
+fn test_hint_workspace_virtual() {
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [workspace]
+ members = ["a", "b", "c"]
+ "#,
+ )
+ .file("a/Cargo.toml", &basic_manifest("a", "0.1.0"))
+ .file("a/src/lib.rs", "#[test] fn t1() {}")
+ .file("b/Cargo.toml", &basic_manifest("b", "0.1.0"))
+ .file("b/src/lib.rs", "#[test] fn t1() {assert!(false)}")
+ .file("c/Cargo.toml", &basic_manifest("c", "0.1.0"))
+ .file(
+ "c/src/lib.rs",
+ r#"
+ /// ```rust
+ /// assert_eq!(1, 2);
+ /// ```
+ pub fn foo() {}
+ "#,
+ )
+ .file(
+ "c/src/main.rs",
+ r#"
+ fn main() {}
+
+ #[test]
+ fn from_main() { assert_eq!(1, 2); }
+ "#,
+ )
+ .file(
+ "c/tests/t1.rs",
+ r#"
+ #[test]
+ fn from_int_test() { assert_eq!(1, 2); }
+ "#,
+ )
+ .file(
+ "c/examples/ex1.rs",
+ r#"
+ fn main() {}
+
+ #[test]
+ fn from_example() { assert_eq!(1, 2); }
+ "#,
+ )
+ // This does not use #[bench] since it is unstable. #[test] works just
+ // the same for our purpose of checking the hint.
+ .file(
+ "c/benches/b1.rs",
+ r#"
+ #[test]
+ fn from_bench() { assert_eq!(1, 2); }
+ "#,
+ )
+ .build();
+
+ // This depends on Units being sorted so that `b` fails first.
+ p.cargo("test")
+ .with_stderr_unordered(
+ "\
+[COMPILING] c v0.1.0 [..]
+[COMPILING] a v0.1.0 [..]
+[COMPILING] b v0.1.0 [..]
+[FINISHED] test [..]
+[RUNNING] unittests src/lib.rs (target/debug/deps/a[..])
+[RUNNING] unittests src/lib.rs (target/debug/deps/b[..])
+[ERROR] test failed, to rerun pass `-p b --lib`
+",
+ )
+ .with_status(101)
+ .run();
+ p.cargo("test")
+ .cwd("b")
+ .with_stderr(
+ "\
+[FINISHED] test [..]
+[RUNNING] unittests src/lib.rs ([ROOT]/foo/target/debug/deps/b[..])
+[ERROR] test failed, to rerun pass `--lib`
+",
+ )
+ .with_status(101)
+ .run();
+ p.cargo("test --no-fail-fast")
+ .with_stderr(
+ "\
+[FINISHED] test [..]
+[RUNNING] unittests src/lib.rs (target/debug/deps/a[..])
+[RUNNING] unittests src/lib.rs (target/debug/deps/b[..])
+[ERROR] test failed, to rerun pass `-p b --lib`
+[RUNNING] unittests src/lib.rs (target/debug/deps/c[..])
+[RUNNING] unittests src/main.rs (target/debug/deps/c[..])
+[ERROR] test failed, to rerun pass `-p c --bin c`
+[RUNNING] tests/t1.rs (target/debug/deps/t1[..])
+[ERROR] test failed, to rerun pass `-p c --test t1`
+[DOCTEST] a
+[DOCTEST] b
+[DOCTEST] c
+[ERROR] doctest failed, to rerun pass `-p c --doc`
+[ERROR] 4 targets failed:
+ `-p b --lib`
+ `-p c --bin c`
+ `-p c --test t1`
+ `-p c --doc`
+",
+ )
+ .with_status(101)
+ .run();
+ // Check others that are not in the default set.
+ p.cargo("test -p c --examples --benches --no-fail-fast")
+ .with_stderr(
+ "\
+[COMPILING] c v0.1.0 [..]
+[FINISHED] test [..]
+[RUNNING] unittests src/lib.rs (target/debug/deps/c[..])
+[RUNNING] unittests src/main.rs (target/debug/deps/c[..])
+[ERROR] test failed, to rerun pass `-p c --bin c`
+[RUNNING] benches/b1.rs (target/debug/deps/b1[..])
+[ERROR] test failed, to rerun pass `-p c --bench b1`
+[RUNNING] unittests examples/ex1.rs (target/debug/examples/ex1[..])
+[ERROR] test failed, to rerun pass `-p c --example ex1`
+[ERROR] 3 targets failed:
+ `-p c --bin c`
+ `-p c --bench b1`
+ `-p c --example ex1`
+",
+ )
+ .with_status(101)
+ .run()
+}
+
+#[cargo_test]
+fn test_hint_workspace_nonvirtual() {
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+
+ [workspace]
+ members = ["a"]
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .file("a/Cargo.toml", &basic_manifest("a", "0.1.0"))
+ .file("a/src/lib.rs", "#[test] fn t1() {assert!(false)}")
+ .build();
+
+ p.cargo("test --workspace")
+ .with_stderr_contains("[ERROR] test failed, to rerun pass `-p a --lib`")
+ .with_status(101)
+ .run();
+ p.cargo("test -p a")
+ .with_stderr_contains("[ERROR] test failed, to rerun pass `-p a --lib`")
+ .with_status(101)
+ .run();
+}
+
+#[cargo_test]
+fn json_artifact_includes_test_flag() {
+ // Verify that the JSON artifact output includes `test` flag.
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [profile.test]
+ opt-level = 1
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .build();
+
+ p.cargo("test --lib -v --message-format=json")
+ .with_json(
+ r#"
+ {
+ "reason":"compiler-artifact",
+ "profile": {
+ "debug_assertions": true,
+ "debuginfo": 2,
+ "opt_level": "1",
+ "overflow_checks": true,
+ "test": true
+ },
+ "executable": "[..]/foo-[..]",
+ "features": [],
+ "package_id":"foo 0.0.1 ([..])",
+ "manifest_path": "[..]",
+ "target":{
+ "kind":["lib"],
+ "crate_types":["lib"],
+ "doc": true,
+ "doctest": true,
+ "edition": "2015",
+ "name":"foo",
+ "src_path":"[..]lib.rs",
+ "test": true
+ },
+ "filenames":"{...}",
+ "fresh": false
+ }
+
+ {"reason": "build-finished", "success": true}
+ "#,
+ )
+ .run();
+}
+
+#[cargo_test]
+fn json_artifact_includes_executable_for_library_tests() {
+ let p = project()
+ .file("src/main.rs", "fn main() { }")
+ .file("src/lib.rs", r#"#[test] fn lib_test() {}"#)
+ .build();
+
+ p.cargo("test --lib -v --no-run --message-format=json")
+ .with_json(
+ r#"
+ {
+ "executable": "[..]/foo/target/debug/deps/foo-[..][EXE]",
+ "features": [],
+ "filenames": "{...}",
+ "fresh": false,
+ "package_id": "foo 0.0.1 ([..])",
+ "manifest_path": "[..]",
+ "profile": "{...}",
+ "reason": "compiler-artifact",
+ "target": {
+ "crate_types": [ "lib" ],
+ "kind": [ "lib" ],
+ "doc": true,
+ "doctest": true,
+ "edition": "2015",
+ "name": "foo",
+ "src_path": "[..]/foo/src/lib.rs",
+ "test": true
+ }
+ }
+
+ {"reason": "build-finished", "success": true}
+ "#,
+ )
+ .run();
+}
+
+#[cargo_test]
+fn json_artifact_includes_executable_for_integration_tests() {
+ let p = project()
+ .file(
+ "tests/integration_test.rs",
+ r#"#[test] fn integration_test() {}"#,
+ )
+ .build();
+
+ p.cargo("test -v --no-run --message-format=json --test integration_test")
+ .with_json(
+ r#"
+ {
+ "executable": "[..]/foo/target/debug/deps/integration_test-[..][EXE]",
+ "features": [],
+ "filenames": "{...}",
+ "fresh": false,
+ "package_id": "foo 0.0.1 ([..])",
+ "manifest_path": "[..]",
+ "profile": "{...}",
+ "reason": "compiler-artifact",
+ "target": {
+ "crate_types": [ "bin" ],
+ "kind": [ "test" ],
+ "doc": false,
+ "doctest": false,
+ "edition": "2015",
+ "name": "integration_test",
+ "src_path": "[..]/foo/tests/integration_test.rs",
+ "test": true
+ }
+ }
+
+ {"reason": "build-finished", "success": true}
+ "#,
+ )
+ .run();
+}
+
+#[cargo_test]
+fn test_build_script_links() {
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ links = 'something'
+
+ [lib]
+ test = false
+ "#,
+ )
+ .file("build.rs", "fn main() {}")
+ .file("src/lib.rs", "")
+ .build();
+
+ p.cargo("test --no-run").run();
+}
+
+#[cargo_test]
+fn doctest_skip_staticlib() {
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+
+ [lib]
+ crate-type = ["staticlib"]
+ "#,
+ )
+ .file(
+ "src/lib.rs",
+ r#"
+ //! ```
+ //! assert_eq!(1,2);
+ //! ```
+ "#,
+ )
+ .build();
+
+ p.cargo("test --doc")
+ .with_status(101)
+ .with_stderr(
+ "\
+[WARNING] doc tests are not supported for crate type(s) `staticlib` in package `foo`
+[ERROR] no library targets found in package `foo`",
+ )
+ .run();
+
+ p.cargo("test")
+ .with_stderr(
+ "\
+[COMPILING] foo [..]
+[FINISHED] test [..]
+[RUNNING] [..] (target/debug/deps/foo-[..])",
+ )
+ .run();
+}
+
+#[cargo_test]
+fn can_not_mix_doc_tests_and_regular_tests() {
+ let p = project()
+ .file(
+ "src/lib.rs",
+ "\
+/// ```
+/// assert_eq!(1, 1)
+/// ```
+pub fn foo() -> u8 { 1 }
+
+#[cfg(test)] mod tests {
+ #[test] fn it_works() { assert_eq!(2 + 2, 4); }
+}
+",
+ )
+ .build();
+
+ p.cargo("test")
+ .with_stderr(
+ "\
+[COMPILING] foo v0.0.1 ([CWD])
+[FINISHED] test [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] [..] (target/debug/deps/foo-[..])
+[DOCTEST] foo
+",
+ )
+ .with_stdout(
+ "
+running 1 test
+test tests::it_works ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out[..]
+
+
+running 1 test
+test src/lib.rs - foo (line 1) ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out[..]
+\n",
+ )
+ .run();
+
+ p.cargo("test --lib")
+ .with_stderr(
+ "\
+[FINISHED] test [unoptimized + debuginfo] target(s) in [..]
+[RUNNING] [..] (target/debug/deps/foo-[..])\n",
+ )
+ .with_stdout(
+ "
+running 1 test
+test tests::it_works ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out[..]
+\n",
+ )
+ .run();
+
+ // This has been modified to attempt to diagnose spurious errors on CI.
+ // For some reason, this is recompiling the lib when it shouldn't. If the
+ // root cause is ever found, the changes here should be reverted.
+ // See https://github.com/rust-lang/cargo/issues/6887
+ p.cargo("test --doc -vv")
+ .with_stderr_does_not_contain("[COMPILING] foo [..]")
+ .with_stderr_contains("[DOCTEST] foo")
+ .with_stdout(
+ "
+running 1 test
+test src/lib.rs - foo (line 1) ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out[..]
+
+",
+ )
+ .env("CARGO_LOG", "cargo=trace")
+ .run();
+
+ p.cargo("test --lib --doc")
+ .with_status(101)
+ .with_stderr("[ERROR] Can't mix --doc with other target selecting options\n")
+ .run();
+}
+
+#[cargo_test]
+fn can_not_no_run_doc_tests() {
+ let p = project()
+ .file(
+ "src/lib.rs",
+ r#"
+ /// ```
+ /// let _x = 1 + "foo";
+ /// ```
+ pub fn foo() -> u8 { 1 }
+ "#,
+ )
+ .build();
+
+ p.cargo("test --doc --no-run")
+ .with_status(101)
+ .with_stderr("[ERROR] Can't skip running doc tests with --no-run")
+ .run();
+}
+
+#[cargo_test]
+fn test_all_targets_lib() {
+ let p = project().file("src/lib.rs", "").build();
+
+ p.cargo("test --all-targets")
+ .with_stderr(
+ "\
+[COMPILING] foo [..]
+[FINISHED] test [..]
+[RUNNING] [..]foo[..]
+",
+ )
+ .run();
+}
+
+#[cargo_test]
+fn test_dep_with_dev() {
+ Package::new("devdep", "0.1.0").publish();
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+
+ [dependencies]
+ bar = { path = "bar" }
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .file(
+ "bar/Cargo.toml",
+ r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+
+ [dev-dependencies]
+ devdep = "0.1"
+ "#,
+ )
+ .file("bar/src/lib.rs", "")
+ .build();
+
+ p.cargo("test -p bar")
+ .with_status(101)
+ .with_stderr(
+ "[ERROR] package `bar` cannot be tested because it requires dev-dependencies \
+ and is not a member of the workspace",
+ )
+ .run();
+}
+
+#[cargo_test(nightly, reason = "-Zdoctest-xcompile is unstable")]
+fn cargo_test_doctest_xcompile_ignores() {
+ // -Zdoctest-xcompile also enables --enable-per-target-ignores which
+ // allows the ignore-TARGET syntax.
+ let p = project()
+ .file("Cargo.toml", &basic_lib_manifest("foo"))
+ .file(
+ "src/lib.rs",
+ r#"
+ ///```ignore-x86_64
+ ///assert!(cfg!(not(target_arch = "x86_64")));
+ ///```
+ pub fn foo() -> u8 {
+ 4
+ }
+ "#,
+ )
+ .build();
+
+ p.cargo("build").run();
+ #[cfg(not(target_arch = "x86_64"))]
+ p.cargo("test")
+ .with_stdout_contains(
+ "test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out[..]",
+ )
+ .run();
+ #[cfg(target_arch = "x86_64")]
+ p.cargo("test")
+ .with_status(101)
+ .with_stdout_contains(
+ "test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out[..]",
+ )
+ .run();
+
+ #[cfg(not(target_arch = "x86_64"))]
+ p.cargo("test -Zdoctest-xcompile")
+ .masquerade_as_nightly_cargo(&["doctest-xcompile"])
+ .with_stdout_contains(
+ "test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out[..]",
+ )
+ .run();
+
+ #[cfg(target_arch = "x86_64")]
+ p.cargo("test -Zdoctest-xcompile")
+ .masquerade_as_nightly_cargo(&["doctest-xcompile"])
+ .with_stdout_contains(
+ "test result: ok. 0 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out[..]",
+ )
+ .run();
+}
+
+#[cargo_test(nightly, reason = "-Zdoctest-xcompile is unstable")]
+fn cargo_test_doctest_xcompile() {
+ if !cross_compile::can_run_on_host() {
+ return;
+ }
+ let p = project()
+ .file("Cargo.toml", &basic_lib_manifest("foo"))
+ .file(
+ "src/lib.rs",
+ r#"
+
+ ///```
+ ///assert!(1 == 1);
+ ///```
+ pub fn foo() -> u8 {
+ 4
+ }
+ "#,
+ )
+ .build();
+
+ p.cargo("build").run();
+ p.cargo(&format!("test --target {}", cross_compile::alternate()))
+ .with_stdout_contains("running 0 tests")
+ .run();
+ p.cargo(&format!(
+ "test --target {} -Zdoctest-xcompile",
+ cross_compile::alternate()
+ ))
+ .masquerade_as_nightly_cargo(&["doctest-xcompile"])
+ .with_stdout_contains(
+ "test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out[..]",
+ )
+ .run();
+}
+
+#[cargo_test(nightly, reason = "-Zdoctest-xcompile is unstable")]
+fn cargo_test_doctest_xcompile_runner() {
+ if !cross_compile::can_run_on_host() {
+ return;
+ }
+
+ let runner = project()
+ .file("Cargo.toml", &basic_bin_manifest("runner"))
+ .file(
+ "src/main.rs",
+ r#"
+ pub fn main() {
+ eprintln!("this is a runner");
+ let args: Vec<String> = std::env::args().collect();
+ std::process::Command::new(&args[1]).spawn();
+ }
+ "#,
+ )
+ .build();
+
+ runner.cargo("build").run();
+ assert!(runner.bin("runner").is_file());
+ let runner_path = paths::root().join("runner");
+ fs::copy(&runner.bin("runner"), &runner_path).unwrap();
+
+ let config = paths::root().join(".cargo/config");
+
+ fs::create_dir_all(config.parent().unwrap()).unwrap();
+ // Escape Windows backslashes for TOML config.
+ let runner_str = runner_path.to_str().unwrap().replace('\\', "\\\\");
+ fs::write(
+ config,
+ format!(
+ r#"
+ [target.'cfg(target_arch = "{}")']
+ runner = "{}"
+ "#,
+ cross_compile::alternate_arch(),
+ runner_str
+ ),
+ )
+ .unwrap();
+
+ let p = project()
+ .file("Cargo.toml", &basic_lib_manifest("foo"))
+ .file(
+ "src/lib.rs",
+ &format!(
+ r#"
+ ///```
+ ///assert!(cfg!(target_arch = "{}"));
+ ///```
+ pub fn foo() -> u8 {{
+ 4
+ }}
+ "#,
+ cross_compile::alternate_arch()
+ ),
+ )
+ .build();
+
+ p.cargo("build").run();
+ p.cargo(&format!("test --target {}", cross_compile::alternate()))
+ .with_stdout_contains("running 0 tests")
+ .run();
+ p.cargo(&format!(
+ "test --target {} -Zdoctest-xcompile",
+ cross_compile::alternate()
+ ))
+ .masquerade_as_nightly_cargo(&["doctest-xcompile"])
+ .with_stdout_contains(
+ "test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out[..]",
+ )
+ .with_stderr_contains("this is a runner")
+ .run();
+}
+
+#[cargo_test(nightly, reason = "-Zdoctest-xcompile is unstable")]
+fn cargo_test_doctest_xcompile_no_runner() {
+ if !cross_compile::can_run_on_host() {
+ return;
+ }
+
+ let p = project()
+ .file("Cargo.toml", &basic_lib_manifest("foo"))
+ .file(
+ "src/lib.rs",
+ &format!(
+ r#"
+ ///```
+ ///assert!(cfg!(target_arch = "{}"));
+ ///```
+ pub fn foo() -> u8 {{
+ 4
+ }}
+ "#,
+ cross_compile::alternate_arch()
+ ),
+ )
+ .build();
+
+ p.cargo("build").run();
+ p.cargo(&format!("test --target {}", cross_compile::alternate()))
+ .with_stdout_contains("running 0 tests")
+ .run();
+ p.cargo(&format!(
+ "test --target {} -Zdoctest-xcompile",
+ cross_compile::alternate()
+ ))
+ .masquerade_as_nightly_cargo(&["doctest-xcompile"])
+ .with_stdout_contains(
+ "test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out[..]",
+ )
+ .run();
+}
+
+#[cargo_test(nightly, reason = "-Zpanic-abort-tests in rustc is unstable")]
+fn panic_abort_tests() {
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = 'foo'
+ version = '0.1.0'
+
+ [dependencies]
+ a = { path = 'a' }
+
+ [profile.dev]
+ panic = 'abort'
+ [profile.test]
+ panic = 'abort'
+ "#,
+ )
+ .file(
+ "src/lib.rs",
+ r#"
+ #[test]
+ fn foo() {
+ a::foo();
+ }
+ "#,
+ )
+ .file("a/Cargo.toml", &basic_lib_manifest("a"))
+ .file("a/src/lib.rs", "pub fn foo() {}")
+ .build();
+
+ p.cargo("test -Z panic-abort-tests -v")
+ .with_stderr_contains("[..]--crate-name a [..]-C panic=abort[..]")
+ .with_stderr_contains("[..]--crate-name foo [..]-C panic=abort[..]")
+ .with_stderr_contains("[..]--crate-name foo [..]-C panic=abort[..]--test[..]")
+ .masquerade_as_nightly_cargo(&["panic-abort-tests"])
+ .run();
+}
+
+#[cargo_test(nightly, reason = "-Zpanic-abort-tests in rustc is unstable")]
+fn panic_abort_only_test() {
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = 'foo'
+ version = '0.1.0'
+
+ [dependencies]
+ a = { path = 'a' }
+
+ [profile.test]
+ panic = 'abort'
+ "#,
+ )
+ .file(
+ "src/lib.rs",
+ r#"
+ #[test]
+ fn foo() {
+ a::foo();
+ }
+ "#,
+ )
+ .file("a/Cargo.toml", &basic_lib_manifest("a"))
+ .file("a/src/lib.rs", "pub fn foo() {}")
+ .build();
+
+ p.cargo("test -Z panic-abort-tests -v")
+ .with_stderr_contains("warning: `panic` setting is ignored for `test` profile")
+ .masquerade_as_nightly_cargo(&["panic-abort-tests"])
+ .run();
+}
+
+#[cargo_test(nightly, reason = "-Zpanic-abort-tests in rustc is unstable")]
+fn panic_abort_test_profile_inherits() {
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = 'foo'
+ version = '0.1.0'
+
+ [dependencies]
+ a = { path = 'a' }
+
+ [profile.dev]
+ panic = 'abort'
+ "#,
+ )
+ .file(
+ "src/lib.rs",
+ r#"
+ #[test]
+ fn foo() {
+ a::foo();
+ }
+ "#,
+ )
+ .file("a/Cargo.toml", &basic_lib_manifest("a"))
+ .file("a/src/lib.rs", "pub fn foo() {}")
+ .build();
+
+ p.cargo("test -Z panic-abort-tests -v")
+ .masquerade_as_nightly_cargo(&["panic-abort-tests"])
+ .with_status(0)
+ .run();
+}
+
+#[cargo_test]
+fn bin_env_for_test() {
+ // Test for the `CARGO_BIN_EXE_` environment variables for tests.
+ //
+ // Note: The Unicode binary uses a `[[bin]]` definition because different
+ // filesystems normalize utf-8 in different ways. For example, HFS uses
+ // "gru\u{308}ßen" and APFS uses "gr\u{fc}ßen". Defining it in TOML forces
+ // one form to be used.
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ edition = "2018"
+
+ [[bin]]
+ name = 'grüßen'
+ path = 'src/bin/grussen.rs'
+ "#,
+ )
+ .file("src/bin/foo.rs", "fn main() {}")
+ .file("src/bin/with-dash.rs", "fn main() {}")
+ .file("src/bin/grussen.rs", "fn main() {}")
+ .build();
+
+ let bin_path = |name| p.bin(name).to_string_lossy().replace("\\", "\\\\");
+ p.change_file(
+ "tests/check_env.rs",
+ &r#"
+ #[test]
+ fn run_bins() {
+ assert_eq!(env!("CARGO_BIN_EXE_foo"), "<FOO_PATH>");
+ assert_eq!(env!("CARGO_BIN_EXE_with-dash"), "<WITH_DASH_PATH>");
+ assert_eq!(env!("CARGO_BIN_EXE_grüßen"), "<GRÜSSEN_PATH>");
+ }
+ "#
+ .replace("<FOO_PATH>", &bin_path("foo"))
+ .replace("<WITH_DASH_PATH>", &bin_path("with-dash"))
+ .replace("<GRÜSSEN_PATH>", &bin_path("grüßen")),
+ );
+
+ p.cargo("test --test check_env").run();
+ p.cargo("check --test check_env").run();
+}
+
+#[cargo_test]
+fn test_workspaces_cwd() {
+ // This tests that all the different test types are executed from the
+ // crate directory (manifest_dir), and not from the workspace root.
+
+ let make_lib_file = |expected| {
+ format!(
+ r#"
+ //! ```
+ //! assert_eq!("{expected}", std::fs::read_to_string("file.txt").unwrap());
+ //! assert_eq!("{expected}", include_str!("../file.txt"));
+ //! assert_eq!(
+ //! std::path::PathBuf::from(std::env!("CARGO_MANIFEST_DIR")),
+ //! std::env::current_dir().unwrap(),
+ //! );
+ //! ```
+
+ #[test]
+ fn test_unit_{expected}_cwd() {{
+ assert_eq!("{expected}", std::fs::read_to_string("file.txt").unwrap());
+ assert_eq!("{expected}", include_str!("../file.txt"));
+ assert_eq!(
+ std::path::PathBuf::from(std::env!("CARGO_MANIFEST_DIR")),
+ std::env::current_dir().unwrap(),
+ );
+ }}
+ "#,
+ expected = expected
+ )
+ };
+ let make_test_file = |expected| {
+ format!(
+ r#"
+ #[test]
+ fn test_integration_{expected}_cwd() {{
+ assert_eq!("{expected}", std::fs::read_to_string("file.txt").unwrap());
+ assert_eq!("{expected}", include_str!("../file.txt"));
+ assert_eq!(
+ std::path::PathBuf::from(std::env!("CARGO_MANIFEST_DIR")),
+ std::env::current_dir().unwrap(),
+ );
+ }}
+ "#,
+ expected = expected
+ )
+ };
+
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "root-crate"
+ version = "0.0.0"
+
+ [workspace]
+ members = [".", "nested-crate", "very/deeply/nested/deep-crate"]
+ "#,
+ )
+ .file("file.txt", "root")
+ .file("src/lib.rs", &make_lib_file("root"))
+ .file("tests/integration.rs", &make_test_file("root"))
+ .file(
+ "nested-crate/Cargo.toml",
+ r#"
+ [package]
+ name = "nested-crate"
+ version = "0.0.0"
+ "#,
+ )
+ .file("nested-crate/file.txt", "nested")
+ .file("nested-crate/src/lib.rs", &make_lib_file("nested"))
+ .file(
+ "nested-crate/tests/integration.rs",
+ &make_test_file("nested"),
+ )
+ .file(
+ "very/deeply/nested/deep-crate/Cargo.toml",
+ r#"
+ [package]
+ name = "deep-crate"
+ version = "0.0.0"
+ "#,
+ )
+ .file("very/deeply/nested/deep-crate/file.txt", "deep")
+ .file(
+ "very/deeply/nested/deep-crate/src/lib.rs",
+ &make_lib_file("deep"),
+ )
+ .file(
+ "very/deeply/nested/deep-crate/tests/integration.rs",
+ &make_test_file("deep"),
+ )
+ .build();
+
+ p.cargo("test --workspace --all")
+ .with_stderr_contains("[DOCTEST] root-crate")
+ .with_stderr_contains("[DOCTEST] nested-crate")
+ .with_stderr_contains("[DOCTEST] deep-crate")
+ .with_stdout_contains("test test_unit_root_cwd ... ok")
+ .with_stdout_contains("test test_unit_nested_cwd ... ok")
+ .with_stdout_contains("test test_unit_deep_cwd ... ok")
+ .with_stdout_contains("test test_integration_root_cwd ... ok")
+ .with_stdout_contains("test test_integration_nested_cwd ... ok")
+ .with_stdout_contains("test test_integration_deep_cwd ... ok")
+ .run();
+
+ p.cargo("test -p root-crate --all")
+ .with_stderr_contains("[DOCTEST] root-crate")
+ .with_stdout_contains("test test_unit_root_cwd ... ok")
+ .with_stdout_contains("test test_integration_root_cwd ... ok")
+ .run();
+
+ p.cargo("test -p nested-crate --all")
+ .with_stderr_contains("[DOCTEST] nested-crate")
+ .with_stdout_contains("test test_unit_nested_cwd ... ok")
+ .with_stdout_contains("test test_integration_nested_cwd ... ok")
+ .run();
+
+ p.cargo("test -p deep-crate --all")
+ .with_stderr_contains("[DOCTEST] deep-crate")
+ .with_stdout_contains("test test_unit_deep_cwd ... ok")
+ .with_stdout_contains("test test_integration_deep_cwd ... ok")
+ .run();
+
+ p.cargo("test --all")
+ .cwd("nested-crate")
+ .with_stderr_contains("[DOCTEST] nested-crate")
+ .with_stdout_contains("test test_unit_nested_cwd ... ok")
+ .with_stdout_contains("test test_integration_nested_cwd ... ok")
+ .run();
+
+ p.cargo("test --all")
+ .cwd("very/deeply/nested/deep-crate")
+ .with_stderr_contains("[DOCTEST] deep-crate")
+ .with_stdout_contains("test test_unit_deep_cwd ... ok")
+ .with_stdout_contains("test test_integration_deep_cwd ... ok")
+ .run();
+}
+
+#[cargo_test]
+fn execution_error() {
+ // Checks the behavior when a test fails to launch.
+ let p = project()
+ .file(
+ "tests/t1.rs",
+ r#"
+ #[test]
+ fn foo() {}
+ "#,
+ )
+ .build();
+ let key = format!("CARGO_TARGET_{}_RUNNER", rustc_host_env());
+ p.cargo("test")
+ .env(&key, "does_not_exist")
+ // The actual error is usually "no such file", but on Windows it has a
+ // custom message. Since matching against the error string produced by
+ // Rust is not very reliable, this just uses `[..]`.
+ .with_stderr(
+ "\
+[COMPILING] foo v0.0.1 [..]
+[FINISHED] test [..]
+[RUNNING] tests/t1.rs (target/debug/deps/t1[..])
+error: test failed, to rerun pass `--test t1`
+
+Caused by:
+ could not execute process `does_not_exist [ROOT]/foo/target/debug/deps/t1[..]` (never executed)
+
+Caused by:
+ [..]
+",
+ )
+ .with_status(101)
+ .run();
+}
+
+#[cargo_test]
+fn nonzero_exit_status() {
+ // Tests for nonzero exit codes from tests.
+ let p = project()
+ .file(
+ "tests/t1.rs",
+ r#"
+ #[test]
+ fn t() { panic!("this is a normal error") }
+ "#,
+ )
+ .file(
+ "tests/t2.rs",
+ r#"
+ #[test]
+ fn t() { std::process::exit(4) }
+ "#,
+ )
+ .build();
+
+ p.cargo("test --test t1")
+ .with_stderr(
+ "\
+[COMPILING] foo [..]
+[FINISHED] test [..]
+[RUNNING] tests/t1.rs (target/debug/deps/t1[..])
+error: test failed, to rerun pass `--test t1`
+",
+ )
+ .with_stdout_contains("[..]this is a normal error[..]")
+ .with_status(101)
+ .run();
+
+ p.cargo("test --test t2")
+ .with_stderr(
+ "\
+[COMPILING] foo v0.0.1 [..]
+[FINISHED] test [..]
+[RUNNING] tests/t2.rs (target/debug/deps/t2[..])
+error: test failed, to rerun pass `--test t2`
+
+Caused by:
+ process didn't exit successfully: `[ROOT]/foo/target/debug/deps/t2[..]` (exit [..]: 4)
+",
+ )
+ .with_status(4)
+ .run();
+
+ // no-fail-fast always uses 101
+ p.cargo("test --no-fail-fast")
+ .with_stderr(
+ "\
+[FINISHED] test [..]
+[RUNNING] tests/t1.rs (target/debug/deps/t1[..])
+error: test failed, to rerun pass `--test t1`
+[RUNNING] tests/t2.rs (target/debug/deps/t2[..])
+error: test failed, to rerun pass `--test t2`
+
+Caused by:
+ process didn't exit successfully: `[ROOT]/foo/target/debug/deps/t2[..]` (exit [..]: 4)
+error: 2 targets failed:
+ `--test t1`
+ `--test t2`
+",
+ )
+ .with_status(101)
+ .run();
+}