Skip to content

Commit 22dc71a

Browse files
authored
Merge pull request rust-lang#2416 from rbtcollins/unit-tests
More unit testifications
2 parents 7050161 + a8a9e86 commit 22dc71a

14 files changed

+513
-371
lines changed

Cargo.lock

+7
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+37-36
Original file line numberDiff line numberDiff line change
@@ -1,69 +1,70 @@
11
[package]
2-
name = "rustup"
3-
version = "1.22.1"
4-
authors = [ "Daniel Silverstone <[email protected]>", "Diggory Blake <[email protected]>" ]
2+
authors = ["Daniel Silverstone <[email protected]>", "Diggory Blake <[email protected]>"]
53
build = "build.rs"
4+
description = "Manage multiple rust installations with ease"
65
edition = "2018"
76
homepage = "https://github.com/rust-lang/rustup"
87
keywords = ["rustup", "multirust", "install", "proxy"]
98
license = "MIT OR Apache-2.0"
9+
name = "rustup"
1010
readme = "README.md"
1111
repository = "https://github.com/rust-lang/rustup"
12-
description = "Manage multiple rust installations with ease"
12+
version = "1.22.1"
1313

1414
[features]
15-
default = ["curl-backend", "reqwest-backend"]
1615
curl-backend = ["download/curl-backend"]
16+
default = ["curl-backend", "reqwest-backend"]
1717
reqwest-backend = ["download/reqwest-backend"]
1818
vendored-openssl = ['openssl/vendored']
1919
# Include in the default set to disable self-update and uninstall.
2020
no-self-update = []
2121

2222
# Sorted by alphabetic order
2323
[dependencies]
24+
anyhow = "1.0.31"
2425
cfg-if = "0.1"
2526
chrono = "0.4"
2627
clap = "2"
27-
download = { path = "download" }
28+
download = {path = "download"}
2829
error-chain = "0.12"
2930
flate2 = "1"
3031
git-testament = "0.1.4"
31-
home = { git = "https://github.com/rbtcollins/home", rev="a243ee2fbee6022c57d56f5aa79aefe194eabe53" }
32+
home = {git = "https://github.com/rbtcollins/home", rev = "a243ee2fbee6022c57d56f5aa79aefe194eabe53"}
3233
lazy_static = "1"
3334
libc = "0.2"
3435
num_cpus = "1.13"
3536
opener = "0.4.0"
3637
# Used by `curl` or `reqwest` backend although it isn't imported
3738
# by our rustup.
38-
openssl = { version = "0.10", optional = true }
39-
pulldown-cmark = { version = "0.7", default-features = false }
39+
openssl = {version = "0.10", optional = true}
40+
pulldown-cmark = {version = "0.7", default-features = false}
4041
rand = "0.7"
4142
regex = "1"
4243
remove_dir_all = "0.5.1"
4344
same-file = "1"
4445
scopeguard = "1"
4546
semver = "0.9"
46-
serde = { version = "1.0", features = ["derive"] }
47+
serde = {version = "1.0", features = ["derive"]}
4748
sha2 = "0.8"
4849
strsim = "0.10"
4950
tar = "0.4.26"
5051
tempfile = "3.1"
5152
# FIXME(issue #1788)
53+
pgp = {version = "0.5", default-features = false}
5254
term = "=0.5.1"
5355
threadpool = "1"
5456
toml = "0.5"
5557
url = "2.1"
5658
wait-timeout = "0.2"
5759
xz2 = "0.1.3"
58-
pgp = { version = "0.5", default-features = false}
5960

6061
[dependencies.retry]
61-
version = "1"
6262
default-features = false
63+
version = "1"
6364

6465
[dependencies.rs_tracing]
65-
version = "1.0.1"
6666
features = ["rs_tracing"]
67+
version = "1.0.1"
6768

6869
[target.'cfg(not(any(target_os="freebsd", target_os="netbsd")))'.dependencies]
6970
effective-limits = "0.5.1"
@@ -73,30 +74,30 @@ cc = "1"
7374
winreg = "0.6"
7475

7576
[target."cfg(windows)".dependencies.winapi]
76-
version = "0.3"
7777
features = [
78-
"combaseapi",
79-
"errhandlingapi",
80-
"fileapi",
81-
"handleapi",
82-
"ioapiset",
83-
"jobapi",
84-
"jobapi2",
85-
"minwindef",
86-
"processthreadsapi",
87-
"psapi",
88-
"shlobj",
89-
"shtypes",
90-
"synchapi",
91-
"sysinfoapi",
92-
"tlhelp32",
93-
"userenv",
94-
"winbase",
95-
"winerror",
96-
"winioctl",
97-
"winnt",
98-
"winuser",
78+
"combaseapi",
79+
"errhandlingapi",
80+
"fileapi",
81+
"handleapi",
82+
"ioapiset",
83+
"jobapi",
84+
"jobapi2",
85+
"minwindef",
86+
"processthreadsapi",
87+
"psapi",
88+
"shlobj",
89+
"shtypes",
90+
"synchapi",
91+
"sysinfoapi",
92+
"tlhelp32",
93+
"userenv",
94+
"winbase",
95+
"winerror",
96+
"winioctl",
97+
"winnt",
98+
"winuser",
9999
]
100+
version = "0.3"
100101

101102
[dev-dependencies]
102103
walkdir = "2"
@@ -109,8 +110,8 @@ name = "rustup"
109110
path = "src/lib.rs"
110111

111112
[profile.release]
112-
lto = true
113113
codegen-units = 1
114+
lto = true
114115

115116
# Reduce build time by setting proc-macro crates non optimized.
116117
[profile.release.build-override]

src/cli/self_update.rs

+100-19
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ use super::markdown::md;
4545
use super::term2;
4646
use crate::dist::dist::{self, Profile, TargetTriple};
4747
use crate::process;
48-
use crate::toolchain::DistributableToolchain;
48+
use crate::toolchain::{DistributableToolchain, Toolchain};
4949
use crate::utils::utils;
5050
use crate::utils::Notification;
5151
use crate::{Cfg, UpdateStatus};
@@ -721,6 +721,39 @@ fn maybe_install_rust(
721721
quiet: bool,
722722
) -> Result<()> {
723723
let mut cfg = common::set_globals(verbose, quiet)?;
724+
725+
let toolchain = _install_selection(
726+
&mut cfg,
727+
toolchain,
728+
profile_str,
729+
default_host_triple,
730+
update_existing_toolchain,
731+
components,
732+
targets,
733+
)?;
734+
if let Some(toolchain) = toolchain {
735+
if toolchain.exists() {
736+
warn!("Updating existing toolchain, profile choice will be ignored");
737+
}
738+
let distributable = DistributableToolchain::new(&toolchain)?;
739+
let status = distributable.install_from_dist(true, false, components, targets)?;
740+
let toolchain_str = toolchain.name().to_owned();
741+
toolchain.cfg().set_default(&toolchain_str)?;
742+
writeln!(process().stdout())?;
743+
common::show_channel_update(&toolchain.cfg(), &toolchain_str, Ok(status))?;
744+
}
745+
Ok(())
746+
}
747+
748+
fn _install_selection<'a>(
749+
cfg: &'a mut Cfg,
750+
toolchain_opt: Option<&str>,
751+
profile_str: &str,
752+
default_host_triple: Option<&str>,
753+
update_existing_toolchain: bool,
754+
components: &[&str],
755+
targets: &[&str],
756+
) -> Result<Option<Toolchain<'a>>> {
724757
cfg.set_profile(profile_str)?;
725758

726759
if let Some(default_host_triple) = default_host_triple {
@@ -731,7 +764,7 @@ fn maybe_install_rust(
731764
info!("default host triple is {}", cfg.get_default_host_triple()?);
732765
}
733766

734-
let user_specified_something = toolchain.is_some()
767+
let user_specified_something = toolchain_opt.is_some()
735768
|| !targets.is_empty()
736769
|| !components.is_empty()
737770
|| update_existing_toolchain;
@@ -741,7 +774,7 @@ fn maybe_install_rust(
741774
// a toolchain (updating if it's already present) and then if neither of
742775
// those are true, we have a user who doesn't mind, and already has an
743776
// install, so we leave their setup alone.
744-
if toolchain == Some("none") {
777+
Ok(if toolchain_opt == Some("none") {
745778
info!("skipping toolchain installation");
746779
if !components.is_empty() {
747780
warn!(
@@ -758,28 +791,20 @@ fn maybe_install_rust(
758791
);
759792
}
760793
writeln!(process().stdout())?;
794+
None
761795
} else if user_specified_something || cfg.find_default()?.is_none() {
762-
let (toolchain_str, toolchain) = match toolchain {
763-
Some(s) => (s.to_owned(), cfg.get_toolchain(s, false)?),
796+
Some(match toolchain_opt {
797+
Some(s) => cfg.get_toolchain(s, false)?,
764798
None => match cfg.find_default()? {
765-
Some(t) => (t.name().to_owned(), t),
766-
None => ("stable".to_owned(), cfg.get_toolchain("stable", false)?),
799+
Some(t) => t,
800+
None => cfg.get_toolchain("stable", false)?,
767801
},
768-
};
769-
if toolchain.exists() {
770-
warn!("Updating existing toolchain, profile choice will be ignored");
771-
}
772-
let distributable = DistributableToolchain::new(&toolchain)?;
773-
let status = distributable.install_from_dist(true, false, components, targets)?;
774-
cfg.set_default(&toolchain_str)?;
775-
writeln!(process().stdout())?;
776-
common::show_channel_update(&cfg, &toolchain_str, Ok(status))?;
802+
})
777803
} else {
778804
info!("updating existing rustup installation - leaving toolchains alone");
779805
writeln!(process().stdout())?;
780-
}
781-
782-
Ok(())
806+
None
807+
})
783808
}
784809

785810
pub fn uninstall(no_prompt: bool) -> Result<utils::ExitCode> {
@@ -1060,3 +1085,59 @@ pub fn cleanup_self_updater() -> Result<()> {
10601085

10611086
Ok(())
10621087
}
1088+
1089+
#[cfg(test)]
1090+
mod test {
1091+
use std::collections::HashMap;
1092+
1093+
use crate::cli::common;
1094+
use crate::dist::dist::ToolchainDesc;
1095+
use crate::test::with_rustup_home;
1096+
use crate::{currentprocess, for_host};
1097+
1098+
#[test]
1099+
fn default_toolchain_is_stable() {
1100+
with_rustup_home(|home| {
1101+
let mut vars = HashMap::new();
1102+
home.apply(&mut vars);
1103+
let tp = Box::new(currentprocess::TestProcess {
1104+
vars,
1105+
..Default::default()
1106+
});
1107+
currentprocess::with(tp.clone(), || -> anyhow::Result<()> {
1108+
// TODO: we could pass in a custom cfg to get notification
1109+
// callbacks rather than output to the tp sink.
1110+
let mut cfg = common::set_globals(false, false).unwrap();
1111+
assert_eq!(
1112+
"stable",
1113+
super::_install_selection(
1114+
&mut cfg,
1115+
None, // No toolchain specified
1116+
"default", // default profile
1117+
None,
1118+
false,
1119+
&[],
1120+
&[],
1121+
)
1122+
.unwrap() // result
1123+
.unwrap() // option
1124+
.name()
1125+
.parse::<ToolchainDesc>()
1126+
.unwrap()
1127+
.channel
1128+
);
1129+
Ok(())
1130+
})?;
1131+
assert_eq!(
1132+
for_host!(
1133+
r"info: profile set to 'default'
1134+
info: default host triple is {0}
1135+
"
1136+
),
1137+
&String::from_utf8(tp.get_stderr()).unwrap()
1138+
);
1139+
Ok(())
1140+
})
1141+
.unwrap();
1142+
}
1143+
}

src/cli/self_update/windows.rs

+51
Original file line numberDiff line numberDiff line change
@@ -537,6 +537,57 @@ mod tests {
537537
});
538538
}
539539

540+
#[test]
541+
fn windows_path_delete_key_when_empty() {
542+
use std::io;
543+
// during uninstall the PATH key may end up empty; if so we should
544+
// delete it.
545+
let tp = Box::new(currentprocess::TestProcess::default());
546+
with_registry_edits(&|| {
547+
currentprocess::with(tp.clone(), || {
548+
let root = RegKey::predef(HKEY_CURRENT_USER);
549+
let environment = root
550+
.open_subkey_with_flags("Environment", KEY_READ | KEY_WRITE)
551+
.unwrap();
552+
environment
553+
.set_raw_value(
554+
"PATH",
555+
&RegValue {
556+
bytes: utils::string_to_winreg_bytes("foo"),
557+
vtype: RegType::REG_EXPAND_SZ,
558+
},
559+
)
560+
.unwrap();
561+
562+
assert_eq!((), super::_apply_new_path(Some("".into())).unwrap());
563+
564+
let reg_value = environment.get_raw_value("PATH");
565+
match reg_value {
566+
Ok(_) => panic!("key not deleted"),
567+
Err(ref e) if e.kind() == io::ErrorKind::NotFound => {}
568+
Err(ref e) => panic!("error {}", e),
569+
}
570+
})
571+
});
572+
}
573+
574+
#[test]
575+
fn windows_treat_missing_path_as_empty() {
576+
// during install the PATH key may be missing; treat it as empty
577+
let tp = Box::new(currentprocess::TestProcess::default());
578+
with_registry_edits(&|| {
579+
currentprocess::with(tp.clone(), || {
580+
let root = RegKey::predef(HKEY_CURRENT_USER);
581+
let environment = root
582+
.open_subkey_with_flags("Environment", KEY_READ | KEY_WRITE)
583+
.unwrap();
584+
environment.delete_value("PATH").unwrap();
585+
586+
assert_eq!(Some("".into()), super::get_windows_path_var().unwrap());
587+
})
588+
});
589+
}
590+
540591
#[test]
541592
fn windows_uninstall_removes_semicolon_from_path_prefix() {
542593
assert_eq!(

src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -66,5 +66,6 @@ pub mod fallback_settings;
6666
mod install;
6767
mod notifications;
6868
pub mod settings;
69+
pub mod test;
6970
pub mod toolchain;
7071
pub mod utils;

0 commit comments

Comments
 (0)