Add thorough tests for target/profile selection.
authorEric Huss <eric@huss.org>
Sat, 21 Apr 2018 20:57:54 +0000 (13:57 -0700)
committerEric Huss <eric@huss.org>
Fri, 27 Apr 2018 20:42:30 +0000 (13:42 -0700)
tests/testsuite/cargotest/support/mod.rs
tests/testsuite/main.rs
tests/testsuite/profile_targets.rs [new file with mode: 0644]

index 115f5be47b6577bf36cac6e165f74fbc19f28e02..f51ea4384aa9556adec7939712e1b2115c7c3e8c 100644 (file)
@@ -380,6 +380,7 @@ pub struct Execs {
     expect_stdout_contains_n: Vec<(String, usize)>,
     expect_stdout_not_contains: Vec<String>,
     expect_stderr_not_contains: Vec<String>,
+    expect_stderr_unordered: Vec<String>,
     expect_neither_contains: Vec<String>,
     expect_json: Option<Vec<Value>>,
     stream_output: bool,
@@ -436,6 +437,11 @@ impl Execs {
         self
     }
 
+    pub fn with_stderr_unordered<S: ToString>(mut self, expected: S) -> Execs {
+        self.expect_stderr_unordered.push(expected.to_string());
+        self
+    }
+
     pub fn with_json(mut self, expected: &str) -> Execs {
         self.expect_json = Some(
             expected
@@ -526,6 +532,15 @@ impl Execs {
                 MatchKind::NotPresent,
             )?;
         }
+        for expect in self.expect_stderr_unordered.iter() {
+            self.match_std(
+                Some(expect),
+                &actual.stderr,
+                "stderr",
+                &actual.stdout,
+                MatchKind::Unordered,
+            )?;
+        }
         for expect in self.expect_neither_contains.iter() {
             self.match_std(
                 Some(expect),
@@ -709,6 +724,32 @@ impl Execs {
                     Ok(())
                 }
             }
+            MatchKind::Unordered => {
+                let mut a = actual.lines().collect::<Vec<_>>();
+                let e = out.lines();
+
+                for e_line in e {
+                    match a.iter().position(|a_line| lines_match(e_line, a_line)) {
+                        Some(index) => a.remove(index),
+                        None => {
+                            return Err(format!(
+                                "Did not find expected line:\n\
+                                 {}\n\
+                                 Remaining available output:\n\
+                                 {}\n",
+                                e_line,
+                                a.join("\n")
+                            ))
+                        }
+                    };
+                }
+                if a.len() > 0 {
+                    Err(format!("Output included extra lines:\n\
+                        {}\n", a.join("\n")))
+                } else {
+                    Ok(())
+                }
+            }
         }
     }
 
@@ -765,6 +806,7 @@ enum MatchKind {
     Partial,
     PartialN(usize),
     NotPresent,
+    Unordered,
 }
 
 pub fn lines_match(expected: &str, mut actual: &str) -> bool {
@@ -943,6 +985,7 @@ pub fn execs() -> Execs {
         expect_stdout_contains_n: Vec::new(),
         expect_stdout_not_contains: Vec::new(),
         expect_stderr_not_contains: Vec::new(),
+        expect_stderr_unordered: Vec::new(),
         expect_neither_contains: Vec::new(),
         expect_json: None,
         stream_output: false,
index 51b8ae584689becf7257e3f6c4ff8e741b3270cb..413f0463d3f63556e9ec14489356269b9f891ad0 100644 (file)
@@ -71,6 +71,7 @@ mod plugins;
 mod proc_macro;
 mod profiles;
 mod profile_overrides;
+mod profile_targets;
 mod publish;
 mod read_manifest;
 mod registry;
diff --git a/tests/testsuite/profile_targets.rs b/tests/testsuite/profile_targets.rs
new file mode 100644 (file)
index 0000000..0340e35
--- /dev/null
@@ -0,0 +1,710 @@
+use cargotest::support::{execs, project, Project};
+use hamcrest::assert_that;
+
+// These tests try to exercise exactly which profiles are selected for every
+// target.
+
+fn all_target_project() -> Project {
+    // This abuses the `codegen-units` setting so that we can verify exactly
+    // which profile is used for each compiler invocation.
+    project("foo")
+        .file(
+            "Cargo.toml",
+            r#"
+            [package]
+            name = "foo"
+            version = "0.0.1"
+
+            [dependencies]
+            bar = { path = "bar" }
+
+            [build-dependencies]
+            bdep = { path = "bdep" }
+
+            [profile.dev]
+            codegen-units = 1
+            panic = "abort"
+            [profile.release]
+            codegen-units = 2
+            panic = "abort"
+            [profile.test]
+            codegen-units = 3
+            [profile.bench]
+            codegen-units = 4
+            [profile.doc]
+            codegen-units = 5
+        "#,
+        )
+        .file("src/lib.rs", "extern crate bar;")
+        .file("src/main.rs", r#"
+            extern crate foo;
+            fn main() {}
+        "#)
+        .file("examples/ex1.rs", r#"
+            extern crate foo;
+            fn main() {}
+        "#)
+        .file("tests/test1.rs", "extern crate foo;")
+        .file("benches/bench1.rs", "extern crate foo;")
+        .file("build.rs", r#"
+            extern crate bdep;
+            fn main() {
+                eprintln!("foo custom build PROFILE={} DEBUG={} OPT_LEVEL={}",
+                    std::env::var("PROFILE").unwrap(),
+                    std::env::var("DEBUG").unwrap(),
+                    std::env::var("OPT_LEVEL").unwrap(),
+                );
+            }
+        "#)
+
+        // bar package
+        .file("bar/Cargo.toml", r#"
+            [package]
+            name = "bar"
+            version = "0.0.1"
+        "#)
+        .file("bar/src/lib.rs", "")
+
+        // bdep package
+        .file("bdep/Cargo.toml", r#"
+            [package]
+            name = "bdep"
+            version = "0.0.1"
+
+            [dependencies]
+            bar = { path = "../bar" }
+        "#)
+        .file("bdep/src/lib.rs", "extern crate bar;")
+        .build()
+}
+
+#[test]
+fn profile_selection_build() {
+    let p = all_target_project();
+
+    // Build default targets.
+    // NOTES:
+    // - bdep `panic` is not set because it thinks `build.rs` is a plugin.
+    // - bar `panic` is not set because it is shared with `bdep`.
+    // - build_script_build is built without panic because it thinks `build.rs` is a plugin.
+    assert_that(p.cargo("build -vv"), execs().with_status(0).with_stderr_unordered("\
+[COMPILING] bar [..]
+[RUNNING] `rustc --crate-name bar bar[/]src[/]lib.rs --crate-type lib --emit=dep-info,link -C codegen-units=1 -C debuginfo=2 [..]
+[COMPILING] bdep [..]
+[RUNNING] `rustc --crate-name bdep bdep[/]src[/]lib.rs --crate-type lib --emit=dep-info,link -C codegen-units=1 -C debuginfo=2 [..]
+[COMPILING] foo [..]
+[RUNNING] `rustc --crate-name build_script_build build.rs --crate-type bin --emit=dep-info,link -C codegen-units=1 -C debuginfo=2 [..]
+[RUNNING] `[..][/]target[/]debug[/]build[/]foo-[..][/]build-script-build`
+foo custom build PROFILE=debug DEBUG=true OPT_LEVEL=0
+[RUNNING] `rustc --crate-name foo src[/]lib.rs --crate-type lib --emit=dep-info,link -C panic=abort -C codegen-units=1 -C debuginfo=2 [..]
+[RUNNING] `rustc --crate-name foo src[/]main.rs --crate-type bin --emit=dep-info,link -C panic=abort -C codegen-units=1 -C debuginfo=2 [..]
+[FINISHED] dev [unoptimized + debuginfo] [..]
+"));
+    assert_that(
+        p.cargo("build -vv"),
+        execs().with_status(0).with_stderr_unordered(
+            "\
+[FRESH] bar [..]
+[FRESH] bdep [..]
+[FRESH] foo [..]
+[FINISHED] dev [unoptimized + debuginfo] [..]
+",
+        ),
+    );
+}
+
+#[test]
+fn profile_selection_build_release() {
+    let p = all_target_project();
+
+    // Build default targets, release.
+    assert_that(p.cargo("build --release -vv"),
+        execs().with_status(0).with_stderr_unordered("\
+[COMPILING] bar [..]
+[RUNNING] `rustc --crate-name bar bar[/]src[/]lib.rs --crate-type lib --emit=dep-info,link -C opt-level=3 -C codegen-units=2 [..]
+[COMPILING] bdep [..]
+[RUNNING] `rustc --crate-name bdep bdep[/]src[/]lib.rs --crate-type lib --emit=dep-info,link -C opt-level=3 -C codegen-units=2 [..]
+[COMPILING] foo [..]
+[RUNNING] `rustc --crate-name build_script_build build.rs --crate-type bin --emit=dep-info,link -C opt-level=3 -C codegen-units=2 [..]
+[RUNNING] `[..][/]target[/]release[/]build[/]foo-[..][/]build-script-build`
+foo custom build PROFILE=release DEBUG=false OPT_LEVEL=3
+[RUNNING] `rustc --crate-name foo src[/]lib.rs --crate-type lib --emit=dep-info,link -C opt-level=3 -C panic=abort -C codegen-units=2 [..]
+[RUNNING] `rustc --crate-name foo src[/]main.rs --crate-type bin --emit=dep-info,link -C opt-level=3 -C panic=abort -C codegen-units=2 [..]
+[FINISHED] release [optimized] [..]
+"));
+    assert_that(
+        p.cargo("build --release -vv"),
+        execs().with_status(0).with_stderr_unordered(
+            "\
+[FRESH] bar [..]
+[FRESH] bdep [..]
+[FRESH] foo [..]
+[FINISHED] release [optimized] [..]
+",
+        ),
+    );
+}
+
+#[test]
+fn profile_selection_build_all_targets() {
+    let p = all_target_project();
+    // Build all explicit targets.
+    // NOTES
+    // - bdep `panic` is not set because it thinks `build.rs` is a plugin.
+    // - bar compiled twice.  It tries with and without panic, but the "is a
+    //   plugin" logic is forcing it to be cleared.
+    // - build_script_build is built without panic because it thinks
+    //   `build.rs` is a plugin.
+    // - build_script_build is being run two times.  Once for the `dev` and
+    //   `test` targets, once for the `bench` targets.
+    //   TODO: "PROFILE" says debug both times, though!
+    // - Benchmark dependencies are compiled in `dev` mode, which may be
+    //   surprising.  See https://github.com/rust-lang/cargo/issues/4929.
+    //
+    // - Dependency profiles:
+    //   Pkg  Target  Profile     Reason
+    //   ---  ------  -------     ------
+    //   bar  lib     dev*        For bdep and foo
+    //   bar  lib     dev-panic   For tests/benches
+    //   bdep lib     dev*        For foo build.rs
+    //   foo  custom  dev*
+    //
+    //   `*` = wants panic, but it is cleared when args are built.
+    //
+    // - foo target list is:
+    //   Target   Profile    Mode
+    //   ------   -------    ----
+    //   lib      dev+panic  build  (a normal lib target)
+    //   lib      dev-panic  build  (used by tests/benches)
+    //   lib      test       test
+    //   lib      bench      bench
+    //   test     test       test
+    //   bench    bench      bench
+    //   bin      test       test
+    //   bin      bench      bench
+    //   bin      dev        build
+    //   example  dev        build
+    assert_that(p.cargo("build --all-targets -vv"),
+        execs().with_status(0).with_stderr_unordered("\
+[COMPILING] bar [..]
+[RUNNING] `rustc --crate-name bar bar[/]src[/]lib.rs --crate-type lib --emit=dep-info,link -C codegen-units=1 -C debuginfo=2 [..]
+[RUNNING] `rustc --crate-name bar bar[/]src[/]lib.rs --crate-type lib --emit=dep-info,link -C codegen-units=1 -C debuginfo=2 [..]
+[COMPILING] bdep [..]
+[RUNNING] `rustc --crate-name bdep bdep[/]src[/]lib.rs --crate-type lib --emit=dep-info,link -C codegen-units=1 -C debuginfo=2 [..]
+[COMPILING] foo [..]
+[RUNNING] `rustc --crate-name build_script_build build.rs --crate-type bin --emit=dep-info,link -C codegen-units=1 -C debuginfo=2 [..]
+[RUNNING] `[..][/]target[/]debug[/]build[/]foo-[..][/]build-script-build`
+[RUNNING] `[..][/]target[/]debug[/]build[/]foo-[..][/]build-script-build`
+foo custom build PROFILE=debug DEBUG=false OPT_LEVEL=3
+foo custom build PROFILE=debug DEBUG=true OPT_LEVEL=0
+[RUNNING] `rustc --crate-name foo src[/]lib.rs --crate-type lib --emit=dep-info,link -C panic=abort -C codegen-units=1 -C debuginfo=2 [..]`
+[RUNNING] `rustc --crate-name foo src[/]lib.rs --emit=dep-info,link -C codegen-units=3 -C debuginfo=2 --test [..]`
+[RUNNING] `rustc --crate-name foo src[/]lib.rs --crate-type lib --emit=dep-info,link -C codegen-units=1 -C debuginfo=2 [..]`
+[RUNNING] `rustc --crate-name foo src[/]lib.rs --emit=dep-info,link -C opt-level=3 -C codegen-units=4 --test [..]`
+[RUNNING] `rustc --crate-name foo src[/]main.rs --emit=dep-info,link -C codegen-units=3 -C debuginfo=2 --test [..]`
+[RUNNING] `rustc --crate-name test1 tests[/]test1.rs --emit=dep-info,link -C codegen-units=3 -C debuginfo=2 --test [..]`
+[RUNNING] `rustc --crate-name bench1 benches[/]bench1.rs --emit=dep-info,link -C opt-level=3 -C codegen-units=4 --test [..]`
+[RUNNING] `rustc --crate-name foo src[/]main.rs --emit=dep-info,link -C opt-level=3 -C codegen-units=4 --test [..]`
+[RUNNING] `rustc --crate-name foo src[/]main.rs --crate-type bin --emit=dep-info,link -C panic=abort -C codegen-units=1 -C debuginfo=2 [..]`
+[RUNNING] `rustc --crate-name ex1 examples[/]ex1.rs --crate-type bin --emit=dep-info,link -C panic=abort -C codegen-units=1 -C debuginfo=2 [..]`
+[FINISHED] dev [unoptimized + debuginfo] [..]
+"));
+    assert_that(
+        p.cargo("build -vv"),
+        execs().with_status(0).with_stderr_unordered(
+            "\
+[FRESH] bar [..]
+[FRESH] bdep [..]
+[FRESH] foo [..]
+[FINISHED] dev [unoptimized + debuginfo] [..]
+",
+        ),
+    );
+}
+
+#[test]
+fn profile_selection_build_all_targets_release() {
+    let p = all_target_project();
+    // Build all explicit targets, release.
+    // NOTES
+    // - bdep `panic` is not set because it thinks `build.rs` is a plugin.
+    // - bar compiled twice.  It tries with and without panic, but the "is a
+    //   plugin" logic is forcing it to be cleared.
+    // - build_script_build is built without panic because it thinks
+    //   `build.rs` is a plugin.
+    // - build_script_build is being run two times.  Once for the `dev` and
+    //   `test` targets, once for the `bench` targets.
+    //   TODO: "PROFILE" says debug both times, though!
+    //
+    // - Dependency profiles:
+    //   Pkg  Target  Profile        Reason
+    //   ---  ------  -------        ------
+    //   bar  lib     release*       For bdep and foo
+    //   bar  lib     release-panic  For tests/benches
+    //   bdep lib     release*       For foo build.rs
+    //   foo  custom  release*
+    //
+    //   `*` = wants panic, but it is cleared when args are built.
+    //
+    //
+    // - foo target list is:
+    //   Target   Profile        Mode
+    //   ------   -------        ----
+    //   lib      release+panic  build  (a normal lib target)
+    //   lib      release-panic  build  (used by tests/benches)
+    //   lib      bench          test
+    //   lib      bench          bench
+    //   test     bench          test
+    //   bench    bench          bench
+    //   bin      bench          test
+    //   bin      bench          bench
+    //   bin      release        build
+    //   example  release        build
+    assert_that(p.cargo("build --all-targets --release -vv"),
+        execs().with_status(0).with_stderr_unordered("\
+[COMPILING] bar [..]
+[RUNNING] `rustc --crate-name bar bar[/]src[/]lib.rs --crate-type lib --emit=dep-info,link -C opt-level=3 -C codegen-units=2 [..]
+[RUNNING] `rustc --crate-name bar bar[/]src[/]lib.rs --crate-type lib --emit=dep-info,link -C opt-level=3 -C codegen-units=2 [..]
+[COMPILING] bdep [..]
+[RUNNING] `rustc --crate-name bdep bdep[/]src[/]lib.rs --crate-type lib --emit=dep-info,link -C opt-level=3 -C codegen-units=2 [..]
+[COMPILING] foo [..]
+[RUNNING] `rustc --crate-name build_script_build build.rs --crate-type bin --emit=dep-info,link -C opt-level=3 -C codegen-units=2 [..]
+[RUNNING] `[..][/]target[/]release[/]build[/]foo-[..][/]build-script-build`
+foo custom build PROFILE=release DEBUG=false OPT_LEVEL=3
+[RUNNING] `rustc --crate-name foo src[/]lib.rs --crate-type lib --emit=dep-info,link -C opt-level=3 -C panic=abort -C codegen-units=2 [..]`
+[RUNNING] `rustc --crate-name foo src[/]lib.rs --emit=dep-info,link -C opt-level=3 -C codegen-units=4 --test [..]`
+[RUNNING] `rustc --crate-name foo src[/]lib.rs --crate-type lib --emit=dep-info,link -C opt-level=3 -C codegen-units=2 [..]`
+[RUNNING] `rustc --crate-name foo src[/]lib.rs --emit=dep-info,link -C opt-level=3 -C codegen-units=4 --test [..]`
+[RUNNING] `rustc --crate-name foo src[/]main.rs --emit=dep-info,link -C opt-level=3 -C codegen-units=4 --test [..]`
+[RUNNING] `rustc --crate-name test1 tests[/]test1.rs --emit=dep-info,link -C opt-level=3 -C codegen-units=4 --test [..]`
+[RUNNING] `rustc --crate-name bench1 benches[/]bench1.rs --emit=dep-info,link -C opt-level=3 -C codegen-units=4 --test [..]`
+[RUNNING] `rustc --crate-name foo src[/]main.rs --emit=dep-info,link -C opt-level=3 -C codegen-units=4 --test [..]`
+[RUNNING] `rustc --crate-name foo src[/]main.rs --crate-type bin --emit=dep-info,link -C opt-level=3 -C panic=abort -C codegen-units=2 [..]`
+[RUNNING] `rustc --crate-name ex1 examples[/]ex1.rs --crate-type bin --emit=dep-info,link -C opt-level=3 -C panic=abort -C codegen-units=2 [..]`
+[FINISHED] release [optimized] [..]
+"));
+    assert_that(
+        p.cargo("build --all-targets --release -vv"),
+        execs().with_status(0).with_stderr_unordered(
+            "\
+[FRESH] bar [..]
+[FRESH] bdep [..]
+[FRESH] foo [..]
+[FINISHED] release [optimized] [..]
+",
+        ),
+    );
+}
+
+#[test]
+fn profile_selection_test() {
+    let p = all_target_project();
+    // Test default.
+    // NOTES:
+    // - Dependency profiles:
+    //   Pkg  Target  Profile    Reason
+    //   ---  ------  -------    ------
+    //   bar  lib     dev*       For bdep and foo
+    //   bar  lib     dev-panic  For tests/benches
+    //   bdep lib     dev*       For foo build.rs
+    //   foo  custom  dev*
+    //
+    //   `*` = wants panic, but it is cleared when args are built.
+    //
+    // - foo target list is:
+    //   Target   Profile        Mode
+    //   ------   -------        ----
+    //   lib      dev-panic      build
+    //   lib      test           test
+    //   test     test           test
+    //   example  dev-panic      build
+    //   bin      test           test
+    //   bin      dev-panic      build
+    //
+    assert_that(p.cargo("test -vv"), execs().with_status(0).with_stderr_unordered("\
+[COMPILING] bar [..]
+[RUNNING] `rustc --crate-name bar bar[/]src[/]lib.rs --crate-type lib --emit=dep-info,link -C codegen-units=1 -C debuginfo=2 [..]
+[RUNNING] `rustc --crate-name bar bar[/]src[/]lib.rs --crate-type lib --emit=dep-info,link -C codegen-units=1 -C debuginfo=2 [..]
+[COMPILING] bdep [..]
+[RUNNING] `rustc --crate-name bdep bdep[/]src[/]lib.rs --crate-type lib --emit=dep-info,link -C codegen-units=1 -C debuginfo=2 [..]
+[COMPILING] foo [..]
+[RUNNING] `rustc --crate-name build_script_build build.rs --crate-type bin --emit=dep-info,link -C codegen-units=1 -C debuginfo=2 [..]
+[RUNNING] `[..][/]target[/]debug[/]build[/]foo-[..][/]build-script-build`
+foo custom build PROFILE=debug DEBUG=true OPT_LEVEL=0
+[RUNNING] `rustc --crate-name foo src[/]lib.rs --crate-type lib --emit=dep-info,link -C codegen-units=1 -C debuginfo=2 [..]
+[RUNNING] `rustc --crate-name foo src[/]lib.rs --emit=dep-info,link -C codegen-units=3 -C debuginfo=2 --test [..]
+[RUNNING] `rustc --crate-name test1 tests[/]test1.rs --emit=dep-info,link -C codegen-units=3 -C debuginfo=2 --test [..]
+[RUNNING] `rustc --crate-name ex1 examples[/]ex1.rs --crate-type bin --emit=dep-info,link -C codegen-units=1 -C debuginfo=2 [..]
+[RUNNING] `rustc --crate-name foo src[/]main.rs --emit=dep-info,link -C codegen-units=3 -C debuginfo=2 --test [..]
+[RUNNING] `rustc --crate-name foo src[/]main.rs --crate-type bin --emit=dep-info,link -C codegen-units=1 -C debuginfo=2 [..]
+[FINISHED] dev [unoptimized + debuginfo] [..]
+[RUNNING] `[..]foo[..]`
+[RUNNING] `[..]foo[..]`
+[RUNNING] `[..]test1[..]`
+[DOCTEST] foo
+[RUNNING] `rustdoc --test [..]
+"));
+    assert_that(
+        p.cargo("test -vv"),
+        execs().with_status(0).with_stderr_unordered(
+            "\
+[FRESH] bar [..]
+[FRESH] bdep [..]
+[FRESH] foo [..]
+[FINISHED] dev [unoptimized + debuginfo] [..]
+[RUNNING] `[..]foo[..]`
+[RUNNING] `[..]foo[..]`
+[RUNNING] `[..]test1[..]`
+[DOCTEST] foo
+[RUNNING] `rustdoc --test [..]
+",
+        ),
+    );
+}
+
+#[test]
+fn profile_selection_test_release() {
+    let p = all_target_project();
+    // Test default release.
+    // NOTES:
+    // - Dependency profiles:
+    //   Pkg  Target  Profile        Reason
+    //   ---  ------  -------        ------
+    //   bar  lib     release*       For bdep and foo
+    //   bar  lib     release-panic  For tests/benches
+    //   bdep lib     release*       For foo build.rs
+    //   foo  custom  release*
+    //
+    //   `*` = wants panic, but it is cleared when args are built.
+    //
+    // - foo target list is:
+    //   Target   Profile        Mode
+    //   ------   -------        ----
+    //   lib      release-panic  build
+    //   lib      bench          test
+    //   test     bench          test
+    //   example  release-panic  build
+    //   bin      bench          test
+    //   bin      release-panic  build
+    //
+    assert_that(p.cargo("test --release -vv"), execs().with_status(0).with_stderr_unordered("\
+[COMPILING] bar [..]
+[RUNNING] `rustc --crate-name bar bar[/]src[/]lib.rs --crate-type lib --emit=dep-info,link -C opt-level=3 -C codegen-units=2 [..]
+[RUNNING] `rustc --crate-name bar bar[/]src[/]lib.rs --crate-type lib --emit=dep-info,link -C opt-level=3 -C codegen-units=2 [..]
+[COMPILING] bdep [..]
+[RUNNING] `rustc --crate-name bdep bdep[/]src[/]lib.rs --crate-type lib --emit=dep-info,link -C opt-level=3 -C codegen-units=2 [..]
+[COMPILING] foo [..]
+[RUNNING] `rustc --crate-name build_script_build build.rs --crate-type bin --emit=dep-info,link -C opt-level=3 -C codegen-units=2 [..]
+[RUNNING] `[..][/]target[/]release[/]build[/]foo-[..][/]build-script-build`
+foo custom build PROFILE=release DEBUG=false OPT_LEVEL=3
+[RUNNING] `rustc --crate-name foo src[/]lib.rs --crate-type lib --emit=dep-info,link -C opt-level=3 -C codegen-units=2 [..]
+[RUNNING] `rustc --crate-name foo src[/]lib.rs --emit=dep-info,link -C opt-level=3 -C codegen-units=4 --test [..]
+[RUNNING] `rustc --crate-name test1 tests[/]test1.rs --emit=dep-info,link -C opt-level=3 -C codegen-units=4 --test [..]
+[RUNNING] `rustc --crate-name foo src[/]main.rs --emit=dep-info,link -C opt-level=3 -C codegen-units=4 --test [..]
+[RUNNING] `rustc --crate-name ex1 examples[/]ex1.rs --crate-type bin --emit=dep-info,link -C opt-level=3 -C codegen-units=2 [..]
+[RUNNING] `rustc --crate-name foo src[/]main.rs --crate-type bin --emit=dep-info,link -C opt-level=3 -C codegen-units=2 [..]
+[FINISHED] release [optimized] [..]
+[RUNNING] `[..]foo[..]`
+[RUNNING] `[..]foo[..]`
+[RUNNING] `[..]test1[..]`
+[DOCTEST] foo
+[RUNNING] `rustdoc --test [..]`
+"));
+    assert_that(
+        p.cargo("test --release -vv"),
+        execs().with_status(0).with_stderr_unordered(
+            "\
+[FRESH] bar [..]
+[FRESH] bdep [..]
+[FRESH] foo [..]
+[FINISHED] release [optimized] [..]
+[RUNNING] `[..]foo[..]`
+[RUNNING] `[..]foo[..]`
+[RUNNING] `[..]test1[..]`
+[DOCTEST] foo
+[RUNNING] `rustdoc --test [..]
+",
+        ),
+    );
+}
+
+#[test]
+fn profile_selection_bench() {
+    let p = all_target_project();
+
+    // Bench default.
+    // NOTES:
+    // - Dependency profiles:
+    //   Pkg  Target  Profile        Reason
+    //   ---  ------  -------        ------
+    //   bar  lib     release*       For bdep and foo
+    //   bar  lib     release-panic  For tests/benches
+    //   bdep lib     release*       For foo build.rs
+    //   foo  custom  release*
+    //
+    //   `*` = wants panic, but it is cleared when args are built.
+    //
+    // - foo target list is:
+    //   Target   Profile        Mode
+    //   ------   -------        ----
+    //   lib      release-panic  build
+    //   lib      bench          bench
+    //   bench    bench          bench
+    //   bin      bench          bench
+    //   bin      release-panic  build
+    //
+    assert_that(p.cargo("bench -vv"), execs().with_status(0).with_stderr_unordered("\
+[COMPILING] bar [..]
+[RUNNING] `rustc --crate-name bar bar[/]src[/]lib.rs --crate-type lib --emit=dep-info,link -C opt-level=3 -C codegen-units=2 [..]
+[RUNNING] `rustc --crate-name bar bar[/]src[/]lib.rs --crate-type lib --emit=dep-info,link -C opt-level=3 -C codegen-units=2 [..]
+[COMPILING] bdep [..]
+[RUNNING] `rustc --crate-name bdep bdep[/]src[/]lib.rs --crate-type lib --emit=dep-info,link -C opt-level=3 -C codegen-units=2 [..]
+[COMPILING] foo [..]
+[RUNNING] `rustc --crate-name build_script_build build.rs --crate-type bin --emit=dep-info,link -C opt-level=3 -C codegen-units=2 [..]
+[RUNNING] `[..]target[/]release[/]build[/]foo-[..][/]build-script-build`
+foo custom build PROFILE=release DEBUG=false OPT_LEVEL=3
+[RUNNING] `rustc --crate-name foo src[/]lib.rs --crate-type lib --emit=dep-info,link -C opt-level=3 -C codegen-units=2 [..]
+[RUNNING] `rustc --crate-name foo src[/]lib.rs --emit=dep-info,link -C opt-level=3 -C codegen-units=4 --test [..]
+[RUNNING] `rustc --crate-name bench1 benches[/]bench1.rs --emit=dep-info,link -C opt-level=3 -C codegen-units=4 --test [..]
+[RUNNING] `rustc --crate-name foo src[/]main.rs --emit=dep-info,link -C opt-level=3 -C codegen-units=4 --test [..]
+[RUNNING] `rustc --crate-name foo src[/]main.rs --crate-type bin --emit=dep-info,link -C opt-level=3 -C codegen-units=2 [..]
+[FINISHED] release [optimized] [..]
+[RUNNING] `[..]foo[..] --bench`
+[RUNNING] `[..]foo[..] --bench`
+[RUNNING] `[..]bench1[..] --bench`
+"));
+    assert_that(
+        p.cargo("bench -vv"),
+        execs().with_status(0).with_stderr_unordered(
+            "\
+[FRESH] bar [..]
+[FRESH] bdep [..]
+[FRESH] foo [..]
+[FINISHED] release [optimized] [..]
+[RUNNING] `[..]foo[..] --bench`
+[RUNNING] `[..]foo[..] --bench`
+[RUNNING] `[..]bench1[..] --bench`
+",
+        ),
+    );
+}
+
+#[test]
+fn profile_selection_check_all_targets() {
+    let p = all_target_project();
+    // check
+    // NOTES:
+    // - Dependency profiles:
+    //   Pkg  Target  Profile    Action   Reason
+    //   ---  ------  -------    ------   ------
+    //   bar  lib     dev*       link     For bdep
+    //   bar  lib     dev-panic  metadata For tests/benches
+    //   bar  lib     dev        metadata For lib/bins
+    //   bdep lib     dev*       link     For foo build.rs
+    //   foo  custom  dev*       link     For build.rs
+    //
+    //   `*` = wants panic, but it is cleared when args are built.
+    //
+    // - foo target list is:
+    //   Target   Profile        Mode
+    //   ------   -------        ----
+    //   lib      dev            check
+    //   lib      dev-panic      check (for tests/benches)
+    //   lib      dev-panic      check-test (checking lib as a unittest)
+    //   example  dev            check
+    //   test     dev-panic      check-test
+    //   bench    dev-panic      check-test
+    //   bin      dev            check
+    //   bin      dev-panic      check-test (checking bin as a unittest)
+    //
+    assert_that(p.cargo("check --all-targets -vv"), execs().with_status(0).with_stderr_unordered("\
+[COMPILING] bar [..]
+[RUNNING] `rustc --crate-name bar bar[/]src[/]lib.rs --crate-type lib --emit=dep-info,link -C codegen-units=1 -C debuginfo=2 [..]
+[RUNNING] `rustc --crate-name bar bar[/]src[/]lib.rs --crate-type lib --emit=dep-info,metadata -C codegen-units=1 -C debuginfo=2 [..]
+[RUNNING] `rustc --crate-name bar bar[/]src[/]lib.rs --crate-type lib --emit=dep-info,metadata -C panic=abort -C codegen-units=1 -C debuginfo=2 [..]
+[COMPILING] bdep[..]
+[RUNNING] `rustc --crate-name bdep bdep[/]src[/]lib.rs --crate-type lib --emit=dep-info,link -C codegen-units=1 -C debuginfo=2 [..]
+[COMPILING] foo [..]
+[RUNNING] `rustc --crate-name build_script_build build.rs --crate-type bin --emit=dep-info,link -C codegen-units=1 -C debuginfo=2 [..]
+[RUNNING] `[..]target[/]debug[/]build[/]foo-[..][/]build-script-build`
+foo custom build PROFILE=debug DEBUG=true OPT_LEVEL=0
+[RUNNING] `rustc --crate-name foo src[/]lib.rs --crate-type lib --emit=dep-info,metadata -C panic=abort -C codegen-units=1 -C debuginfo=2 [..]
+[RUNNING] `rustc --crate-name foo src[/]lib.rs --crate-type lib --emit=dep-info,metadata -C codegen-units=1 -C debuginfo=2 [..]
+[RUNNING] `rustc --crate-name foo src[/]lib.rs --emit=dep-info,metadata -C codegen-units=1 -C debuginfo=2 --test [..]
+[RUNNING] `rustc --crate-name test1 tests[/]test1.rs --emit=dep-info,metadata -C codegen-units=1 -C debuginfo=2 --test [..]
+[RUNNING] `rustc --crate-name foo src[/]main.rs --emit=dep-info,metadata -C codegen-units=1 -C debuginfo=2 --test [..]
+[RUNNING] `rustc --crate-name bench1 benches[/]bench1.rs --emit=dep-info,metadata -C codegen-units=1 -C debuginfo=2 --test [..]
+[RUNNING] `rustc --crate-name ex1 examples[/]ex1.rs --crate-type bin --emit=dep-info,metadata -C panic=abort -C codegen-units=1 -C debuginfo=2 [..]
+[RUNNING] `rustc --crate-name foo src[/]main.rs --crate-type bin --emit=dep-info,metadata -C panic=abort -C codegen-units=1 -C debuginfo=2 [..]
+[FINISHED] dev [unoptimized + debuginfo] [..]
+"));
+    // Check re-run re-checks bins (and tests/benches) because rustc does not
+    // emit rmeta files for bins. See
+    // https://github.com/rust-lang/cargo/issues/3624.
+    assert_that(
+        p.cargo("check --all-targets -vv"),
+        execs().with_status(0).with_stderr_unordered(
+            "\
+[FRESH] bar [..]
+[FRESH] bdep [..]
+[CHECKING] foo [..]
+[RUNNING] `rustc --crate-name foo src[/]lib.rs --emit=dep-info,metadata -C codegen-units=1 -C debuginfo=2 --test [..]
+[RUNNING] `rustc --crate-name foo src[/]main.rs --emit=dep-info,metadata -C codegen-units=1 -C debuginfo=2 --test [..]
+[RUNNING] `rustc --crate-name bench1 benches[/]bench1.rs --emit=dep-info,metadata -C codegen-units=1 -C debuginfo=2 --test [..]
+[RUNNING] `rustc --crate-name test1 tests[/]test1.rs --emit=dep-info,metadata -C codegen-units=1 -C debuginfo=2 --test [..]
+[RUNNING] `rustc --crate-name foo src[/]main.rs --crate-type bin --emit=dep-info,metadata -C panic=abort -C codegen-units=1 -C debuginfo=2 [..]
+[RUNNING] `rustc --crate-name ex1 examples[/]ex1.rs --crate-type bin --emit=dep-info,metadata -C panic=abort -C codegen-units=1 -C debuginfo=2 [..]
+[FINISHED] dev [unoptimized + debuginfo] [..]
+",
+        ),
+    );
+}
+
+#[test]
+fn profile_selection_check_all_targets_release() {
+    let p = all_target_project();
+    // check --release
+    // https://github.com/rust-lang/cargo/issues/5218
+    // This is a pretty straightforward variant of
+    // `profile_selection_check_all_targets` that uses `release` instead of
+    // `dev` for all targets.
+    assert_that(p.cargo("check --all-targets --release -vv"), execs().with_status(0).with_stderr_unordered("\
+[COMPILING] bar [..]
+[RUNNING] `rustc --crate-name bar bar[/]src[/]lib.rs --crate-type lib --emit=dep-info,link -C opt-level=3 -C codegen-units=2 [..]
+[RUNNING] `rustc --crate-name bar bar[/]src[/]lib.rs --crate-type lib --emit=dep-info,metadata -C opt-level=3 -C codegen-units=2 [..]
+[RUNNING] `rustc --crate-name bar bar[/]src[/]lib.rs --crate-type lib --emit=dep-info,metadata -C opt-level=3 -C panic=abort -C codegen-units=2 [..]
+[COMPILING] bdep[..]
+[RUNNING] `rustc --crate-name bdep bdep[/]src[/]lib.rs --crate-type lib --emit=dep-info,link -C opt-level=3 -C codegen-units=2 [..]
+[COMPILING] foo [..]
+[RUNNING] `rustc --crate-name build_script_build build.rs --crate-type bin --emit=dep-info,link -C opt-level=3 -C codegen-units=2 [..]
+[RUNNING] `[..]target[/]release[/]build[/]foo-[..][/]build-script-build`
+foo custom build PROFILE=release DEBUG=false OPT_LEVEL=3
+[RUNNING] `rustc --crate-name foo src[/]lib.rs --crate-type lib --emit=dep-info,metadata -C opt-level=3 -C panic=abort -C codegen-units=2 [..]
+[RUNNING] `rustc --crate-name foo src[/]lib.rs --crate-type lib --emit=dep-info,metadata -C opt-level=3 -C codegen-units=2 [..]
+[RUNNING] `rustc --crate-name foo src[/]lib.rs --emit=dep-info,metadata -C opt-level=3 -C codegen-units=2 --test [..]
+[RUNNING] `rustc --crate-name test1 tests[/]test1.rs --emit=dep-info,metadata -C opt-level=3 -C codegen-units=2 --test [..]
+[RUNNING] `rustc --crate-name foo src[/]main.rs --emit=dep-info,metadata -C opt-level=3 -C codegen-units=2 --test [..]
+[RUNNING] `rustc --crate-name bench1 benches[/]bench1.rs --emit=dep-info,metadata -C opt-level=3 -C codegen-units=2 --test [..]
+[RUNNING] `rustc --crate-name ex1 examples[/]ex1.rs --crate-type bin --emit=dep-info,metadata -C opt-level=3 -C panic=abort -C codegen-units=2 [..]
+[RUNNING] `rustc --crate-name foo src[/]main.rs --crate-type bin --emit=dep-info,metadata -C opt-level=3 -C panic=abort -C codegen-units=2 [..]
+[FINISHED] release [optimized] [..]
+"));
+    // Check re-run re-checks bins (and tests/benches) because rustc does not
+    // emit rmeta files for bins. See
+    // https://github.com/rust-lang/cargo/issues/3624.
+    assert_that(
+        p.cargo("check --all-targets --release -vv"),
+        execs().with_status(0).with_stderr_unordered(
+            "\
+[FRESH] bar [..]
+[FRESH] bdep [..]
+[CHECKING] foo [..]
+[RUNNING] `rustc --crate-name foo src[/]lib.rs --emit=dep-info,metadata -C opt-level=3 -C codegen-units=2 --test [..]
+[RUNNING] `rustc --crate-name foo src[/]main.rs --emit=dep-info,metadata -C opt-level=3 -C codegen-units=2 --test [..]
+[RUNNING] `rustc --crate-name bench1 benches[/]bench1.rs --emit=dep-info,metadata -C opt-level=3 -C codegen-units=2 --test [..]
+[RUNNING] `rustc --crate-name test1 tests[/]test1.rs --emit=dep-info,metadata -C opt-level=3 -C codegen-units=2 --test [..]
+[RUNNING] `rustc --crate-name foo src[/]main.rs --crate-type bin --emit=dep-info,metadata -C opt-level=3 -C panic=abort -C codegen-units=2 [..]
+[RUNNING] `rustc --crate-name ex1 examples[/]ex1.rs --crate-type bin --emit=dep-info,metadata -C opt-level=3 -C panic=abort -C codegen-units=2 [..]
+[FINISHED] release [optimized] [..]
+",
+        ),
+    );
+}
+
+#[test]
+fn profile_selection_check_all_targets_test() {
+    let p = all_target_project();
+    // check --profile=test
+    // NOTES:
+    // - This doesn't actually use the "test" profile.  Everything uses dev.
+    //   It probably should use "test"???  Probably doesn't really matter.
+    // - Dependency profiles:
+    //   Pkg  Target  Profile    Action   Reason
+    //   ---  ------  -------    ------   ------
+    //   bar  lib     dev*       link     For bdep
+    //   bar  lib     dev-panic  metadata For tests/benches
+    //   bdep lib     dev*       link     For foo build.rs
+    //   foo  custom  dev*       link     For build.rs
+    //
+    //   `*` = wants panic, but it is cleared when args are built.
+    //
+    // - foo target list is:
+    //   Target   Profile    Mode
+    //   ------   -------    ----
+    //   lib      dev-panic  check-test (for tests/benches)
+    //   lib      dev-panic  check-test (checking lib as a unittest)
+    //   example  dev-panic  check-test
+    //   test     dev-panic  check-test
+    //   bench    dev-panic  check-test
+    //   bin      dev-panic  check-test
+    //
+    assert_that(p.cargo("check --all-targets --profile=test -vv"), execs().with_status(0).with_stderr_unordered("\
+[COMPILING] bar [..]
+[RUNNING] `rustc --crate-name bar bar[/]src[/]lib.rs --crate-type lib --emit=dep-info,link -C codegen-units=1 -C debuginfo=2 [..]
+[RUNNING] `rustc --crate-name bar bar[/]src[/]lib.rs --crate-type lib --emit=dep-info,metadata -C codegen-units=1 -C debuginfo=2 [..]
+[COMPILING] bdep[..]
+[RUNNING] `rustc --crate-name bdep bdep[/]src[/]lib.rs --crate-type lib --emit=dep-info,link -C codegen-units=1 -C debuginfo=2 [..]
+[COMPILING] foo [..]
+[RUNNING] `rustc --crate-name build_script_build build.rs --crate-type bin --emit=dep-info,link -C codegen-units=1 -C debuginfo=2 [..]
+[RUNNING] `[..]target[/]debug[/]build[/]foo-[..][/]build-script-build`
+foo custom build PROFILE=debug DEBUG=true OPT_LEVEL=0
+[RUNNING] `rustc --crate-name foo src[/]lib.rs --crate-type lib --emit=dep-info,metadata -C codegen-units=1 -C debuginfo=2 [..]
+[RUNNING] `rustc --crate-name foo src[/]lib.rs --emit=dep-info,metadata -C codegen-units=1 -C debuginfo=2 --test [..]
+[RUNNING] `rustc --crate-name test1 tests[/]test1.rs --emit=dep-info,metadata -C codegen-units=1 -C debuginfo=2 --test [..]
+[RUNNING] `rustc --crate-name foo src[/]main.rs --emit=dep-info,metadata -C codegen-units=1 -C debuginfo=2 --test [..]
+[RUNNING] `rustc --crate-name bench1 benches[/]bench1.rs --emit=dep-info,metadata -C codegen-units=1 -C debuginfo=2 --test [..]
+[RUNNING] `rustc --crate-name ex1 examples[/]ex1.rs --emit=dep-info,metadata -C codegen-units=1 -C debuginfo=2 --test [..]
+[FINISHED] dev [unoptimized + debuginfo] [..]
+"));
+    // Check re-run re-checks bins (and tests/benches) because rustc does not
+    // emit rmeta files for bins. See
+    // https://github.com/rust-lang/cargo/issues/3624.
+    assert_that(
+        p.cargo("check --all-targets --profile=test -vv"),
+        execs().with_status(0).with_stderr_unordered(
+            "\
+[FRESH] bar [..]
+[FRESH] bdep [..]
+[CHECKING] foo [..]
+[RUNNING] `rustc --crate-name foo src[/]lib.rs --emit=dep-info,metadata -C codegen-units=1 -C debuginfo=2 --test [..]
+[RUNNING] `rustc --crate-name foo src[/]main.rs --emit=dep-info,metadata -C codegen-units=1 -C debuginfo=2 --test [..]
+[RUNNING] `rustc --crate-name bench1 benches[/]bench1.rs --emit=dep-info,metadata -C codegen-units=1 -C debuginfo=2 --test [..]
+[RUNNING] `rustc --crate-name test1 tests[/]test1.rs --emit=dep-info,metadata -C codegen-units=1 -C debuginfo=2 --test [..]
+[RUNNING] `rustc --crate-name ex1 examples[/]ex1.rs --emit=dep-info,metadata -C codegen-units=1 -C debuginfo=2 --test [..]
+[FINISHED] dev [unoptimized + debuginfo] [..]
+",
+        ),
+    );
+}
+
+#[test]
+fn profile_selection_doc() {
+    let p = all_target_project();
+    // doc
+    // NOTES:
+    // - Dependency profiles:
+    //   Pkg  Target  Profile    Action   Reason
+    //   ---  ------  -------    ------   ------
+    //   bar  lib     dev*       link     For bdep
+    //   bar  lib     dev        metadata For rustdoc
+    //   bdep lib     dev*       link     For foo build.rs
+    //   foo  custom  dev*       link     For build.rs
+    //
+    //   `*` = wants panic, but it is cleared when args are built.
+    assert_that(p.cargo("doc -vv"), execs().with_status(0).with_stderr_unordered("\
+[COMPILING] bar [..]
+[DOCUMENTING] bar [..]
+[RUNNING] `rustc --crate-name bar bar[/]src[/]lib.rs --crate-type lib --emit=dep-info,link -C codegen-units=1 -C debuginfo=2 [..]
+[RUNNING] `rustdoc --crate-name bar bar[/]src[/]lib.rs [..]
+[RUNNING] `rustc --crate-name bar bar[/]src[/]lib.rs --crate-type lib --emit=dep-info,metadata -C panic=abort -C codegen-units=1 -C debuginfo=2 [..]
+[COMPILING] bdep [..]
+[RUNNING] `rustc --crate-name bdep bdep[/]src[/]lib.rs --crate-type lib --emit=dep-info,link -C codegen-units=1 -C debuginfo=2 [..]
+[COMPILING] foo [..]
+[RUNNING] `rustc --crate-name build_script_build build.rs --crate-type bin --emit=dep-info,link -C codegen-units=1 -C debuginfo=2 [..]
+[RUNNING] `[..]target[/]debug[/]build[/]foo-[..][/]build-script-build`
+foo custom build PROFILE=debug DEBUG=true OPT_LEVEL=0
+[DOCUMENTING] foo [..]
+[RUNNING] `rustdoc --crate-name foo src[/]lib.rs [..]
+[FINISHED] dev [unoptimized + debuginfo] [..]
+"));
+}