Skip to content

Commit 5b11fdf

Browse files
committed
Convert unicode uninstall test to unit test
Added a mutex for registry editing unit tests as they will need to mutually exclude as the functional test suite does. For now I've copied the support functions; it is small and I've left a pointer.
1 parent 6d6e137 commit 5b11fdf

File tree

4 files changed

+88
-38
lines changed

4 files changed

+88
-38
lines changed

src/cli/self_update/windows.rs

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,89 @@ pub fn get_remove_path_methods() -> Result<Vec<PathUpdateMethod>> {
449449

450450
#[cfg(test)]
451451
mod tests {
452+
use std::sync::Mutex;
453+
454+
use lazy_static::lazy_static;
455+
use winreg::enums::{RegType, HKEY_CURRENT_USER, KEY_READ, KEY_WRITE};
456+
use winreg::{RegKey, RegValue};
457+
458+
use crate::currentprocess;
459+
use crate::utils::utils;
460+
461+
pub fn get_path() -> Option<String> {
462+
let root = RegKey::predef(HKEY_CURRENT_USER);
463+
let environment = root
464+
.open_subkey_with_flags("Environment", KEY_READ | KEY_WRITE)
465+
.unwrap();
466+
// XXX: copied from the mock support crate, but I am suspicous of this
467+
// code: This uses ok to allow signalling None for 'delete', but this
468+
// can fail e.g. with !(winerror::ERROR_BAD_FILE_TYPE) or other
469+
// failures; which will lead to attempting to delete the users path
470+
// rather than aborting the test suite.
471+
environment.get_value("PATH").ok()
472+
}
473+
474+
pub fn restore_path(p: Option<String>) {
475+
let root = RegKey::predef(HKEY_CURRENT_USER);
476+
let environment = root
477+
.open_subkey_with_flags("Environment", KEY_READ | KEY_WRITE)
478+
.unwrap();
479+
if let Some(p) = p.as_ref() {
480+
let reg_value = RegValue {
481+
bytes: utils::string_to_winreg_bytes(&p),
482+
vtype: RegType::REG_EXPAND_SZ,
483+
};
484+
environment.set_raw_value("PATH", &reg_value).unwrap();
485+
} else {
486+
let _ = environment.delete_value("PATH");
487+
}
488+
}
489+
490+
fn with_registry_edits(f: &dyn Fn()) {
491+
// Lock protects concurrent mutation of registry
492+
lazy_static! {
493+
static ref LOCK: Mutex<()> = Mutex::new(());
494+
}
495+
let _g = LOCK.lock();
496+
497+
// On windows these tests mess with the user's PATH. Save
498+
// and restore them here to keep from trashing things.
499+
let saved_path = get_path();
500+
let _g = scopeguard::guard(saved_path, restore_path);
501+
502+
f();
503+
}
504+
505+
#[test]
506+
fn windows_uninstall_doesnt_mess_with_a_non_unicode_path() {
507+
// This writes an error, so we want a sink for it.
508+
let tp = Box::new(currentprocess::TestProcess::default());
509+
with_registry_edits(&|| {
510+
currentprocess::with(tp.clone(), || {
511+
let root = RegKey::predef(HKEY_CURRENT_USER);
512+
let environment = root
513+
.open_subkey_with_flags("Environment", KEY_READ | KEY_WRITE)
514+
.unwrap();
515+
let reg_value = RegValue {
516+
bytes: vec![
517+
0x00, 0xD8, // leading surrogate
518+
0x01, 0x01, // bogus trailing surrogate
519+
0x00, 0x00,
520+
], // null
521+
vtype: RegType::REG_EXPAND_SZ,
522+
};
523+
environment.set_raw_value("PATH", &reg_value).unwrap();
524+
// Ok(None) signals no change to the PATH setting layer
525+
assert_eq!(None, super::_path_without_cargo_home_bin().unwrap());
526+
})
527+
});
528+
assert_eq!(
529+
r"warning: the registry key HKEY_CURRENT_USER\Environment\PATH does not contain valid Unicode. Not modifying the PATH variable
530+
",
531+
String::from_utf8(tp.get_stderr()).unwrap()
532+
);
533+
}
534+
452535
#[test]
453536
fn windows_uninstall_removes_semicolon_from_path_prefix() {
454537
assert_eq!(

src/currentprocess.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ impl ProcessSource for OSProcess {
160160

161161
// ------------ test process ----------------
162162

163-
#[derive(Clone, Debug)]
163+
#[derive(Clone, Debug, Default)]
164164
pub struct TestProcess {
165165
cwd: PathBuf,
166166
args: Vec<String>,

tests/cli-self-upd.rs

Lines changed: 0 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1126,43 +1126,6 @@ fn install_doesnt_mess_with_a_non_unicode_path() {
11261126
});
11271127
}
11281128

1129-
#[test]
1130-
#[cfg(windows)]
1131-
fn uninstall_doesnt_mess_with_a_non_unicode_path() {
1132-
use winreg::enums::{RegType, HKEY_CURRENT_USER, KEY_READ, KEY_WRITE};
1133-
use winreg::{RegKey, RegValue};
1134-
1135-
setup(&|config| {
1136-
expect_ok(config, &["rustup-init", "-y"]);
1137-
1138-
let root = RegKey::predef(HKEY_CURRENT_USER);
1139-
let environment = root
1140-
.open_subkey_with_flags("Environment", KEY_READ | KEY_WRITE)
1141-
.unwrap();
1142-
1143-
let reg_value = RegValue {
1144-
bytes: vec![
1145-
0x00, 0xD8, // leading surrogate
1146-
0x01, 0x01, // bogus trailing surrogate
1147-
0x00, 0x00,
1148-
], // null
1149-
vtype: RegType::REG_EXPAND_SZ,
1150-
};
1151-
environment.set_raw_value("PATH", &reg_value).unwrap();
1152-
1153-
expect_stderr_ok(config, &["rustup", "self", "uninstall", "-y"],
1154-
"the registry key HKEY_CURRENT_USER\\Environment\\PATH does not contain valid Unicode. \
1155-
Not modifying the PATH variable");
1156-
1157-
let root = RegKey::predef(HKEY_CURRENT_USER);
1158-
let environment = root
1159-
.open_subkey_with_flags("Environment", KEY_READ | KEY_WRITE)
1160-
.unwrap();
1161-
let path = environment.get_raw_value("PATH").unwrap();
1162-
assert!(path.bytes == reg_value.bytes);
1163-
});
1164-
}
1165-
11661129
#[test]
11671130
#[ignore] // untestable
11681131
fn install_but_rustup_is_installed() {}

tests/mock/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,10 @@ pub fn get_path() -> Option<String> {
180180
.open_subkey_with_flags("Environment", KEY_READ | KEY_WRITE)
181181
.unwrap();
182182

183+
// XXX: Suspect code: This uses ok to allow signalling None for 'delete', but this
184+
// can fail e.g. with !(winerror::ERROR_BAD_FILE_TYPE) or other
185+
// failures; which would lead to attempting to delete the users path
186+
// rather than aborting the test suite.
183187
environment.get_value("PATH").ok()
184188
}
185189

0 commit comments

Comments
 (0)