Skip to content

Commit 2cdbc82

Browse files
committed
check: add tests
1 parent a58d241 commit 2cdbc82

File tree

1 file changed

+184
-3
lines changed

1 file changed

+184
-3
lines changed

src/check.rs

Lines changed: 184 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
use std::cmp::Ordering;
2+
use std::env;
3+
use std::sync::Mutex;
24

35
use color_eyre::{eyre, Result};
46
use semver::Version;
@@ -14,9 +16,29 @@ pub fn check_nix_version() -> Result<()> {
1416
let version = util::get_nix_version()?;
1517
let is_lix_binary = util::is_lix()?;
1618

19+
// XXX: Both Nix and Lix follow semantic versioning (semver). Update the
20+
// versions below once latest stable for either of those packages change.
21+
// TODO: Set up a CI to automatically update those in the future.
22+
const MIN_LIX_VERSION: &str = "2.91.1";
23+
const MIN_NIX_VERSION: &str = "2.24.14";
24+
1725
// Minimum supported versions. Those should generally correspond to
18-
// latest package versions in the stable branch
19-
let min_version = if is_lix_binary { "2.91.1" } else { "2.26.1" };
26+
// latest package versions in the stable branch.
27+
//
28+
// Q: Why are you doing this?
29+
// A: First of all to make sure we do not make baseless assumptions
30+
// about the user's system; we should only work around APIs that we
31+
// are fully aware of, and not try to work around every edge case.
32+
// Also, nh should be responsible for nudging the user to use the
33+
// relevant versions of the software it wraps, so that we do not have
34+
// to try and support too many versions. NixOS stable and unstable
35+
// will ALWAYS be supported, but outdated versions will not. If your
36+
// Nix fork uses a different versioning scheme, please open an issue.
37+
let min_version = if is_lix_binary {
38+
MIN_LIX_VERSION
39+
} else {
40+
MIN_NIX_VERSION
41+
};
2042

2143
let current = Version::parse(&version)?;
2244
let required = Version::parse(min_version)?;
@@ -85,7 +107,9 @@ pub fn setup_environment() -> Result<bool> {
85107
Ok(do_warn)
86108
}
87109

88-
/// Runs all necessary checks for Nix functionality
110+
/// Consolidate all necessary checks for Nix functionality into a single function. This
111+
/// will be executed in the main function, but can be executed before critical commands
112+
/// to double-check if necessary.
89113
///
90114
/// # Returns
91115
///
@@ -95,3 +119,160 @@ pub fn verify_nix_environment() -> Result<()> {
95119
check_nix_features()?;
96120
Ok(())
97121
}
122+
123+
// Environment variables are global state, so tests need to be run sequentially.
124+
// Using a mutex to ensure that env var manipulation in one test doesn't affect others.
125+
// Alternatively, run tests with `cargo test -- --test-threads=1`
126+
#[allow(dead_code)] // suppress 'false' positives
127+
static ENV_LOCK: Mutex<()> = Mutex::new(());
128+
129+
// Clean up environment variables set during tests
130+
#[allow(dead_code)]
131+
fn cleanup_env_vars() {
132+
env::remove_var("FLAKE");
133+
env::remove_var("NH_FLAKE");
134+
env::remove_var("NH_OS_FLAKE");
135+
env::remove_var("NH_HOME_FLAKE");
136+
env::remove_var("NH_DARWIN_FLAKE");
137+
}
138+
139+
#[test]
140+
fn test_setup_environment_no_flake_set() -> Result<()> {
141+
let _lock = ENV_LOCK.lock().unwrap();
142+
cleanup_env_vars();
143+
144+
let should_warn = setup_environment()?;
145+
assert!(!should_warn, "Should not warn when FLAKE is not set");
146+
assert!(env::var("NH_FLAKE").is_err(), "NH_FLAKE should not be set");
147+
148+
cleanup_env_vars();
149+
Ok(())
150+
}
151+
152+
#[test]
153+
fn test_setup_environment_flake_set_no_nh_flake_no_specifics() -> Result<()> {
154+
let _lock = ENV_LOCK.lock().unwrap();
155+
cleanup_env_vars();
156+
157+
env::set_var("FLAKE", "test_flake_path");
158+
let should_warn = setup_environment()?;
159+
160+
assert!(
161+
should_warn,
162+
"Should warn when FLAKE is set, NH_FLAKE is not, and no specific NH_*_FLAKE vars are set"
163+
);
164+
assert_eq!(
165+
env::var("NH_FLAKE").unwrap(),
166+
"test_flake_path",
167+
"NH_FLAKE should be set from FLAKE"
168+
);
169+
170+
cleanup_env_vars();
171+
Ok(())
172+
}
173+
174+
#[test]
175+
fn test_setup_environment_flake_set_nh_flake_already_set() -> Result<()> {
176+
let _lock = ENV_LOCK.lock().unwrap();
177+
cleanup_env_vars();
178+
179+
env::set_var("FLAKE", "test_flake_path");
180+
env::set_var("NH_FLAKE", "existing_nh_flake_path");
181+
let should_warn = setup_environment()?;
182+
183+
assert!(!should_warn, "Should not warn when NH_FLAKE is already set");
184+
assert_eq!(
185+
env::var("NH_FLAKE").unwrap(),
186+
"existing_nh_flake_path",
187+
"NH_FLAKE should retain its original value"
188+
);
189+
190+
cleanup_env_vars();
191+
Ok(())
192+
}
193+
194+
#[test]
195+
fn test_setup_environment_flake_set_no_nh_flake_nh_os_flake_set() -> Result<()> {
196+
let _lock = ENV_LOCK.lock().unwrap();
197+
cleanup_env_vars();
198+
199+
env::set_var("FLAKE", "test_flake_path");
200+
env::set_var("NH_OS_FLAKE", "os_specific_flake");
201+
let should_warn = setup_environment()?;
202+
203+
assert!(
204+
!should_warn,
205+
"Should not warn when FLAKE is set, NH_FLAKE is not, but NH_OS_FLAKE is set"
206+
);
207+
assert_eq!(
208+
env::var("NH_FLAKE").unwrap(),
209+
"test_flake_path",
210+
"NH_FLAKE should be set from FLAKE"
211+
);
212+
assert_eq!(
213+
env::var("NH_OS_FLAKE").unwrap(),
214+
"os_specific_flake",
215+
"NH_OS_FLAKE should remain set"
216+
);
217+
218+
cleanup_env_vars();
219+
Ok(())
220+
}
221+
222+
#[test]
223+
fn test_setup_environment_flake_set_no_nh_flake_nh_home_flake_set() -> Result<()> {
224+
let _lock = ENV_LOCK.lock().unwrap();
225+
cleanup_env_vars();
226+
227+
env::set_var("FLAKE", "test_flake_path");
228+
env::set_var("NH_HOME_FLAKE", "home_specific_flake");
229+
let should_warn = setup_environment()?;
230+
231+
assert!(
232+
!should_warn,
233+
"Should not warn when FLAKE is set, NH_FLAKE is not, but NH_HOME_FLAKE is set"
234+
);
235+
assert_eq!(
236+
env::var("NH_FLAKE").unwrap(),
237+
"test_flake_path",
238+
"NH_FLAKE should be set from FLAKE"
239+
);
240+
assert_eq!(
241+
env::var("NH_HOME_FLAKE").unwrap(),
242+
"home_specific_flake",
243+
"NH_HOME_FLAKE should remain set"
244+
);
245+
246+
cleanup_env_vars();
247+
Ok(())
248+
}
249+
250+
#[test]
251+
// Greatest function name ever.
252+
// testSetupEnvironmentFlakeSetNoNhFlakeNhDarwinFlakeSetAbstractFactoryBuilder
253+
fn test_setup_environment_flake_set_no_nh_flake_nh_darwin_flake_set() -> Result<()> {
254+
let _lock = ENV_LOCK.lock().unwrap();
255+
cleanup_env_vars();
256+
257+
env::set_var("FLAKE", "test_flake_path");
258+
env::set_var("NH_DARWIN_FLAKE", "darwin_specific_flake");
259+
let should_warn = setup_environment()?;
260+
261+
assert!(
262+
!should_warn,
263+
"Should not warn when FLAKE is set, NH_FLAKE is not, but NH_DARWIN_FLAKE is set"
264+
);
265+
assert_eq!(
266+
env::var("NH_FLAKE").unwrap(),
267+
"test_flake_path",
268+
"NH_FLAKE should be set from FLAKE"
269+
);
270+
assert_eq!(
271+
env::var("NH_DARWIN_FLAKE").unwrap(),
272+
"darwin_specific_flake",
273+
"NH_DARWIN_FLAKE should remain set"
274+
);
275+
276+
cleanup_env_vars(); // Clean up after test
277+
Ok(())
278+
}

0 commit comments

Comments
 (0)