Skip to content

Commit b035369

Browse files
committed
Test cleanup of rustup-init functional tests
Run all rustup-init tests that can in parallel. Use common helpers where possible. Move some tests to more relevant modules. Fixes test path leakages on Windows I think.
1 parent 4d7c0e5 commit b035369

File tree

11 files changed

+443
-501
lines changed

11 files changed

+443
-501
lines changed

src/cli/self_update.rs

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,20 @@
3030
//! Deleting the running binary during uninstall is tricky
3131
//! and racy on Windows.
3232
33+
#[cfg(unix)]
34+
mod shell;
35+
pub mod test;
36+
#[cfg(unix)]
37+
mod unix;
38+
#[cfg(windows)]
39+
mod windows;
40+
mod os {
41+
#[cfg(unix)]
42+
pub use super::unix::*;
43+
#[cfg(windows)]
44+
pub use super::windows::*;
45+
}
46+
3347
use std::borrow::Cow;
3448
use std::env;
3549
use std::env::consts::EXE_SUFFIX;
@@ -50,19 +64,6 @@ use crate::utils::utils;
5064
use crate::utils::Notification;
5165
use crate::{Cfg, UpdateStatus};
5266
use crate::{DUP_TOOLS, TOOLS};
53-
54-
#[cfg(unix)]
55-
mod shell;
56-
#[cfg(unix)]
57-
mod unix;
58-
#[cfg(windows)]
59-
mod windows;
60-
mod os {
61-
#[cfg(unix)]
62-
pub use super::unix::*;
63-
#[cfg(windows)]
64-
pub use super::windows::*;
65-
}
6667
use os::*;
6768
pub use os::{complete_windows_uninstall, delete_rustup_and_cargo_home, run_update, self_replace};
6869

@@ -1078,7 +1079,7 @@ pub fn cleanup_self_updater() -> Result<()> {
10781079
}
10791080

10801081
#[cfg(test)]
1081-
mod test {
1082+
mod tests {
10821083
use std::collections::HashMap;
10831084

10841085
use crate::cli::common;

src/cli/self_update/test.rs

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
//! Support for functional tests.
2+
3+
use std::sync::Mutex;
4+
5+
use lazy_static::lazy_static;
6+
#[cfg(not(unix))]
7+
use winreg::{
8+
enums::{RegType, HKEY_CURRENT_USER, KEY_READ, KEY_WRITE},
9+
RegKey, RegValue,
10+
};
11+
12+
#[cfg(not(unix))]
13+
use crate::utils::utils;
14+
15+
#[cfg(not(unix))]
16+
pub fn get_path() -> Option<String> {
17+
let root = RegKey::predef(HKEY_CURRENT_USER);
18+
let environment = root
19+
.open_subkey_with_flags("Environment", KEY_READ | KEY_WRITE)
20+
.unwrap();
21+
// XXX: copied from the mock support crate, but I am suspicous of this
22+
// code: This uses ok to allow signalling None for 'delete', but this
23+
// can fail e.g. with !(winerror::ERROR_BAD_FILE_TYPE) or other
24+
// failures; which will lead to attempting to delete the users path
25+
// rather than aborting the test suite.
26+
environment.get_value("PATH").ok()
27+
}
28+
29+
#[cfg(not(unix))]
30+
fn restore_path(p: Option<String>) {
31+
let root = RegKey::predef(HKEY_CURRENT_USER);
32+
let environment = root
33+
.open_subkey_with_flags("Environment", KEY_READ | KEY_WRITE)
34+
.unwrap();
35+
if let Some(p) = p.as_ref() {
36+
let reg_value = RegValue {
37+
bytes: utils::string_to_winreg_bytes(&p),
38+
vtype: RegType::REG_EXPAND_SZ,
39+
};
40+
environment.set_raw_value("PATH", &reg_value).unwrap();
41+
} else {
42+
let _ = environment.delete_value("PATH");
43+
}
44+
}
45+
46+
/// Support testing of code that mutates global path state
47+
pub fn with_saved_path(f: &dyn Fn()) {
48+
// Lock protects concurrent mutation of registry
49+
lazy_static! {
50+
static ref LOCK: Mutex<()> = Mutex::new(());
51+
}
52+
let _g = LOCK.lock();
53+
54+
// On windows these tests mess with the user's PATH. Save
55+
// and restore them here to keep from trashing things.
56+
let saved_path = get_path();
57+
let _g = scopeguard::guard(saved_path, restore_path);
58+
59+
f();
60+
}
61+
62+
#[cfg(unix)]
63+
pub fn get_path() -> Option<String> {
64+
None
65+
}
66+
67+
#[cfg(unix)]
68+
fn restore_path(_: Option<String>) {}

src/cli/self_update/windows.rs

Lines changed: 5 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -394,59 +394,13 @@ pub fn delete_rustup_and_cargo_home() -> Result<()> {
394394

395395
#[cfg(test)]
396396
mod tests {
397-
use std::sync::Mutex;
398-
399-
use lazy_static::lazy_static;
400397
use winreg::enums::{RegType, HKEY_CURRENT_USER, KEY_READ, KEY_WRITE};
401398
use winreg::{RegKey, RegValue};
402399

403400
use crate::currentprocess;
401+
use crate::test::with_saved_path;
404402
use crate::utils::utils;
405403

406-
pub fn get_path() -> Option<String> {
407-
let root = RegKey::predef(HKEY_CURRENT_USER);
408-
let environment = root
409-
.open_subkey_with_flags("Environment", KEY_READ | KEY_WRITE)
410-
.unwrap();
411-
// XXX: copied from the mock support crate, but I am suspicous of this
412-
// code: This uses ok to allow signalling None for 'delete', but this
413-
// can fail e.g. with !(winerror::ERROR_BAD_FILE_TYPE) or other
414-
// failures; which will lead to attempting to delete the users path
415-
// rather than aborting the test suite.
416-
environment.get_value("PATH").ok()
417-
}
418-
419-
pub fn restore_path(p: Option<String>) {
420-
let root = RegKey::predef(HKEY_CURRENT_USER);
421-
let environment = root
422-
.open_subkey_with_flags("Environment", KEY_READ | KEY_WRITE)
423-
.unwrap();
424-
if let Some(p) = p.as_ref() {
425-
let reg_value = RegValue {
426-
bytes: utils::string_to_winreg_bytes(&p),
427-
vtype: RegType::REG_EXPAND_SZ,
428-
};
429-
environment.set_raw_value("PATH", &reg_value).unwrap();
430-
} else {
431-
let _ = environment.delete_value("PATH");
432-
}
433-
}
434-
435-
fn with_registry_edits(f: &dyn Fn()) {
436-
// Lock protects concurrent mutation of registry
437-
lazy_static! {
438-
static ref LOCK: Mutex<()> = Mutex::new(());
439-
}
440-
let _g = LOCK.lock();
441-
442-
// On windows these tests mess with the user's PATH. Save
443-
// and restore them here to keep from trashing things.
444-
let saved_path = get_path();
445-
let _g = scopeguard::guard(saved_path, restore_path);
446-
447-
f();
448-
}
449-
450404
#[test]
451405
fn windows_install_does_not_add_path_twice() {
452406
assert_eq!(
@@ -468,7 +422,7 @@ mod tests {
468422
.collect(),
469423
..Default::default()
470424
});
471-
with_registry_edits(&|| {
425+
with_saved_path(&|| {
472426
currentprocess::with(tp.clone(), || {
473427
let root = RegKey::predef(HKEY_CURRENT_USER);
474428
let environment = root
@@ -501,7 +455,7 @@ mod tests {
501455
fn windows_path_regkey_type() {
502456
// per issue #261, setting PATH should use REG_EXPAND_SZ.
503457
let tp = Box::new(currentprocess::TestProcess::default());
504-
with_registry_edits(&|| {
458+
with_saved_path(&|| {
505459
currentprocess::with(tp.clone(), || {
506460
let root = RegKey::predef(HKEY_CURRENT_USER);
507461
let environment = root
@@ -528,7 +482,7 @@ mod tests {
528482
// during uninstall the PATH key may end up empty; if so we should
529483
// delete it.
530484
let tp = Box::new(currentprocess::TestProcess::default());
531-
with_registry_edits(&|| {
485+
with_saved_path(&|| {
532486
currentprocess::with(tp.clone(), || {
533487
let root = RegKey::predef(HKEY_CURRENT_USER);
534488
let environment = root
@@ -560,7 +514,7 @@ mod tests {
560514
fn windows_treat_missing_path_as_empty() {
561515
// during install the PATH key may be missing; treat it as empty
562516
let tp = Box::new(currentprocess::TestProcess::default());
563-
with_registry_edits(&|| {
517+
with_saved_path(&|| {
564518
currentprocess::with(tp.clone(), || {
565519
let root = RegKey::predef(HKEY_CURRENT_USER);
566520
let environment = root

src/test.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use std::io;
88
use std::path::{Path, PathBuf};
99
use std::process::Command;
1010

11+
pub use crate::cli::self_update::test::{get_path, with_saved_path};
1112
use crate::currentprocess;
1213
use crate::dist::dist::TargetTriple;
1314

tests/cli-exact.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ fn setup(f: &dyn Fn(&mut Config)) {
1515
}
1616

1717
#[test]
18-
fn update() {
18+
fn update_once() {
1919
setup(&|config| {
2020
expect_ok_ex(
2121
config,

0 commit comments

Comments
 (0)