From 10ee2acdd26a7f1298c6f6d6b7af9b469fe29b87 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 4 May 2024 14:41:41 +0200 Subject: Merging upstream version 1.70.0+dfsg2. Signed-off-by: Daniel Baumann --- src/tools/cargo/tests/testsuite/test.rs | 4820 +++++++++++++++++++++++++++++++ 1 file changed, 4820 insertions(+) create mode 100644 src/tools/cargo/tests/testsuite/test.rs (limited to 'src/tools/cargo/tests/testsuite/test.rs') 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::(); + }); + 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 = 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"), ""); + assert_eq!(env!("CARGO_BIN_EXE_with-dash"), ""); + assert_eq!(env!("CARGO_BIN_EXE_grüßen"), ""); + } + "# + .replace("", &bin_path("foo")) + .replace("", &bin_path("with-dash")) + .replace("", &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(); +} -- cgit v1.2.3