Skip to content

Commit

Permalink
[nextest-runner] set env vars from build script
Browse files Browse the repository at this point in the history
Set environment variables specified via `cargo::rustc-env` in the build
script when running tests
  • Loading branch information
chrjabs committed Oct 17, 2024
1 parent 93fcd9e commit 719a640
Show file tree
Hide file tree
Showing 12 changed files with 96 additions and 2 deletions.
1 change: 1 addition & 0 deletions fixture-data/src/nextest_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ pub static EXPECTED_TEST_SUITES: Lazy<BTreeMap<RustBinaryId, TestSuiteFixture>>
"with-build-script",
BuildPlatform::Target,
vec![
TestCaseFixture::new("tests::test_build_script_vars_set", TestCaseFixtureStatus::Pass),
TestCaseFixture::new("tests::test_out_dir_present", TestCaseFixtureStatus::Pass),
],
),
Expand Down
24 changes: 24 additions & 0 deletions fixtures/nextest-tests/with-build-script/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,28 @@ fn main() {

// The presence of this file is checked by a test.
std::fs::write(out_dir.join("this-is-a-test-file"), "test-contents").unwrap();

// Needed for 1.79+
println!("cargo:rustc-check-cfg=cfg(new_format)");

// The presence of these environment variables is checked by a test.
if rustc_minor_version().is_some_and(|minor| minor >= 77) {
println!("cargo::rustc-cfg=new_format");
println!("cargo::rustc-env=BUILD_SCRIPT_NEW_FMT=new_val");
}
println!("cargo:rustc-env=BUILD_SCRIPT_OLD_FMT=old_val");
}

fn rustc_minor_version() -> Option<u32> {
let rustc = std::env::var_os("RUSTC")?;
let output = std::process::Command::new(rustc)
.arg("--version")
.output()
.ok()?;
let version = std::str::from_utf8(&output.stdout).ok()?;
let mut pieces = version.split('.');
if pieces.next() != Some("rustc 1") {
return None;
}
pieces.next()?.parse().ok()
}
13 changes: 13 additions & 0 deletions fixtures/nextest-tests/with-build-script/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,17 @@ mod tests {
let contents = std::fs::read(&path).expect("test file exists in OUT_DIR");
assert_eq!(contents, b"test-contents");
}

#[test]
fn test_build_script_vars_set() {
// Sinc the build script wrote `cargo::rustc-env` instructions, these variables are
// expected to be set by nextest
#[cfg(new_format)]
{
let val = std::env::var("BUILD_SCRIPT_NEW_FMT").expect("BUILD_SCRIPT_NEW_FMT is valid");
assert_eq!(val, "new_val");
}
let val = std::env::var("BUILD_SCRIPT_OLD_FMT").expect("BUILD_SCRIPT_OLD_FMT is valid");
assert_eq!(val, "old_val");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,5 @@ nextest-tests::example/nextest-tests:
nextest-tests::example/other:
tests::other_example_success
with-build-script:
tests::test_build_script_vars_set
tests::test_out_dir_present
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,5 @@ nextest-tests::example/nextest-tests:
nextest-tests::example/other:
tests::other_example_success
with-build-script:
tests::test_build_script_vars_set
tests::test_out_dir_present
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,5 @@ nextest-tests::example/nextest-tests:
nextest-tests::example/other:
tests::other_example_success
with-build-script:
tests::test_build_script_vars_set
tests::test_out_dir_present
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,5 @@ nextest-tests::example/nextest-tests:
nextest-tests::example/other:
tests::other_example_success
with-build-script:
tests::test_build_script_vars_set
tests::test_out_dir_present
Original file line number Diff line number Diff line change
Expand Up @@ -47,5 +47,6 @@ group: @global
nextest-tests::example/other:
tests::other_example_success
with-build-script:
tests::test_build_script_vars_set
tests::test_out_dir_present

Original file line number Diff line number Diff line change
Expand Up @@ -48,5 +48,6 @@ group: @global
nextest-tests::example/other:
tests::other_example_success
with-build-script:
tests::test_build_script_vars_set
tests::test_out_dir_present

Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,6 @@ group: @global
nextest-tests::example/other:
tests::other_example_success
with-build-script:
tests::test_build_script_vars_set
tests::test_out_dir_present

19 changes: 18 additions & 1 deletion nextest-runner/src/reuse_build/archiver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use std::{
io::{self, BufWriter, Write},
time::{Instant, SystemTime},
};
use tracing::{debug, trace};
use tracing::{debug, trace, warn};
use zstd::Encoder;

/// Archive format.
Expand Down Expand Up @@ -394,6 +394,23 @@ impl<'a, W: Write> Archiver<'a, W> {
false,
callback,
)?;

// Archive build script output in order to set environment variables from there
let Some(out_dir_parent) = build_script_out_dir.parent() else {
warn!("could not determine parent directory of output directory {build_script_out_dir}");
continue;

Check warning on line 401 in nextest-runner/src/reuse_build/archiver.rs

View check run for this annotation

Codecov / codecov/patch

nextest-runner/src/reuse_build/archiver.rs#L400-L401

Added lines #L400 - L401 were not covered by tests
};
let out_file_path = out_dir_parent.join("output");
let src_path = self
.binary_list
.rust_build_meta
.target_directory
.join(&out_file_path);

let rel_path = Utf8Path::new("target").join(out_file_path);
let rel_path = convert_rel_path_to_forward_slash(&rel_path);

self.append_file(ArchiveStep::BuildScriptOutDirs, &src_path, &rel_path)?;
}

// Write linked paths to the archive.
Expand Down
34 changes: 33 additions & 1 deletion nextest-runner/src/test_command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@ use once_cell::sync::Lazy;
use std::{
collections::{BTreeSet, HashMap},
ffi::{OsStr, OsString},
fs::File,
io::{BufRead, BufReader},
};
use tracing::warn;

mod imp;
pub use imp::{Child, Output};
Expand Down Expand Up @@ -74,7 +77,8 @@ impl TestCommand {
{
// Convert the output directory to an absolute path.
let out_dir = lctx.rust_build_meta.target_directory.join(out_dir);
cmd.env("OUT_DIR", out_dir);
cmd.env("OUT_DIR", &out_dir);
apply_build_script_env(&mut cmd, out_dir);
}

// Expose paths to non-test binaries at runtime so that relocated paths work.
Expand Down Expand Up @@ -191,6 +195,34 @@ fn apply_package_env(cmd: &mut std::process::Command, package: &PackageMetadata<
);
}

/// Applies environment variables spcified by the build script via `cargo::rustc-env`
fn apply_build_script_env(cmd: &mut std::process::Command, out_dir: Utf8PathBuf) {
let Some(out_dir_parent) = out_dir.parent() else {
warn!("could not determine parent directory of output directory {out_dir}");
return;

Check warning on line 202 in nextest-runner/src/test_command.rs

View check run for this annotation

Codecov / codecov/patch

nextest-runner/src/test_command.rs#L201-L202

Added lines #L201 - L202 were not covered by tests
};
let Ok(out_file) = File::open(out_dir_parent.join("output")) else {
warn!("could not find build script output file at {out_dir_parent}/output");
return;

Check warning on line 206 in nextest-runner/src/test_command.rs

View check run for this annotation

Codecov / codecov/patch

nextest-runner/src/test_command.rs#L205-L206

Added lines #L205 - L206 were not covered by tests
};
for line in BufReader::new(out_file).lines() {
let Ok(line) = line else {
warn!("found line with invalid UTF8 in build script output file at {out_dir_parent}/output");
continue;

Check warning on line 211 in nextest-runner/src/test_command.rs

View check run for this annotation

Codecov / codecov/patch

nextest-runner/src/test_command.rs#L210-L211

Added lines #L210 - L211 were not covered by tests
};
// `cargo::rustc-env` is the official syntax since `cargo` 1.77, `cargo:rustc-env` is
// supported for backwards compatibility
let Some(key_val) = line
.strip_prefix("cargo::rustc-env=")
.or_else(|| line.strip_prefix("cargo:rustc-env="))
else {
continue;
};
let split = key_val.find('=').unwrap();
cmd.env(&key_val[..split], &key_val[split + 1..]);
}
}

/// This is a workaround for a macOS SIP issue:
/// https://github.com/nextest-rs/nextest/pull/84
///
Expand Down

0 comments on commit 719a640

Please sign in to comment.