Let `gix_testtools::Env` undo multiple changes to the same var
Showing the changes to tests (3 of 4 files). Show all
Unified · Split
| @@ -49,6 +49,9 @@ xz2 = { version = "0.1.6", optional = true } · 48 unmodified lines | ||
| 49 | 49 | |
| 50 | 50 | document-features = { version = "0.2.1", optional = true } |
| 51 | 51 | |
| 52 | +[dev-dependencies] | |
| 53 | +serial_test = { version = "3.1.0", default-features = false } | |
| 54 | + | |
| 52 | 55 | [package.metadata.docs.rs] |
| 53 | 56 | all-features = true |
| 54 | 57 | features = ["document-features"] |
| @@ -823,7 +823,7 @@ fn family_name() -> &'static str { · 822 unmodified lines | ||
| 823 | 823 | } |
| 824 | 824 | } |
| 825 | 825 | |
| 826 | −/// A utility to set environment variables, while unsetting them (or resetting them to their previous value) on drop. | |
| 826 | +/// A utility to set and unset environment variables, while restoring or removing them on drop. | |
| 827 | 827 | #[derive(Default)] |
| 828 | 828 | pub struct Env<'a> { |
| 829 | 829 | altered_vars: Vec<(&'a str, Option<OsString>)>, |
| @@ -845,7 +845,7 @@ impl<'a> Env<'a> { · 15 unmodified lines | ||
| 845 | 845 | self |
| 846 | 846 | } |
| 847 | 847 | |
| 848 | − /// Set `var` to `value`. | |
| 848 | + /// Unset `var`. | |
| 849 | 849 | pub fn unset(mut self, var: &'a str) -> Self { |
| 850 | 850 | let prev = std::env::var_os(var); |
| 851 | 851 | std::env::remove_var(var); |
| @@ -856,7 +856,7 @@ impl<'a> Env<'a> { · 4 unmodified lines | ||
| 856 | 856 | |
| 857 | 857 | impl<'a> Drop for Env<'a> { |
| 858 | 858 | fn drop(&mut self) { |
| 859 | − for (var, prev_value) in &self.altered_vars { | |
| 859 | + for (var, prev_value) in self.altered_vars.iter().rev() { | |
| 860 | 860 | match prev_value { |
| 861 | 861 | Some(value) => std::env::set_var(var, value), |
| 862 | 862 | None => std::env::remove_var(var), |
| @@ -0,0 +1,93 @@ | ||
| 1 | +use std::env; | |
| 2 | + | |
| 3 | +use gix_testtools::Env; | |
| 4 | +use serial_test::serial; | |
| 5 | + | |
| 6 | +// We rely on these not already existing, to test `Env` without using or rewriting it. | |
| 7 | +static VAR1: &str = "VAR_03FC4045_6043_4A61_9D15_852236CB632B"; | |
| 8 | +static VAR2: &str = "VAR_8C135840_05DB_4F3A_BFDD_FC755EC35B89"; | |
| 9 | +static VAR3: &str = "VAR_9B23A2BE_E20B_4670_93E2_3A6A8D47F274"; | |
| 10 | + | |
| 11 | +struct TestEnv; | |
| 12 | + | |
| 13 | +impl TestEnv { | |
| 14 | + fn new() -> Self { | |
| 15 | + assert_eq!(env::var_os(VAR1), None); | |
| 16 | + assert_eq!(env::var_os(VAR2), None); | |
| 17 | + assert_eq!(env::var_os(VAR3), None); | |
| 18 | + Self | |
| 19 | + } | |
| 20 | +} | |
| 21 | + | |
| 22 | +impl Drop for TestEnv { | |
| 23 | + fn drop(&mut self) { | |
| 24 | + env::remove_var(VAR1); | |
| 25 | + env::remove_var(VAR2); | |
| 26 | + env::remove_var(VAR3); | |
| 27 | + } | |
| 28 | +} | |
| 29 | + | |
| 30 | +#[test] | |
| 31 | +#[serial] | |
| 32 | +fn nonoverlapping() { | |
| 33 | + let _meta = TestEnv::new(); | |
| 34 | + env::set_var(VAR1, "old1"); | |
| 35 | + env::set_var(VAR2, "old2"); | |
| 36 | + { | |
| 37 | + let _env = Env::new().set(VAR1, "new1").unset(VAR2).set(VAR3, "new3"); | |
| 38 | + assert_eq!(env::var_os(VAR1), Some("new1".into())); | |
| 39 | + assert_eq!(env::var_os(VAR2), None); | |
| 40 | + assert_eq!(env::var_os(VAR3), Some("new3".into())); | |
| 41 | + } | |
| 42 | + assert_eq!(env::var_os(VAR1), Some("old1".into())); | |
| 43 | + assert_eq!(env::var_os(VAR2), Some("old2".into())); | |
| 44 | + assert_eq!(env::var_os(VAR3), None); | |
| 45 | +} | |
| 46 | + | |
| 47 | +#[test] | |
| 48 | +#[serial] | |
| 49 | +fn overlapping_reset() { | |
| 50 | + let _meta = TestEnv::new(); | |
| 51 | + { | |
| 52 | + let _env = Env::new().set(VAR1, "new1A").set(VAR1, "new1B"); | |
| 53 | + assert_eq!(env::var_os(VAR1), Some("new1B".into())); | |
| 54 | + } | |
| 55 | + assert_eq!(env::var_os(VAR1), None); | |
| 56 | +} | |
| 57 | + | |
| 58 | +#[test] | |
| 59 | +#[serial] | |
| 60 | +fn overlapping_unset() { | |
| 61 | + let _meta = TestEnv::new(); | |
| 62 | + env::set_var(VAR1, "old1"); | |
| 63 | + { | |
| 64 | + let _env = Env::new().unset(VAR1).unset(VAR1); | |
| 65 | + assert_eq!(env::var_os(VAR1), None); | |
| 66 | + } | |
| 67 | + assert_eq!(env::var_os(VAR1), Some("old1".into())); | |
| 68 | +} | |
| 69 | + | |
| 70 | +#[test] | |
| 71 | +#[serial] | |
| 72 | +fn overlapping_combo() { | |
| 73 | + let _meta = TestEnv::new(); | |
| 74 | + env::set_var(VAR1, "old1"); | |
| 75 | + env::set_var(VAR2, "old2"); | |
| 76 | + { | |
| 77 | + let _env = Env::new() | |
| 78 | + .set(VAR1, "new1A") | |
| 79 | + .unset(VAR2) | |
| 80 | + .set(VAR1, "new1B") | |
| 81 | + .unset(VAR3) | |
| 82 | + .set(VAR2, "new2") | |
| 83 | + .set(VAR3, "new3") | |
| 84 | + .unset(VAR1) | |
| 85 | + .unset(VAR3); | |
| 86 | + assert_eq!(env::var_os(VAR1), None); | |
| 87 | + assert_eq!(env::var_os(VAR2), Some("new2".into())); | |
| 88 | + assert_eq!(env::var_os(VAR3), None); | |
| 89 | + } | |
| 90 | + assert_eq!(env::var_os(VAR1), Some("old1".into())); | |
| 91 | + assert_eq!(env::var_os(VAR2), Some("old2".into())); | |
| 92 | + assert_eq!(env::var_os(VAR3), None); | |
| 93 | +} | |