Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
rbtcollins committed May 27, 2023
1 parent df41415 commit 230c766
Show file tree
Hide file tree
Showing 14 changed files with 892 additions and 853 deletions.
76 changes: 39 additions & 37 deletions src/cli/self_update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1291,46 +1291,48 @@ mod tests {

#[test]
async fn default_toolchain_is_stable() {
with_rustup_home(|home| async move {
let mut vars = HashMap::new();
home.apply(&mut vars);
let tp = Box::new(currentprocess::TestProcess {
vars,
..Default::default()
});
currentprocess::with_tokio(tp.clone(), async {
// TODO: we could pass in a custom cfg to get notification
// callbacks rather than output to the tp sink.
let mut cfg = common::set_globals(false, false).unwrap();
with_rustup_home(|home| {
Box::pin(async move {
let mut vars = HashMap::new();
home.apply(&mut vars);
let tp = Box::new(currentprocess::TestProcess {
vars,
..Default::default()
});
currentprocess::with_tokio(tp.clone(), async {
// TODO: we could pass in a custom cfg to get notification
// callbacks rather than output to the tp sink.
let mut cfg = common::set_globals(false, false).unwrap();
assert_eq!(
"stable"
.parse::<PartialToolchainDesc>()
.unwrap()
.resolve(&cfg.get_default_host_triple().unwrap())
.unwrap(),
super::_install_selection(
&mut cfg,
None, // No toolchain specified
"default", // default profile
None,
true,
&[],
&[],
)
.unwrap() // result
.unwrap() // option
);
Ok::<(), anyhow::Error>(())
})
.unwrap();
assert_eq!(
"stable"
.parse::<PartialToolchainDesc>()
.unwrap()
.resolve(&cfg.get_default_host_triple().unwrap())
.unwrap(),
super::_install_selection(
&mut cfg,
None, // No toolchain specified
"default", // default profile
None,
true,
&[],
&[],
)
.unwrap() // result
.unwrap() // option
);
Ok::<(), anyhow::Error>(())
})?;
assert_eq!(
for_host!(
r"info: profile set to 'default'
for_host!(
r"info: profile set to 'default'
info: default host triple is {0}
"
),
String::from_utf8(tp.get_stderr()).unwrap()
);
Ok(())
),
String::from_utf8(tp.get_stderr()).unwrap()
);
})
})
.await
.unwrap();
Expand Down
6 changes: 3 additions & 3 deletions src/cli/self_update/test.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Support for functional tests.
use std::sync::Mutex;
use std::{future::Future, pin::Pin, sync::Mutex};

#[cfg(not(unix))]
use winreg::{
Expand Down Expand Up @@ -35,7 +35,7 @@ fn restore_path(p: Option<RegValue>) {
}

/// Support testing of code that mutates global path state
pub fn with_saved_path(f: &mut dyn FnMut()) {
pub async fn with_saved_path(f: &dyn Fn() -> Pin<Box<dyn Future<Output = ()> + Send>>) {
// Lock protects concurrent mutation of registry
static LOCK: Mutex<()> = Mutex::new(());
let _g = LOCK.lock();
Expand All @@ -45,7 +45,7 @@ pub fn with_saved_path(f: &mut dyn FnMut()) {
let saved_path = get_path().expect("Error getting PATH: Better abort to avoid trashing it.");
let _g = scopeguard::guard(saved_path, restore_path);

f();
f().await;
}

#[cfg(unix)]
Expand Down
192 changes: 103 additions & 89 deletions src/cli/self_update/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -747,118 +747,132 @@ mod tests {
#[test]
async fn windows_path_regkey_type() {
// per issue #261, setting PATH should use REG_EXPAND_SZ.
let tp = Box::new(currentprocess::TestProcess::default());

with_saved_path(&mut || {
currentprocess::with_tokio(tp.clone(), async {
let root = RegKey::predef(HKEY_CURRENT_USER);
let environment = root
.open_subkey_with_flags("Environment", KEY_READ | KEY_WRITE)
.unwrap();
environment.delete_value("PATH").unwrap();

{
// Can't compare the Results as Eq isn't derived; thanks error-chain.
#![allow(clippy::unit_cmp)]
assert_eq!((), super::_apply_new_path(Some(wide("foo"))).unwrap());
}
let root = RegKey::predef(HKEY_CURRENT_USER);
let environment = root
.open_subkey_with_flags("Environment", KEY_READ | KEY_WRITE)
.unwrap();
let path = environment.get_raw_value("PATH").unwrap();
assert_eq!(path.vtype, RegType::REG_EXPAND_SZ);
assert_eq!(super::to_winreg_bytes(wide("foo")), &path.bytes[..]);
let tp = Box::new(currentprocess::TestProcess::default());
Box::pin(async move {
currentprocess::with_tokio(tp.clone(), async move {
let root = RegKey::predef(HKEY_CURRENT_USER);
let environment = root
.open_subkey_with_flags("Environment", KEY_READ | KEY_WRITE)
.unwrap();
environment.delete_value("PATH").unwrap();

{
// Can't compare the Results as Eq isn't derived; thanks error-chain.
#![allow(clippy::unit_cmp)]
assert_eq!((), super::_apply_new_path(Some(wide("foo"))).unwrap());
}
let root = RegKey::predef(HKEY_CURRENT_USER);
let environment = root
.open_subkey_with_flags("Environment", KEY_READ | KEY_WRITE)
.unwrap();
let path = environment.get_raw_value("PATH").unwrap();
assert_eq!(path.vtype, RegType::REG_EXPAND_SZ);
assert_eq!(super::to_winreg_bytes(wide("foo")), &path.bytes[..]);
})
})
});
})
.await;
}

#[test]
async fn windows_path_delete_key_when_empty() {
use std::io;
// during uninstall the PATH key may end up empty; if so we should
// delete it.
let tp = Box::new(currentprocess::TestProcess::default());
with_saved_path(&mut || {
currentprocess::with_tokio(tp.clone(), async {
let root = RegKey::predef(HKEY_CURRENT_USER);
let environment = root
.open_subkey_with_flags("Environment", KEY_READ | KEY_WRITE)
.unwrap();
environment
.set_raw_value(
"PATH",
&RegValue {
bytes: super::to_winreg_bytes(wide("foo")),
vtype: RegType::REG_EXPAND_SZ,
},
)
.unwrap();

{
// Can't compare the Results as Eq isn't derived; thanks error-chain.
#![allow(clippy::unit_cmp)]
assert_eq!((), super::_apply_new_path(Some(Vec::new())).unwrap());
}
let reg_value = environment.get_raw_value("PATH");
match reg_value {
Ok(_) => panic!("key not deleted"),
Err(ref e) if e.kind() == io::ErrorKind::NotFound => {}
Err(ref e) => panic!("error {e}"),
}
Box::pin(async move {
use std::io;
// during uninstall the PATH key may end up empty; if so we should
// delete it.
let tp = Box::new(currentprocess::TestProcess::default());

currentprocess::with_tokio(tp.clone(), async {
let root = RegKey::predef(HKEY_CURRENT_USER);
let environment = root
.open_subkey_with_flags("Environment", KEY_READ | KEY_WRITE)
.unwrap();
environment
.set_raw_value(
"PATH",
&RegValue {
bytes: super::to_winreg_bytes(wide("foo")),
vtype: RegType::REG_EXPAND_SZ,
},
)
.unwrap();

{
// Can't compare the Results as Eq isn't derived; thanks error-chain.
#![allow(clippy::unit_cmp)]
assert_eq!((), super::_apply_new_path(Some(Vec::new())).unwrap());
}
let reg_value = environment.get_raw_value("PATH");
match reg_value {
Ok(_) => panic!("key not deleted"),
Err(ref e) if e.kind() == io::ErrorKind::NotFound => {}
Err(ref e) => panic!("error {e}"),
}
})
})
});
})
.await;
}

#[test]
async fn windows_doesnt_mess_with_a_non_string_path() {
// This writes an error, so we want a sink for it.
let tp = Box::new(currentprocess::TestProcess {
vars: [("HOME".to_string(), "/unused".to_string())]
.iter()
.cloned()
.collect(),
..Default::default()
});
with_saved_path(&mut || {
currentprocess::with_tokio(tp.clone(), async {
let root = RegKey::predef(HKEY_CURRENT_USER);
let environment = root
.open_subkey_with_flags("Environment", KEY_READ | KEY_WRITE)
.unwrap();
let reg_value = RegValue {
bytes: vec![0x12, 0x34],
vtype: RegType::REG_BINARY,
};
environment.set_raw_value("PATH", &reg_value).unwrap();
// Ok(None) signals no change to the PATH setting layer
Box::pin(async move {
// This writes an error, so we want a sink for it.
let tp = Box::new(currentprocess::TestProcess {
vars: [("HOME".to_string(), "/unused".to_string())]
.iter()
.cloned()
.collect(),
..Default::default()
});

currentprocess::with_tokio(tp.clone(), async {
let root = RegKey::predef(HKEY_CURRENT_USER);
let environment = root
.open_subkey_with_flags("Environment", KEY_READ | KEY_WRITE)
.unwrap();
let reg_value = RegValue {
bytes: vec![0x12, 0x34],
vtype: RegType::REG_BINARY,
};
environment.set_raw_value("PATH", &reg_value).unwrap();
// Ok(None) signals no change to the PATH setting layer
assert_eq!(
None,
super::_with_path_cargo_home_bin(|_, _| panic!("called")).unwrap()
);
});
assert_eq!(
None,
super::_with_path_cargo_home_bin(|_, _| panic!("called")).unwrap()
r"warning: the registry key HKEY_CURRENT_USER\Environment\PATH is not a string. Not modifying the PATH variable
",
String::from_utf8(tp.get_stderr()).unwrap()
);
})
});
assert_eq!(
r"warning: the registry key HKEY_CURRENT_USER\Environment\PATH is not a string. Not modifying the PATH variable
",
String::from_utf8(tp.get_stderr()).unwrap()
);
}).await;
}

#[test]
async fn windows_treat_missing_path_as_empty() {
// during install the PATH key may be missing; treat it as empty
let tp = Box::new(currentprocess::TestProcess::default());
with_saved_path(&mut || {
currentprocess::with_tokio(tp.clone(), async {
let root = RegKey::predef(HKEY_CURRENT_USER);
let environment = root
.open_subkey_with_flags("Environment", KEY_READ | KEY_WRITE)
.unwrap();
environment.delete_value("PATH").unwrap();

assert_eq!(Some(Vec::new()), super::get_windows_path_var().unwrap());
Box::pin(async move {
let tp = Box::new(currentprocess::TestProcess::default());
currentprocess::with_tokio(tp.clone(), async {
let root = RegKey::predef(HKEY_CURRENT_USER);
let environment = root
.open_subkey_with_flags("Environment", KEY_READ | KEY_WRITE)
.unwrap();
environment.delete_value("PATH").unwrap();

assert_eq!(Some(Vec::new()), super::get_windows_path_var().unwrap());
})
})
});
})
.await;
}

#[test]
Expand Down
Loading

0 comments on commit 230c766

Please sign in to comment.