integration_tests/env.rs
1// Copyright (c) The nextest Contributors
2// SPDX-License-Identifier: MIT OR Apache-2.0
3
4use camino::Utf8PathBuf;
5
6/// Environment info captured before sanitization.
7#[derive(Debug)]
8pub struct TestEnvInfo {
9 /// The workspace root, from `NEXTEST_WORKSPACE_ROOT`.
10 pub workspace_root: Utf8PathBuf,
11 /// Path to the cargo-nextest-dup binary.
12 pub cargo_nextest_dup_bin: Utf8PathBuf,
13 /// Path to the fake_interceptor binary.
14 pub fake_interceptor_bin: Utf8PathBuf,
15 /// Path to the rustc_shim binary.
16 pub rustc_shim_bin: Utf8PathBuf,
17 /// Path to the passthrough binary.
18 pub passthrough_bin: Utf8PathBuf,
19 /// Path to the grab_foreground binary (Unix only).
20 #[cfg(unix)]
21 pub grab_foreground_bin: Utf8PathBuf,
22}
23
24/// Sets up environment variables for a setup script.
25///
26/// Setup scripts don't have access to `CARGO_BIN_EXE_*` or `NEXTEST_BIN_EXE_*`
27/// variables, so this only performs sanitization without capturing binary paths.
28pub fn set_env_vars_for_script() {
29 // SAFETY:
30 // https://nexte.st/docs/configuration/env-vars/#altering-the-environment-within-tests
31 unsafe {
32 sanitize_env();
33 }
34}
35
36/// Sets up environment variables for a test.
37///
38/// This captures binary paths from `NEXTEST_BIN_EXE_*` variables before
39/// sanitizing the environment.
40#[track_caller]
41pub fn set_env_vars_for_test() -> TestEnvInfo {
42 // Capture required values before sanitization removes NEXTEST_* and
43 // CARGO_* variables.
44 let workspace_root: Utf8PathBuf = std::env::var("NEXTEST_WORKSPACE_ROOT")
45 .expect("NEXTEST_WORKSPACE_ROOT should be set")
46 .into();
47 let cargo_nextest_dup_bin: Utf8PathBuf = std::env::var("NEXTEST_BIN_EXE_cargo_nextest_dup")
48 .expect("NEXTEST_BIN_EXE_cargo_nextest_dup should be set")
49 .into();
50 let fake_interceptor_bin: Utf8PathBuf = std::env::var("NEXTEST_BIN_EXE_fake_interceptor")
51 .expect("NEXTEST_BIN_EXE_fake_interceptor should be set")
52 .into();
53 let rustc_shim_bin: Utf8PathBuf = std::env::var("NEXTEST_BIN_EXE_rustc_shim")
54 .expect("NEXTEST_BIN_EXE_rustc_shim should be set")
55 .into();
56 let passthrough_bin: Utf8PathBuf = std::env::var("NEXTEST_BIN_EXE_passthrough")
57 .expect("NEXTEST_BIN_EXE_passthrough should be set")
58 .into();
59 #[cfg(unix)]
60 let grab_foreground_bin: Utf8PathBuf = std::env::var("NEXTEST_BIN_EXE_grab_foreground")
61 .expect("NEXTEST_BIN_EXE_grab_foreground should be set")
62 .into();
63
64 // Ensure NEXTEST_PROFILE is set (we're running under nextest).
65 std::env::var("NEXTEST_PROFILE").expect("NEXTEST_PROFILE should be set");
66
67 // SAFETY:
68 // https://nexte.st/docs/configuration/env-vars/#altering-the-environment-within-tests
69 unsafe {
70 sanitize_env();
71 }
72
73 TestEnvInfo {
74 workspace_root,
75 cargo_nextest_dup_bin,
76 fake_interceptor_bin,
77 rustc_shim_bin,
78 passthrough_bin,
79 #[cfg(unix)]
80 grab_foreground_bin,
81 }
82}
83
84/// Sanitizes the environment by removing `NEXTEST_*` and `CARGO_*` variables
85/// and setting up variables needed for integration tests.
86///
87/// # Safety
88///
89/// This function modifies the process environment, which is not thread-safe.
90/// See <https://nexte.st/docs/configuration/env-vars/#altering-the-environment-within-tests>.
91unsafe fn sanitize_env() {
92 // Sanitize the environment by removing all NEXTEST_* and CARGO_* variables
93 // from the parent environment. This ensures deterministic behavior regardless
94 // of what the parent process has set. We'll then set specific variables below.
95
96 // Collect keys first to avoid mutating while iterating.
97 let keys_to_remove: Vec<_> = std::env::vars()
98 .filter(|(key, _)| key.starts_with("NEXTEST_") || key.starts_with("CARGO_"))
99 .map(|(key, _)| key)
100 .collect();
101 for key in keys_to_remove {
102 std::env::remove_var(&key);
103 }
104
105 // The dynamic library tests require this flag.
106 std::env::set_var("RUSTFLAGS", "-C prefer-dynamic");
107
108 // Set CARGO_TERM_COLOR to never to ensure that ANSI color codes don't
109 // interfere with the output.
110 std::env::set_var("CARGO_TERM_COLOR", "never");
111
112 // This environment variable is required to test the #[bench] fixture.
113 // Note that THIS IS FOR TEST CODE ONLY. NEVER USE THIS IN PRODUCTION.
114 std::env::set_var("RUSTC_BOOTSTRAP", "1");
115
116 // Disable the tests which check for environment variables being set in
117 // `config.toml`, as they won't be in the search path when running
118 // integration tests.
119 std::env::set_var("__NEXTEST_NO_CHECK_CARGO_ENV_VARS", "1");
120
121 // Display empty STDOUT and STDERR lines in the output of failed tests.
122 // This allows tests which make sure outputs are being displayed to
123 // work.
124 std::env::set_var("__NEXTEST_DISPLAY_EMPTY_OUTPUTS", "1");
125
126 // Remove OUT_DIR from the environment, as it interferes with tests
127 // (some of them expect that OUT_DIR isn't set.)
128 std::env::remove_var("OUT_DIR");
129
130 // Set NEXTEST_SHOW_PROGRESS to counter to ensure user config doesn't
131 // affect test output.
132 std::env::set_var("NEXTEST_SHOW_PROGRESS", "counter");
133
134 // Skip user config loading entirely for test isolation. This prevents
135 // the user's personal config from affecting test results. (Note that
136 // some config tests pass in --user-config-file, which overrides this
137 // environment variable.)
138 std::env::set_var("NEXTEST_USER_CONFIG_FILE", "none");
139}