From 3489428921671b274b08ebbabd00128d56ebaa00 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 11 Dec 2019 08:26:08 -0800 Subject: [PATCH 1/3] Set an environment variable for tests to find executables. --- .../compiler/context/compilation_files.rs | 32 ++++++++++++- src/cargo/core/compiler/mod.rs | 17 +++++++ .../src/reference/environment-variables.md | 9 ++++ tests/testsuite/test.rs | 47 +++++++++++++++++++ 4 files changed, 104 insertions(+), 1 deletion(-) diff --git a/src/cargo/core/compiler/context/compilation_files.rs b/src/cargo/core/compiler/context/compilation_files.rs index 1f8286d06ce..ae885d06797 100644 --- a/src/cargo/core/compiler/context/compilation_files.rs +++ b/src/cargo/core/compiler/context/compilation_files.rs @@ -10,7 +10,7 @@ use log::info; use super::{BuildContext, CompileKind, Context, FileFlavor, Layout}; use crate::core::compiler::{CompileMode, CompileTarget, Unit}; -use crate::core::{TargetKind, Workspace}; +use crate::core::{Target, TargetKind, Workspace}; use crate::util::{self, CargoResult}; /// The `Metadata` is a hash used to make unique file names for each unit in a build. @@ -241,6 +241,36 @@ impl<'a, 'cfg: 'a> CompilationFiles<'a, 'cfg> { } } + /// Returns the path to the executable binary for the given bin target. + /// + /// This should only to be used when a `Unit` is not available. + pub fn bin_link_for_target( + &self, + target: &Target, + kind: CompileKind, + bcx: &BuildContext<'_, '_>, + ) -> CargoResult { + assert!(target.is_bin()); + let dest = self.layout(kind).dest(); + let info = bcx.info(kind); + let file_types = info + .file_types( + "bin", + FileFlavor::Normal, + &TargetKind::Bin, + kind.short_name(bcx), + )? + .expect("target must support `bin`"); + + let file_type = file_types + .iter() + .filter(|file_type| file_type.flavor == FileFlavor::Normal) + .next() + .expect("target must support `bin`"); + + Ok(dest.join(file_type.filename(target.name()))) + } + /// Returns the filenames that the given unit will generate. pub(super) fn outputs( &self, diff --git a/src/cargo/core/compiler/mod.rs b/src/cargo/core/compiler/mod.rs index 5052d790d8e..b763f5b317f 100644 --- a/src/cargo/core/compiler/mod.rs +++ b/src/cargo/core/compiler/mod.rs @@ -876,6 +876,23 @@ fn build_base_args<'a, 'cfg>( cmd.arg("-Zforce-unstable-if-unmarked") .env("RUSTC_BOOTSTRAP", "1"); } + + // Add `CARGO_BIN_` environment variables for building tests. + if unit.target.is_test() || unit.target.is_bench() { + for bin_target in unit + .pkg + .manifest() + .targets() + .iter() + .filter(|target| target.is_bin()) + { + let exe_path = cx + .files() + .bin_link_for_target(bin_target, unit.kind, cx.bcx)?; + let key = format!("CARGO_BIN_EXE_{}", bin_target.crate_name().to_uppercase()); + cmd.env(&key, exe_path); + } + } Ok(()) } diff --git a/src/doc/src/reference/environment-variables.md b/src/doc/src/reference/environment-variables.md index 44b018b858c..c99f708e236 100644 --- a/src/doc/src/reference/environment-variables.md +++ b/src/doc/src/reference/environment-variables.md @@ -187,6 +187,15 @@ let version = env!("CARGO_PKG_VERSION"); * `OUT_DIR` — If the package has a build script, this is set to the folder where the build script should place its output. See below for more information. (Only set during compilation.) +* `CARGO_BIN_EXE_` — The absolute path to a binary target's executable. + This is only set when building an [integration test] or benchmark. This may + be used with the [`env` macro] to find the executable to run for testing + purposes. The `` is the name of the binary converted to uppercase, and + `-` converted to `_`. Binaries are automatically built when the test is + built, unless the binary has required features that are not enabled. + +[integration test]: manifest.md#integration-tests +[`env` macro]: ../../std/macro.env.html #### Dynamic library paths diff --git a/tests/testsuite/test.rs b/tests/testsuite/test.rs index a092002fcc8..c685b51ce8c 100644 --- a/tests/testsuite/test.rs +++ b/tests/testsuite/test.rs @@ -3995,3 +3995,50 @@ fn panic_abort_test_profile_inherits() { .with_status(0) .run(); } + +#[cargo_test] +fn bin_env_for_test() { + // Test for the `CARGO_BIN_` 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ÜSSEN"), ""); + } + "# + .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(); +} From 499f917c03f4a4956b83bb497f247e75311528ee Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Thu, 6 Feb 2020 08:30:09 -0800 Subject: [PATCH 2/3] Switch to case-sensitive environment variable. --- src/cargo/core/compiler/mod.rs | 2 +- src/doc/src/reference/environment-variables.md | 7 ++++--- tests/testsuite/test.rs | 6 +++--- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/cargo/core/compiler/mod.rs b/src/cargo/core/compiler/mod.rs index b763f5b317f..1995501b6cc 100644 --- a/src/cargo/core/compiler/mod.rs +++ b/src/cargo/core/compiler/mod.rs @@ -889,7 +889,7 @@ fn build_base_args<'a, 'cfg>( let exe_path = cx .files() .bin_link_for_target(bin_target, unit.kind, cx.bcx)?; - let key = format!("CARGO_BIN_EXE_{}", bin_target.crate_name().to_uppercase()); + let key = format!("CARGO_BIN_EXE_{}", bin_target.name()); cmd.env(&key, exe_path); } } diff --git a/src/doc/src/reference/environment-variables.md b/src/doc/src/reference/environment-variables.md index c99f708e236..6ba68c6ae7a 100644 --- a/src/doc/src/reference/environment-variables.md +++ b/src/doc/src/reference/environment-variables.md @@ -190,9 +190,10 @@ let version = env!("CARGO_PKG_VERSION"); * `CARGO_BIN_EXE_` — The absolute path to a binary target's executable. This is only set when building an [integration test] or benchmark. This may be used with the [`env` macro] to find the executable to run for testing - purposes. The `` is the name of the binary converted to uppercase, and - `-` converted to `_`. Binaries are automatically built when the test is - built, unless the binary has required features that are not enabled. + purposes. The `` is the name of the binary target, exactly as-is. For + example, `CARGO_BIN_EXE_my-program` for a binary named `my-program`. + Binaries are automatically built when the test is built, unless the binary + has required features that are not enabled. [integration test]: manifest.md#integration-tests [`env` macro]: ../../std/macro.env.html diff --git a/tests/testsuite/test.rs b/tests/testsuite/test.rs index c685b51ce8c..9d356bc92fe 100644 --- a/tests/testsuite/test.rs +++ b/tests/testsuite/test.rs @@ -4029,9 +4029,9 @@ fn bin_env_for_test() { &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ÜSSEN"), ""); + 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")) From 4cf531f5a6939fb92c095dd76e252bf778815b01 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Thu, 6 Feb 2020 22:03:59 -0800 Subject: [PATCH 3/3] Add more docs on CARGO_BIN_EXE_. --- src/doc/man/cargo-test.adoc | 8 ++++++++ src/doc/man/generated/cargo-test.html | 9 +++++++++ src/doc/src/reference/cargo-targets.md | 9 +++++++++ src/doc/src/reference/environment-variables.md | 2 +- src/etc/man/cargo-test.1 | 14 ++++++++++++-- 5 files changed, 39 insertions(+), 3 deletions(-) diff --git a/src/doc/man/cargo-test.adoc b/src/doc/man/cargo-test.adoc index a4e6d80ed4c..32aa5ff6688 100644 --- a/src/doc/man/cargo-test.adoc +++ b/src/doc/man/cargo-test.adoc @@ -74,6 +74,14 @@ ignore the `test` flag and will always test the given target. Doc tests for libraries may be disabled by setting `doctest = false` for the library in the manifest. +Binary targets are automatically built if there is an integration test or +benchmark. This allows an integration test to execute the binary to exercise +and test its behavior. The `CARGO_BIN_EXE_` +linkcargo:reference/environment-variables.html#environment-variables-cargo-sets-for-crates[environment variable] +is set when the integration test is built so that it can use the +link:https://doc.rust-lang.org/std/macro.env.html[`env` macro] to locate the +executable. + include::options-targets.adoc[] *--doc*:: diff --git a/src/doc/man/generated/cargo-test.html b/src/doc/man/generated/cargo-test.html index faa7ee72292..bbf162dc88f 100644 --- a/src/doc/man/generated/cargo-test.html +++ b/src/doc/man/generated/cargo-test.html @@ -154,6 +154,15 @@

Target Selection

library in the manifest.

+

Binary targets are automatically built if there is an integration test or +benchmark. This allows an integration test to execute the binary to exercise +and test its behavior. The CARGO_BIN_EXE_<name> +environment variable +is set when the integration test is built so that it can use the +env macro to locate the +executable.

+
+

Passing target selection flags will test only the specified targets.

diff --git a/src/doc/src/reference/cargo-targets.md b/src/doc/src/reference/cargo-targets.md index 4be13c3529f..ebff8be475d 100644 --- a/src/doc/src/reference/cargo-targets.md +++ b/src/doc/src/reference/cargo-targets.md @@ -123,6 +123,15 @@ modules. The libtest harness will automatically find all of the `#[test]` annotated functions and run them in parallel. You can pass module names to [`cargo test`] to only run the tests within that module. +Binary targets are automatically built if there is an integration test. This +allows an integration test to execute the binary to exercise and test its +behavior. The `CARGO_BIN_EXE_` [environment variable] is set when the +integration test is built so that it can use the [`env` macro] to locate the +executable. + +[environment variable]: environment-variables.md#environment-variables-cargo-sets-for-crates +[`env` macro]: ../../std/macro.env.html + ### Benchmarks Benchmarks provide a way to test the performance of your code using the diff --git a/src/doc/src/reference/environment-variables.md b/src/doc/src/reference/environment-variables.md index 6ba68c6ae7a..bfd973a7932 100644 --- a/src/doc/src/reference/environment-variables.md +++ b/src/doc/src/reference/environment-variables.md @@ -195,7 +195,7 @@ let version = env!("CARGO_PKG_VERSION"); Binaries are automatically built when the test is built, unless the binary has required features that are not enabled. -[integration test]: manifest.md#integration-tests +[integration test]: cargo-targets.md#integration-tests [`env` macro]: ../../std/macro.env.html #### Dynamic library paths diff --git a/src/etc/man/cargo-test.1 b/src/etc/man/cargo-test.1 index 26a0aebf6bd..4ebb9def95f 100644 --- a/src/etc/man/cargo-test.1 +++ b/src/etc/man/cargo-test.1 @@ -2,12 +2,12 @@ .\" Title: cargo-test .\" Author: [see the "AUTHOR(S)" section] .\" Generator: Asciidoctor 2.0.10 -.\" Date: 2020-01-18 +.\" Date: 2020-02-06 .\" Manual: \ \& .\" Source: \ \& .\" Language: English .\" -.TH "CARGO\-TEST" "1" "2020-01-18" "\ \&" "\ \&" +.TH "CARGO\-TEST" "1" "2020-02-06" "\ \&" "\ \&" .ie \n(.g .ds Aq \(aq .el .ds Aq ' .ss \n[.ss] 0 @@ -206,6 +206,16 @@ ignore the \fBtest\fP flag and will always test the given target. Doc tests for libraries may be disabled by setting \fBdoctest = false\fP for the library in the manifest. .sp +Binary targets are automatically built if there is an integration test or +benchmark. This allows an integration test to execute the binary to exercise +and test its behavior. The \fBCARGO_BIN_EXE_\fP +\c +.URL "https://doc.rust\-lang.org/cargo/reference/environment\-variables.html#environment\-variables\-cargo\-sets\-for\-crates" "environment variable" +is set when the integration test is built so that it can use the +.URL "https://doc.rust\-lang.org/std/macro.env.html" "\fBenv\fP macro" " " +to locate the +executable. +.sp Passing target selection flags will test only the specified targets. .sp