Skip to content

Commit 3699f8c

Browse files
committed
add CARGO_WORKSPACE_DIR env var for integration tests and benchmarks
1 parent 09276c7 commit 3699f8c

File tree

3 files changed

+264
-1
lines changed

3 files changed

+264
-1
lines changed

src/cargo/core/compiler/mod.rs

+16
Original file line numberDiff line numberDiff line change
@@ -726,6 +726,22 @@ fn prepare_rustc(
726726
if unit.target.is_test() || unit.target.is_bench() {
727727
let tmp = cx.files().layout(unit.kind).prepare_tmp()?;
728728
base.env("CARGO_TARGET_TMPDIR", tmp.display().to_string());
729+
730+
if cx.bcx.config.nightly_features_allowed {
731+
// Use a relative path and limit to integration tests and benchmarks in hopes
732+
// that it conveys to the user that the meaning of this value is a bit fuzzy
733+
// (very different meaning in the original repo vs once published).
734+
let cargo_workspace_dir = if is_primary && is_workspace {
735+
pathdiff::diff_paths(cx.bcx.ws.root(), unit.pkg.root())
736+
.expect("both paths are absolute")
737+
.display()
738+
.to_string()
739+
} else {
740+
// path from unit.pkg.root() to unit.pkg.root()
741+
".".to_string()
742+
};
743+
base.env("CARGO_WORKSPACE_DIR", cargo_workspace_dir);
744+
}
729745
}
730746

731747
base.inherit_jobserver(&cx.jobserver);

src/doc/src/reference/environment-variables.md

+5
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,11 @@ corresponding environment variable is set to the empty string, `""`.
257257
where integration tests or benchmarks are free to put any data needed by
258258
the tests/benches. Cargo initially creates this directory but doesn't
259259
manage its content in any way, this is the responsibility of the test code.
260+
* `CARGO_WORKSPACE_DIR` --- Only set when building [integration test] or benchmark code.
261+
This is a path to the workspace directory of the package being built. When there is
262+
no associated workspace, which includes all registry packages, this will be a path to
263+
the directory that contains the manifest of the package.
264+
Currently, it is implemented as a relative path.
260265

261266
[Cargo target]: cargo-targets.md
262267
[binaries]: cargo-targets.md#binaries

tests/testsuite/build.rs

+243-1
Original file line numberDiff line numberDiff line change
@@ -1383,7 +1383,7 @@ fn cargo_default_env_metadata_env_var() {
13831383
}
13841384

13851385
#[cargo_test]
1386-
fn crate_env_vars() {
1386+
fn crate_env_vars_without_workspace() {
13871387
let p = project()
13881388
.file(
13891389
"Cargo.toml",
@@ -1451,6 +1451,9 @@ fn crate_env_vars() {
14511451
14521452
// Verify CARGO_TARGET_TMPDIR isn't set for bins
14531453
assert!(option_env!("CARGO_TARGET_TMPDIR").is_none());
1454+
1455+
// Verify CARGO_WORKSPACE_DIR isn't set for bins
1456+
assert!(option_env!("CARGO_WORKSPACE_DIR").is_none());
14541457
}
14551458
"#,
14561459
)
@@ -1494,6 +1497,10 @@ fn crate_env_vars() {
14941497
// Check that CARGO_TARGET_TMPDIR isn't set for unit tests
14951498
assert!(option_env!("CARGO_TARGET_TMPDIR").is_none());
14961499
env::var("CARGO_TARGET_TMPDIR").unwrap_err();
1500+
1501+
// Check that CARGO_WORKSPACE_DIR isn't set for unit tests
1502+
assert!(option_env!("CARGO_WORKSPACE_DIR").is_none());
1503+
env::var("CARGO_WORKSPACE_DIR").unwrap_err();
14971504
}
14981505
"#,
14991506
)
@@ -1511,6 +1518,9 @@ fn crate_env_vars() {
15111518
15121519
// Verify CARGO_TARGET_TMPDIR isn't set for examples
15131520
assert!(option_env!("CARGO_TARGET_TMPDIR").is_none());
1521+
1522+
// Verify CARGO_WORKSPACE_DIR isn't set for examples
1523+
assert!(option_env!("CARGO_WORKSPACE_DIR").is_none());
15141524
}
15151525
"#,
15161526
)
@@ -1520,6 +1530,9 @@ fn crate_env_vars() {
15201530
#[test]
15211531
fn env() {
15221532
foo::check_tmpdir(option_env!("CARGO_TARGET_TMPDIR"));
1533+
1534+
// Verify CARGO_WORKSPACE_DIR isn't set for integration tests without masquerade_as_nightly_cargo()
1535+
assert!(option_env!("CARGO_WORKSPACE_DIR").is_none());
15231536
}
15241537
"#,
15251538
);
@@ -1535,6 +1548,9 @@ fn crate_env_vars() {
15351548
#[bench]
15361549
fn env(_: &mut Bencher) {
15371550
foo::check_tmpdir(option_env!("CARGO_TARGET_TMPDIR"));
1551+
1552+
// Verify CARGO_WORKSPACE_DIR isn't set for benches without masquerade_as_nightly_cargo()
1553+
assert!(option_env!("CARGO_WORKSPACE_DIR").is_none());
15381554
}
15391555
"#,
15401556
)
@@ -1563,6 +1579,232 @@ fn crate_env_vars() {
15631579
}
15641580
}
15651581

1582+
#[cargo_test]
1583+
fn nightly_cargo_workspace_dir_env_var_with_workspace() {
1584+
Package::new("bar", "0.1.0")
1585+
.file("src/lib.rs", "#[test] fn bar() {}")
1586+
.file(
1587+
"tests/env.rs",
1588+
r#"
1589+
use std::path::Path;
1590+
1591+
#[test]
1592+
fn env() {
1593+
assert!(Path::new(option_env!("CARGO_WORKSPACE_DIR").unwrap()).join(file!()).exists());
1594+
assert_eq!(std::fs::canonicalize(option_env!("CARGO_WORKSPACE_DIR").unwrap()).unwrap().display().to_string(), option_env!("CARGO_MANIFEST_DIR").unwrap());
1595+
}
1596+
"#,
1597+
)
1598+
.publish();
1599+
1600+
let p = project()
1601+
.file(
1602+
"Cargo.toml",
1603+
r#"
1604+
[workspace]
1605+
members = ["foo"]
1606+
"#,
1607+
)
1608+
.file(
1609+
"foo/Cargo.toml",
1610+
r#"
1611+
[package]
1612+
name = "foo"
1613+
version = "0.0.1"
1614+
authors = []
1615+
1616+
[dependencies]
1617+
bar = "0.1.0"
1618+
1619+
[[bin]]
1620+
name = "foo-bar"
1621+
path = "src/main.rs"
1622+
"#,
1623+
)
1624+
.file(
1625+
"foo/src/main.rs",
1626+
r#"
1627+
fn main() {
1628+
// Verify CARGO_WORKSPACE_DIR isn't set for bins
1629+
assert!(option_env!("CARGO_WORKSPACE_DIR").is_none());
1630+
}
1631+
"#,
1632+
)
1633+
.file(
1634+
"foo/src/lib.rs",
1635+
r#"
1636+
use std::env;
1637+
1638+
#[test]
1639+
fn env() {
1640+
// Check that CARGO_WORKSPACE_DIR isn't set for unit tests
1641+
assert!(option_env!("CARGO_WORKSPACE_DIR").is_none());
1642+
env::var("CARGO_WORKSPACE_DIR").unwrap_err();
1643+
}
1644+
"#,
1645+
)
1646+
.file(
1647+
"foo/examples/ex-env-vars.rs",
1648+
r#"
1649+
fn main() {
1650+
// Verify CARGO_WORKSPACE_DIR isn't set for examples
1651+
assert!(option_env!("CARGO_WORKSPACE_DIR").is_none());
1652+
}
1653+
"#,
1654+
)
1655+
.file(
1656+
"foo/tests/env.rs",
1657+
r#"
1658+
use std::path::Path;
1659+
1660+
#[test]
1661+
fn env() {
1662+
assert!(Path::new(option_env!("CARGO_WORKSPACE_DIR").unwrap()).join(file!()).exists());
1663+
}
1664+
"#,
1665+
);
1666+
1667+
let p = if is_nightly() {
1668+
p.file(
1669+
"foo/benches/env.rs",
1670+
r#"
1671+
#![feature(test)]
1672+
extern crate test;
1673+
use std::path::Path;
1674+
use test::Bencher;
1675+
1676+
#[bench]
1677+
fn env(_: &mut Bencher) {
1678+
assert!(Path::new(option_env!("CARGO_WORKSPACE_DIR").unwrap()).join(file!()).exists());
1679+
}
1680+
"#,
1681+
)
1682+
.build()
1683+
} else {
1684+
p.build()
1685+
};
1686+
1687+
println!("build");
1688+
p.cargo("build -v").run();
1689+
1690+
println!("bin");
1691+
p.process(&p.bin("foo-bar")).run();
1692+
1693+
println!("example");
1694+
p.cargo("run --example ex-env-vars -v").run();
1695+
1696+
println!("test");
1697+
p.cargo("test -v").masquerade_as_nightly_cargo(&[]).run();
1698+
1699+
if is_nightly() {
1700+
println!("bench");
1701+
p.cargo("bench -v").masquerade_as_nightly_cargo(&[]).run();
1702+
}
1703+
1704+
p.cargo("test -p bar")
1705+
.masquerade_as_nightly_cargo(&[])
1706+
.with_stdout_contains("running 1 test\ntest bar ... ok")
1707+
.run();
1708+
}
1709+
1710+
#[cargo_test]
1711+
fn nightly_cargo_workspace_dir_env_var_without_workspace() {
1712+
let p = project()
1713+
.file(
1714+
"Cargo.toml",
1715+
r#"
1716+
[package]
1717+
name = "foo"
1718+
version = "0.0.1"
1719+
authors = []
1720+
1721+
[[bin]]
1722+
name = "foo-bar"
1723+
path = "src/main.rs"
1724+
"#,
1725+
)
1726+
.file(
1727+
"src/main.rs",
1728+
r#"
1729+
extern crate foo;
1730+
1731+
fn main() {
1732+
// Verify CARGO_WORKSPACE_DIR isn't set for bins
1733+
assert!(option_env!("CARGO_WORKSPACE_DIR").is_none());
1734+
}
1735+
"#,
1736+
)
1737+
.file(
1738+
"src/lib.rs",
1739+
r#"
1740+
use std::env;
1741+
#[test]
1742+
fn env() {
1743+
// Check that CARGO_WORKSPACE_DIR isn't set for unit tests
1744+
assert!(option_env!("CARGO_WORKSPACE_DIR").is_none());
1745+
env::var("CARGO_WORKSPACE_DIR").unwrap_err();
1746+
}
1747+
"#,
1748+
)
1749+
.file(
1750+
"examples/ex-env-vars.rs",
1751+
r#"
1752+
fn main() {
1753+
// Verify CARGO_WORKSPACE_DIR isn't set for examples
1754+
assert!(option_env!("CARGO_WORKSPACE_DIR").is_none());
1755+
}
1756+
"#,
1757+
)
1758+
.file(
1759+
"tests/env.rs",
1760+
r#"
1761+
use std::path::Path;
1762+
1763+
#[test]
1764+
fn env() {
1765+
assert!(Path::new(option_env!("CARGO_WORKSPACE_DIR").unwrap()).join(file!()).exists());
1766+
}
1767+
"#,
1768+
);
1769+
1770+
let p = if is_nightly() {
1771+
p.file(
1772+
"benches/env.rs",
1773+
r#"
1774+
#![feature(test)]
1775+
extern crate test;
1776+
use std::path::Path;
1777+
use test::Bencher;
1778+
1779+
#[bench]
1780+
fn env(_: &mut Bencher) {
1781+
assert!(Path::new(option_env!("CARGO_WORKSPACE_DIR").unwrap()).join(file!()).exists());
1782+
}
1783+
"#,
1784+
)
1785+
.build()
1786+
} else {
1787+
p.build()
1788+
};
1789+
1790+
println!("build");
1791+
p.cargo("build -v").run();
1792+
1793+
println!("bin");
1794+
p.process(&p.bin("foo-bar")).run();
1795+
1796+
println!("example");
1797+
p.cargo("run --example ex-env-vars -v").run();
1798+
1799+
println!("test");
1800+
p.cargo("test -v").masquerade_as_nightly_cargo(&[]).run();
1801+
1802+
if is_nightly() {
1803+
println!("bench");
1804+
p.cargo("bench -v").masquerade_as_nightly_cargo(&[]).run();
1805+
}
1806+
}
1807+
15661808
#[cargo_test]
15671809
fn crate_authors_env_vars() {
15681810
let p = project()

0 commit comments

Comments
 (0)