Skip to content

Commit

Permalink
add CARGO_WORKSPACE_DIR env var for integration tests and benchmarks
Browse files Browse the repository at this point in the history
  • Loading branch information
yerke committed May 30, 2023
1 parent 09276c7 commit 3699f8c
Show file tree
Hide file tree
Showing 3 changed files with 264 additions and 1 deletion.
16 changes: 16 additions & 0 deletions src/cargo/core/compiler/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -726,6 +726,22 @@ fn prepare_rustc(
if unit.target.is_test() || unit.target.is_bench() {
let tmp = cx.files().layout(unit.kind).prepare_tmp()?;
base.env("CARGO_TARGET_TMPDIR", tmp.display().to_string());

if cx.bcx.config.nightly_features_allowed {
// Use a relative path and limit to integration tests and benchmarks in hopes
// that it conveys to the user that the meaning of this value is a bit fuzzy
// (very different meaning in the original repo vs once published).
let cargo_workspace_dir = if is_primary && is_workspace {
pathdiff::diff_paths(cx.bcx.ws.root(), unit.pkg.root())
.expect("both paths are absolute")
.display()
.to_string()
} else {
// path from unit.pkg.root() to unit.pkg.root()
".".to_string()
};
base.env("CARGO_WORKSPACE_DIR", cargo_workspace_dir);
}
}

base.inherit_jobserver(&cx.jobserver);
Expand Down
5 changes: 5 additions & 0 deletions src/doc/src/reference/environment-variables.md
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,11 @@ corresponding environment variable is set to the empty string, `""`.
where integration tests or benchmarks are free to put any data needed by
the tests/benches. Cargo initially creates this directory but doesn't
manage its content in any way, this is the responsibility of the test code.
* `CARGO_WORKSPACE_DIR` --- Only set when building [integration test] or benchmark code.
This is a path to the workspace directory of the package being built. When there is
no associated workspace, which includes all registry packages, this will be a path to
the directory that contains the manifest of the package.
Currently, it is implemented as a relative path.

[Cargo target]: cargo-targets.md
[binaries]: cargo-targets.md#binaries
Expand Down
244 changes: 243 additions & 1 deletion tests/testsuite/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1383,7 +1383,7 @@ fn cargo_default_env_metadata_env_var() {
}

#[cargo_test]
fn crate_env_vars() {
fn crate_env_vars_without_workspace() {
let p = project()
.file(
"Cargo.toml",
Expand Down Expand Up @@ -1451,6 +1451,9 @@ fn crate_env_vars() {
// Verify CARGO_TARGET_TMPDIR isn't set for bins
assert!(option_env!("CARGO_TARGET_TMPDIR").is_none());
// Verify CARGO_WORKSPACE_DIR isn't set for bins
assert!(option_env!("CARGO_WORKSPACE_DIR").is_none());
}
"#,
)
Expand Down Expand Up @@ -1494,6 +1497,10 @@ fn crate_env_vars() {
// Check that CARGO_TARGET_TMPDIR isn't set for unit tests
assert!(option_env!("CARGO_TARGET_TMPDIR").is_none());
env::var("CARGO_TARGET_TMPDIR").unwrap_err();
// Check that CARGO_WORKSPACE_DIR isn't set for unit tests
assert!(option_env!("CARGO_WORKSPACE_DIR").is_none());
env::var("CARGO_WORKSPACE_DIR").unwrap_err();
}
"#,
)
Expand All @@ -1511,6 +1518,9 @@ fn crate_env_vars() {
// Verify CARGO_TARGET_TMPDIR isn't set for examples
assert!(option_env!("CARGO_TARGET_TMPDIR").is_none());
// Verify CARGO_WORKSPACE_DIR isn't set for examples
assert!(option_env!("CARGO_WORKSPACE_DIR").is_none());
}
"#,
)
Expand All @@ -1520,6 +1530,9 @@ fn crate_env_vars() {
#[test]
fn env() {
foo::check_tmpdir(option_env!("CARGO_TARGET_TMPDIR"));
// Verify CARGO_WORKSPACE_DIR isn't set for integration tests without masquerade_as_nightly_cargo()
assert!(option_env!("CARGO_WORKSPACE_DIR").is_none());
}
"#,
);
Expand All @@ -1535,6 +1548,9 @@ fn crate_env_vars() {
#[bench]
fn env(_: &mut Bencher) {
foo::check_tmpdir(option_env!("CARGO_TARGET_TMPDIR"));
// Verify CARGO_WORKSPACE_DIR isn't set for benches without masquerade_as_nightly_cargo()
assert!(option_env!("CARGO_WORKSPACE_DIR").is_none());
}
"#,
)
Expand Down Expand Up @@ -1563,6 +1579,232 @@ fn crate_env_vars() {
}
}

#[cargo_test]
fn nightly_cargo_workspace_dir_env_var_with_workspace() {
Package::new("bar", "0.1.0")
.file("src/lib.rs", "#[test] fn bar() {}")
.file(
"tests/env.rs",
r#"
use std::path::Path;
#[test]
fn env() {
assert!(Path::new(option_env!("CARGO_WORKSPACE_DIR").unwrap()).join(file!()).exists());
assert_eq!(std::fs::canonicalize(option_env!("CARGO_WORKSPACE_DIR").unwrap()).unwrap().display().to_string(), option_env!("CARGO_MANIFEST_DIR").unwrap());
}
"#,
)
.publish();

let p = project()
.file(
"Cargo.toml",
r#"
[workspace]
members = ["foo"]
"#,
)
.file(
"foo/Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
authors = []
[dependencies]
bar = "0.1.0"
[[bin]]
name = "foo-bar"
path = "src/main.rs"
"#,
)
.file(
"foo/src/main.rs",
r#"
fn main() {
// Verify CARGO_WORKSPACE_DIR isn't set for bins
assert!(option_env!("CARGO_WORKSPACE_DIR").is_none());
}
"#,
)
.file(
"foo/src/lib.rs",
r#"
use std::env;
#[test]
fn env() {
// Check that CARGO_WORKSPACE_DIR isn't set for unit tests
assert!(option_env!("CARGO_WORKSPACE_DIR").is_none());
env::var("CARGO_WORKSPACE_DIR").unwrap_err();
}
"#,
)
.file(
"foo/examples/ex-env-vars.rs",
r#"
fn main() {
// Verify CARGO_WORKSPACE_DIR isn't set for examples
assert!(option_env!("CARGO_WORKSPACE_DIR").is_none());
}
"#,
)
.file(
"foo/tests/env.rs",
r#"
use std::path::Path;
#[test]
fn env() {
assert!(Path::new(option_env!("CARGO_WORKSPACE_DIR").unwrap()).join(file!()).exists());
}
"#,
);

let p = if is_nightly() {
p.file(
"foo/benches/env.rs",
r#"
#![feature(test)]
extern crate test;
use std::path::Path;
use test::Bencher;
#[bench]
fn env(_: &mut Bencher) {
assert!(Path::new(option_env!("CARGO_WORKSPACE_DIR").unwrap()).join(file!()).exists());
}
"#,
)
.build()
} else {
p.build()
};

println!("build");
p.cargo("build -v").run();

println!("bin");
p.process(&p.bin("foo-bar")).run();

println!("example");
p.cargo("run --example ex-env-vars -v").run();

println!("test");
p.cargo("test -v").masquerade_as_nightly_cargo(&[]).run();

if is_nightly() {
println!("bench");
p.cargo("bench -v").masquerade_as_nightly_cargo(&[]).run();
}

p.cargo("test -p bar")
.masquerade_as_nightly_cargo(&[])
.with_stdout_contains("running 1 test\ntest bar ... ok")
.run();
}

#[cargo_test]
fn nightly_cargo_workspace_dir_env_var_without_workspace() {
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
authors = []
[[bin]]
name = "foo-bar"
path = "src/main.rs"
"#,
)
.file(
"src/main.rs",
r#"
extern crate foo;
fn main() {
// Verify CARGO_WORKSPACE_DIR isn't set for bins
assert!(option_env!("CARGO_WORKSPACE_DIR").is_none());
}
"#,
)
.file(
"src/lib.rs",
r#"
use std::env;
#[test]
fn env() {
// Check that CARGO_WORKSPACE_DIR isn't set for unit tests
assert!(option_env!("CARGO_WORKSPACE_DIR").is_none());
env::var("CARGO_WORKSPACE_DIR").unwrap_err();
}
"#,
)
.file(
"examples/ex-env-vars.rs",
r#"
fn main() {
// Verify CARGO_WORKSPACE_DIR isn't set for examples
assert!(option_env!("CARGO_WORKSPACE_DIR").is_none());
}
"#,
)
.file(
"tests/env.rs",
r#"
use std::path::Path;
#[test]
fn env() {
assert!(Path::new(option_env!("CARGO_WORKSPACE_DIR").unwrap()).join(file!()).exists());
}
"#,
);

let p = if is_nightly() {
p.file(
"benches/env.rs",
r#"
#![feature(test)]
extern crate test;
use std::path::Path;
use test::Bencher;
#[bench]
fn env(_: &mut Bencher) {
assert!(Path::new(option_env!("CARGO_WORKSPACE_DIR").unwrap()).join(file!()).exists());
}
"#,
)
.build()
} else {
p.build()
};

println!("build");
p.cargo("build -v").run();

println!("bin");
p.process(&p.bin("foo-bar")).run();

println!("example");
p.cargo("run --example ex-env-vars -v").run();

println!("test");
p.cargo("test -v").masquerade_as_nightly_cargo(&[]).run();

if is_nightly() {
println!("bench");
p.cargo("bench -v").masquerade_as_nightly_cargo(&[]).run();
}
}

#[cargo_test]
fn crate_authors_env_vars() {
let p = project()
Expand Down

0 comments on commit 3699f8c

Please sign in to comment.