4175 lines
105 KiB
Rust
4175 lines
105 KiB
Rust
//! Test cases for new rustup UI
|
||
|
||
use std::{
|
||
env::consts::EXE_SUFFIX,
|
||
fs,
|
||
path::{Path, PathBuf},
|
||
};
|
||
|
||
use rustup::{
|
||
for_host,
|
||
test::{
|
||
CROSS_ARCH1, CROSS_ARCH2, CliTestContext, MULTI_ARCH1, Scenario, this_host_tuple,
|
||
topical_doc_data,
|
||
},
|
||
utils::raw,
|
||
};
|
||
|
||
#[tokio::test]
|
||
async fn rustup_stable() {
|
||
let mut cx = CliTestContext::new(Scenario::None).await;
|
||
|
||
{
|
||
let cx = cx.with_dist_dir(Scenario::ArchivesV2_2015_01_01);
|
||
cx.config
|
||
.expect(["rustup", "toolchain", "add", "stable"])
|
||
.await
|
||
.is_ok();
|
||
}
|
||
|
||
let cx = cx.with_dist_dir(Scenario::SimpleV2);
|
||
cx.config
|
||
.expect(["rustup", "update"])
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
|
||
stable-[HOST_TUPLE] updated - 1.1.0 (hash-stable-1.1.0) (from 1.0.0 (hash-stable-1.0.0))
|
||
|
||
|
||
"#]])
|
||
.with_stderr(snapbox::str![[r#"
|
||
info: syncing channel updates for stable-[HOST_TUPLE]
|
||
info: latest update on 2015-01-02 for version 1.1.0 (hash-stable-1.1.0)
|
||
info: removing previous version of component cargo
|
||
...
|
||
info: cleaning up downloads & tmp directories
|
||
|
||
"#]])
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "component", "list", "--installed"])
|
||
.await
|
||
.is_ok()
|
||
.with_stdout(snapbox::str![[r#"
|
||
cargo-[HOST_TUPLE]
|
||
rust-docs-[HOST_TUPLE]
|
||
rust-std-[HOST_TUPLE]
|
||
rustc-[HOST_TUPLE]
|
||
|
||
"#]]);
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn rustup_stable_quiet() {
|
||
let mut cx = CliTestContext::new(Scenario::None).await;
|
||
|
||
{
|
||
let cx = cx.with_dist_dir(Scenario::ArchivesV2_2015_01_01);
|
||
cx.config
|
||
.expect(["rustup", "--quiet", "update", "stable"])
|
||
.await
|
||
.is_ok();
|
||
}
|
||
|
||
let cx = cx.with_dist_dir(Scenario::SimpleV2);
|
||
cx.config
|
||
.expect(["rustup", "--quiet", "update"])
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
|
||
stable-[HOST_TUPLE] updated - 1.1.0 (hash-stable-1.1.0) (from 1.0.0 (hash-stable-1.0.0))
|
||
|
||
|
||
"#]])
|
||
.with_stderr(snapbox::str![[""]])
|
||
.is_ok();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn rustup_stable_no_change() {
|
||
let cx = CliTestContext::new(Scenario::ArchivesV2_2015_01_01).await;
|
||
cx.config
|
||
.expect(["rustup", "update", "stable"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "update"])
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
|
||
stable-[HOST_TUPLE] unchanged - 1.0.0 (hash-stable-1.0.0)
|
||
|
||
|
||
"#]])
|
||
.with_stderr(snapbox::str![[r#"
|
||
info: cleaning up downloads & tmp directories
|
||
|
||
"#]])
|
||
.is_ok();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn rustup_all_channels() {
|
||
let mut cx = CliTestContext::new(Scenario::None).await;
|
||
|
||
{
|
||
let cx = cx.with_dist_dir(Scenario::ArchivesV2_2015_01_01);
|
||
cx.config
|
||
.expect(["rustup", "toolchain", "add", "stable", "beta", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
}
|
||
|
||
let cx = cx.with_dist_dir(Scenario::SimpleV2);
|
||
cx.config
|
||
.expect(["rustup", "update"])
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
|
||
stable-[HOST_TUPLE] updated - 1.1.0 (hash-stable-1.1.0) (from 1.0.0 (hash-stable-1.0.0))
|
||
beta-[HOST_TUPLE] updated - 1.2.0 (hash-beta-1.2.0) (from 1.1.0 (hash-beta-1.1.0))
|
||
nightly-[HOST_TUPLE] updated - 1.3.0 (hash-nightly-2) (from 1.2.0 (hash-nightly-1))
|
||
|
||
|
||
"#]])
|
||
.with_stderr(snapbox::str![[r#"
|
||
info: syncing channel updates for stable-[HOST_TUPLE]
|
||
info: latest update on 2015-01-02 for version 1.1.0 (hash-stable-1.1.0)
|
||
info: removing previous version of component cargo
|
||
...
|
||
info: syncing channel updates for beta-[HOST_TUPLE]
|
||
info: latest update on 2015-01-02 for version 1.2.0 (hash-beta-1.2.0)
|
||
info: removing previous version of component cargo
|
||
...
|
||
info: syncing channel updates for nightly-[HOST_TUPLE]
|
||
info: latest update on 2015-01-02 for version 1.3.0 (hash-nightly-2)
|
||
info: removing previous version of component cargo
|
||
...
|
||
info: cleaning up downloads & tmp directories
|
||
|
||
"#]])
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "+stable", "component", "list", "--installed"])
|
||
.await
|
||
.is_ok()
|
||
.with_stdout(snapbox::str![[r#"
|
||
cargo-[HOST_TUPLE]
|
||
rust-docs-[HOST_TUPLE]
|
||
rust-std-[HOST_TUPLE]
|
||
rustc-[HOST_TUPLE]
|
||
|
||
"#]]);
|
||
cx.config
|
||
.expect(["rustup", "+beta", "component", "list", "--installed"])
|
||
.await
|
||
.is_ok()
|
||
.with_stdout(snapbox::str![[r#"
|
||
cargo-[HOST_TUPLE]
|
||
rust-docs-[HOST_TUPLE]
|
||
rust-std-[HOST_TUPLE]
|
||
rustc-[HOST_TUPLE]
|
||
|
||
"#]]);
|
||
cx.config
|
||
.expect(["rustup", "+nightly", "component", "list", "--installed"])
|
||
.await
|
||
.is_ok()
|
||
.with_stdout(snapbox::str![[r#"
|
||
cargo-[HOST_TUPLE]
|
||
rust-docs-[HOST_TUPLE]
|
||
rust-std-[HOST_TUPLE]
|
||
rustc-[HOST_TUPLE]
|
||
|
||
"#]]);
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn rustup_some_channels_up_to_date() {
|
||
let mut cx = CliTestContext::new(Scenario::None).await;
|
||
|
||
{
|
||
let cx = cx.with_dist_dir(Scenario::ArchivesV2_2015_01_01);
|
||
cx.config
|
||
.expect(["rustup", "toolchain", "add", "stable", "beta", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
}
|
||
|
||
let cx = cx.with_dist_dir(Scenario::SimpleV2);
|
||
cx.config.expect(["rustup", "update", "beta"]).await.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "update"])
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
|
||
stable-[HOST_TUPLE] updated - 1.1.0 (hash-stable-1.1.0) (from 1.0.0 (hash-stable-1.0.0))
|
||
beta-[HOST_TUPLE] unchanged - 1.2.0 (hash-beta-1.2.0)
|
||
nightly-[HOST_TUPLE] updated - 1.3.0 (hash-nightly-2) (from 1.2.0 (hash-nightly-1))
|
||
|
||
|
||
"#]])
|
||
.with_stderr(snapbox::str![[r#"
|
||
info: syncing channel updates for stable-[HOST_TUPLE]
|
||
info: latest update on 2015-01-02 for version 1.1.0 (hash-stable-1.1.0)
|
||
info: removing previous version of component cargo
|
||
...
|
||
info: syncing channel updates for nightly-[HOST_TUPLE]
|
||
info: latest update on 2015-01-02 for version 1.3.0 (hash-nightly-2)
|
||
info: removing previous version of component cargo
|
||
...
|
||
info: cleaning up downloads & tmp directories
|
||
|
||
"#]])
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "+stable", "component", "list", "--installed"])
|
||
.await
|
||
.is_ok()
|
||
.with_stdout(snapbox::str![[r#"
|
||
cargo-[HOST_TUPLE]
|
||
rust-docs-[HOST_TUPLE]
|
||
rust-std-[HOST_TUPLE]
|
||
rustc-[HOST_TUPLE]
|
||
|
||
"#]]);
|
||
cx.config
|
||
.expect(["rustup", "+beta", "component", "list", "--installed"])
|
||
.await
|
||
.is_ok()
|
||
.with_stdout(snapbox::str![[r#"
|
||
cargo-[HOST_TUPLE]
|
||
rust-docs-[HOST_TUPLE]
|
||
rust-std-[HOST_TUPLE]
|
||
rustc-[HOST_TUPLE]
|
||
|
||
"#]]);
|
||
cx.config
|
||
.expect(["rustup", "+nightly", "component", "list", "--installed"])
|
||
.await
|
||
.is_ok()
|
||
.with_stdout(snapbox::str![[r#"
|
||
cargo-[HOST_TUPLE]
|
||
rust-docs-[HOST_TUPLE]
|
||
rust-std-[HOST_TUPLE]
|
||
rustc-[HOST_TUPLE]
|
||
|
||
"#]]);
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn rustup_no_channels() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(["rustup", "update"])
|
||
.await
|
||
.with_stdout(snapbox::str![""])
|
||
.with_stderr(snapbox::str![[r#"
|
||
info: no updatable toolchains installed
|
||
info: cleaning up downloads & tmp directories
|
||
|
||
"#]])
|
||
.is_ok();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn default() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(["rustup", "default", "nightly"])
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
|
||
nightly-[HOST_TUPLE] installed - 1.3.0 (hash-nightly-2)
|
||
|
||
|
||
"#]])
|
||
.with_stderr(snapbox::str![[r#"
|
||
info: syncing channel updates for nightly-[HOST_TUPLE]
|
||
info: latest update on 2015-01-02 for version 1.3.0 (hash-nightly-2)
|
||
info: downloading 4 components
|
||
info: default toolchain set to nightly-[HOST_TUPLE]
|
||
|
||
"#]])
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "+nightly", "component", "list", "--installed"])
|
||
.await
|
||
.is_ok()
|
||
.with_stdout(snapbox::str![[r#"
|
||
cargo-[HOST_TUPLE]
|
||
rust-docs-[HOST_TUPLE]
|
||
rust-std-[HOST_TUPLE]
|
||
rustc-[HOST_TUPLE]
|
||
|
||
"#]]);
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn default_override() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(["rustup", "toolchain", "add", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "default", "stable"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "override", "set", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "default", "stable"])
|
||
.await
|
||
.with_stderr(snapbox::str![[r#"
|
||
info: using existing install for stable-[HOST_TUPLE]
|
||
info: default toolchain set to stable-[HOST_TUPLE]
|
||
info: note that the toolchain 'nightly-[HOST_TUPLE]' is currently in use (directory override for '[..]')
|
||
|
||
"#]])
|
||
.is_ok();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn rustup_zstd() {
|
||
let cx = CliTestContext::new(Scenario::ArchivesV2_2015_01_01).await;
|
||
cx.config
|
||
.expect(["rustup", "--verbose", "toolchain", "add", "nightly"])
|
||
.await
|
||
.with_stderr(snapbox::str![[r#"
|
||
...
|
||
[..]dist/2015-01-01/rust-std-nightly-[HOST_TUPLE].tar.zst[..]
|
||
...
|
||
"#]])
|
||
.is_ok();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn add_target() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
let path = format!(
|
||
"toolchains/nightly-{}/lib/rustlib/{}/lib/libstd.rlib",
|
||
&this_host_tuple(),
|
||
CROSS_ARCH1
|
||
);
|
||
cx.config
|
||
.expect(["rustup", "default", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "target", "add", CROSS_ARCH1])
|
||
.await
|
||
.is_ok();
|
||
assert!(cx.config.rustupdir.has(path));
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn remove_target() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
let path = format!(
|
||
"toolchains/nightly-{}/lib/rustlib/{}/lib/libstd.rlib",
|
||
&this_host_tuple(),
|
||
CROSS_ARCH1
|
||
);
|
||
cx.config
|
||
.expect(["rustup", "default", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "target", "add", CROSS_ARCH1])
|
||
.await
|
||
.is_ok();
|
||
assert!(cx.config.rustupdir.has(&path));
|
||
cx.config
|
||
.expect(["rustup", "target", "remove", CROSS_ARCH1])
|
||
.await
|
||
.is_ok();
|
||
assert!(!cx.config.rustupdir.has(&path));
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn add_remove_multiple_targets() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(["rustup", "default", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "target", "add", CROSS_ARCH1, CROSS_ARCH2])
|
||
.await
|
||
.is_ok();
|
||
let path = format!(
|
||
"toolchains/nightly-{}/lib/rustlib/{}/lib/libstd.rlib",
|
||
&this_host_tuple(),
|
||
CROSS_ARCH1
|
||
);
|
||
assert!(cx.config.rustupdir.has(path));
|
||
let path = format!(
|
||
"toolchains/nightly-{}/lib/rustlib/{}/lib/libstd.rlib",
|
||
&this_host_tuple(),
|
||
CROSS_ARCH2
|
||
);
|
||
assert!(cx.config.rustupdir.has(path));
|
||
|
||
cx.config
|
||
.expect(["rustup", "target", "remove", CROSS_ARCH1, CROSS_ARCH2])
|
||
.await
|
||
.is_ok();
|
||
let path = format!(
|
||
"toolchains/nightly-{}/lib/rustlib/{}/lib/libstd.rlib",
|
||
&this_host_tuple(),
|
||
CROSS_ARCH1
|
||
);
|
||
assert!(!cx.config.rustupdir.has(path));
|
||
let path = format!(
|
||
"toolchains/nightly-{}/lib/rustlib/{}/lib/libstd.rlib",
|
||
&this_host_tuple(),
|
||
CROSS_ARCH2
|
||
);
|
||
assert!(!cx.config.rustupdir.has(path));
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn list_targets() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(["rustup", "default", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "target", "list"])
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
...
|
||
[CROSS_ARCH_I]
|
||
...
|
||
"#]])
|
||
.is_ok();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn list_installed_targets() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
|
||
cx.config
|
||
.expect(["rustup", "default", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "target", "list", "--installed"])
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
[HOST_TUPLE]
|
||
|
||
"#]])
|
||
.is_ok();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn add_target_explicit() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
let path = format!(
|
||
"toolchains/nightly-{}/lib/rustlib/{}/lib/libstd.rlib",
|
||
&this_host_tuple(),
|
||
CROSS_ARCH1
|
||
);
|
||
cx.config
|
||
.expect(["rustup", "toolchain", "add", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect([
|
||
"rustup",
|
||
"target",
|
||
"add",
|
||
"--toolchain",
|
||
"nightly",
|
||
CROSS_ARCH1,
|
||
])
|
||
.await
|
||
.is_ok();
|
||
assert!(cx.config.rustupdir.has(path));
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn remove_target_explicit() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
let path = format!(
|
||
"toolchains/nightly-{}/lib/rustlib/{}/lib/libstd.rlib",
|
||
&this_host_tuple(),
|
||
CROSS_ARCH1
|
||
);
|
||
cx.config
|
||
.expect(["rustup", "toolchain", "add", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect([
|
||
"rustup",
|
||
"target",
|
||
"add",
|
||
"--toolchain",
|
||
"nightly",
|
||
CROSS_ARCH1,
|
||
])
|
||
.await
|
||
.is_ok();
|
||
assert!(cx.config.rustupdir.has(&path));
|
||
cx.config
|
||
.expect([
|
||
"rustup",
|
||
"target",
|
||
"remove",
|
||
"--toolchain",
|
||
"nightly",
|
||
CROSS_ARCH1,
|
||
])
|
||
.await
|
||
.is_ok();
|
||
assert!(!cx.config.rustupdir.has(&path));
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn list_targets_explicit() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(["rustup", "toolchain", "add", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "target", "list", "--toolchain", "nightly"])
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
...
|
||
[CROSS_ARCH_I]
|
||
...
|
||
"#]])
|
||
.is_ok();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn link() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
let path = cx.config.customdir.join("custom-1");
|
||
let path = path.to_string_lossy();
|
||
cx.config
|
||
.expect(["rustup", "toolchain", "link", "custom", &path])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "default", "custom"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustc", "--version"])
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
1.0.0 (hash-c-1)
|
||
|
||
"#]])
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "show"])
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
...
|
||
custom (active, default)
|
||
...
|
||
"#]])
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "update", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "default", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "show"])
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
...
|
||
custom
|
||
...
|
||
"#]])
|
||
.is_ok();
|
||
}
|
||
|
||
// Issue #809. When we call the fallback cargo, when it in turn invokes
|
||
// "rustc", that rustc should actually be the rustup proxy, not the toolchain rustc.
|
||
// That way the proxy can pick the correct toolchain.
|
||
#[tokio::test]
|
||
async fn fallback_cargo_calls_correct_rustc() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
// Hm, this is the _only_ test that assumes that toolchain proxies
|
||
// exist in CARGO_HOME. Adding that proxy here.
|
||
let rustup_path = cx.config.exedir.join(format!("rustup{EXE_SUFFIX}"));
|
||
let cargo_bin_path = cx.config.cargodir.join("bin");
|
||
fs::create_dir_all(&cargo_bin_path).unwrap();
|
||
let rustc_path = cargo_bin_path.join(format!("rustc{EXE_SUFFIX}"));
|
||
fs::hard_link(rustup_path, &rustc_path).unwrap();
|
||
|
||
// Install a custom toolchain and a nightly toolchain for the cargo fallback
|
||
let path = cx.config.customdir.join("custom-1");
|
||
let path = path.to_string_lossy();
|
||
cx.config
|
||
.expect(["rustup", "toolchain", "link", "custom", &path])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "default", "custom"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "update", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustc", "--version"])
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
1.0.0 (hash-c-1)
|
||
|
||
"#]])
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["cargo", "--version"])
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
1.3.0 (hash-nightly-2)
|
||
|
||
"#]])
|
||
.is_ok();
|
||
|
||
assert!(rustc_path.exists());
|
||
|
||
// Here --call-rustc tells the mock cargo bin to exec `rustc --version`.
|
||
// We should be ultimately calling the custom rustc, according to the
|
||
// RUSTUP_TOOLCHAIN variable set by the original "cargo" proxy, and
|
||
// interpreted by the nested "rustc" proxy.
|
||
cx.config
|
||
.expect(["cargo", "--call-rustc"])
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
1.0.0 (hash-c-1)
|
||
|
||
"#]])
|
||
.is_ok();
|
||
}
|
||
|
||
// Checks that cargo can recursively invoke itself with rustup shorthand (via
|
||
// the proxy).
|
||
//
|
||
// This involves a series of chained commands:
|
||
//
|
||
// 1. Calls `cargo --recursive-cargo-subcommand`
|
||
// 2. The rustup `cargo` proxy launches, and launches the "mock" nightly cargo exe.
|
||
// 3. The nightly "mock" cargo sees --recursive-cargo-subcommand, and launches
|
||
// `cargo-foo --recursive-cargo`
|
||
// 4. `cargo-foo` sees `--recursive-cargo` and launches `cargo +nightly --version`
|
||
// 5. The rustup `cargo` proxy launches, and launches the "mock" nightly cargo exe.
|
||
// 6. The nightly "mock" cargo sees `--version` and prints the version.
|
||
//
|
||
// Previously, rustup would place the toolchain's `bin` directory in PATH for
|
||
// Windows due to some DLL issues. However, those aren't necessary anymore.
|
||
// If the toolchain `bin` directory is in PATH, then this test would fail in
|
||
// step 5 because the `cargo` executable would be the "mock" nightly cargo,
|
||
// and the first argument would be `+nightly` which would be an error.
|
||
#[tokio::test]
|
||
async fn recursive_cargo() {
|
||
let cx = CliTestContext::new(Scenario::ArchivesV2).await;
|
||
cx.config
|
||
.expect(["rustup", "default", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
|
||
// We need an intermediary to run cargo itself.
|
||
// The "mock" cargo can't do that because on Windows it will check
|
||
// for a `cargo.exe` in the current directory before checking PATH.
|
||
//
|
||
// The solution here is to copy from the "mock" `cargo.exe` into
|
||
// `~/.cargo/bin/cargo-foo`. This is just for convenience to avoid
|
||
// needing to build another executable just for this test.
|
||
let which_cargo = cx.config.expect(["rustup", "which", "cargo"]).await;
|
||
let real_mock_cargo = which_cargo.output.stdout.trim();
|
||
let cargo_bin_path = cx.config.cargodir.join("bin");
|
||
let cargo_subcommand = cargo_bin_path.join(format!("cargo-foo{EXE_SUFFIX}"));
|
||
fs::create_dir_all(&cargo_bin_path).unwrap();
|
||
fs::copy(real_mock_cargo, cargo_subcommand).unwrap();
|
||
|
||
cx.config
|
||
.expect(["cargo", "--recursive-cargo-subcommand"])
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
1.3.0 (hash-nightly-2)
|
||
|
||
"#]])
|
||
.is_ok();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn show_home() {
|
||
let cx = CliTestContext::new(Scenario::None).await;
|
||
cx.config
|
||
.expect(["rustup", "show", "home"])
|
||
.await
|
||
.extend_redactions([("[RUSTUP_DIR]", &cx.config.rustupdir.to_string())])
|
||
.with_stdout(snapbox::str![[r#"
|
||
[RUSTUP_DIR]
|
||
|
||
"#]])
|
||
.with_stderr(snapbox::str![[""]])
|
||
.is_ok();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn show_toolchain_none() {
|
||
let cx = CliTestContext::new(Scenario::None).await;
|
||
cx.config
|
||
.expect(["rustup", "show"])
|
||
.await
|
||
.extend_redactions([("[RUSTUP_DIR]", &cx.config.rustupdir.to_string())])
|
||
.with_stdout(snapbox::str![[r#"
|
||
Default host: [HOST_TUPLE]
|
||
rustup home: [RUSTUP_DIR]
|
||
|
||
installed toolchains
|
||
--------------------
|
||
|
||
active toolchain
|
||
----------------
|
||
no active toolchain
|
||
|
||
"#]])
|
||
.with_stderr(snapbox::str![[""]])
|
||
.is_ok();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn show_toolchain_default() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(["rustup", "default", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "show"])
|
||
.await
|
||
.extend_redactions([("[RUSTUP_DIR]", &cx.config.rustupdir.to_string())])
|
||
.with_stdout(snapbox::str![[r#"
|
||
Default host: [HOST_TUPLE]
|
||
rustup home: [RUSTUP_DIR]
|
||
|
||
installed toolchains
|
||
--------------------
|
||
nightly-[HOST_TUPLE] (active, default)
|
||
|
||
active toolchain
|
||
----------------
|
||
name: nightly-[HOST_TUPLE]
|
||
active because: it's the default toolchain
|
||
installed targets:
|
||
[HOST_TUPLE]
|
||
|
||
"#]])
|
||
.with_stderr(snapbox::str![[""]])
|
||
.is_ok();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn show_no_default() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(["rustup", "install", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "default", "none"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "show"])
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
...
|
||
installed toolchains
|
||
--------------------
|
||
nightly-[HOST_TUPLE]
|
||
|
||
active toolchain
|
||
----------------
|
||
no active toolchain
|
||
|
||
"#]])
|
||
.is_ok();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn show_no_default_active() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(["rustup", "install", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "default", "none"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "+nightly", "show"])
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
...
|
||
installed toolchains
|
||
--------------------
|
||
nightly-[HOST_TUPLE] (active)
|
||
|
||
active toolchain
|
||
----------------
|
||
name: nightly-[HOST_TUPLE]
|
||
active because: overridden by +toolchain on the command line
|
||
installed targets:
|
||
[HOST_TUPLE]
|
||
|
||
"#]])
|
||
.is_ok();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn show_multiple_toolchains() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(["rustup", "default", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "update", "stable"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "show"])
|
||
.await
|
||
.extend_redactions([("[RUSTUP_DIR]", &cx.config.rustupdir.to_string())])
|
||
.with_stdout(snapbox::str![[r#"
|
||
Default host: [HOST_TUPLE]
|
||
rustup home: [RUSTUP_DIR]
|
||
|
||
installed toolchains
|
||
--------------------
|
||
stable-[HOST_TUPLE]
|
||
nightly-[HOST_TUPLE] (active, default)
|
||
|
||
active toolchain
|
||
----------------
|
||
name: nightly-[HOST_TUPLE]
|
||
active because: it's the default toolchain
|
||
installed targets:
|
||
[HOST_TUPLE]
|
||
|
||
"#]])
|
||
.with_stderr(snapbox::str![[""]])
|
||
.is_ok();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn show_multiple_targets() {
|
||
let cx = CliTestContext::new(Scenario::MultiHost).await;
|
||
cx.config
|
||
.expect([
|
||
"rustup",
|
||
"default",
|
||
&format!("nightly-{MULTI_ARCH1}"),
|
||
"--force-non-host",
|
||
])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "target", "add", CROSS_ARCH2])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "show"])
|
||
.await
|
||
.extend_redactions([("[RUSTUP_DIR]", &cx.config.rustupdir.to_string())])
|
||
.with_stdout(snapbox::str![[r#"
|
||
Default host: [HOST_TUPLE]
|
||
rustup home: [RUSTUP_DIR]
|
||
|
||
installed toolchains
|
||
--------------------
|
||
nightly-[MULTI_ARCH_I] (active, default)
|
||
|
||
active toolchain
|
||
----------------
|
||
name: nightly-[MULTI_ARCH_I]
|
||
active because: it's the default toolchain
|
||
installed targets:
|
||
[CROSS_ARCH_II]
|
||
[MULTI_ARCH_I]
|
||
|
||
"#]])
|
||
.with_stderr(snapbox::str![[""]])
|
||
.is_ok();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn show_multiple_toolchains_and_targets() {
|
||
if cfg!(target_os = "linux") && cfg!(target_arch = "x86") {
|
||
return;
|
||
}
|
||
|
||
let cx = CliTestContext::new(Scenario::MultiHost).await;
|
||
cx.config
|
||
.expect([
|
||
"rustup",
|
||
"default",
|
||
&format!("nightly-{MULTI_ARCH1}"),
|
||
"--force-non-host",
|
||
])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "target", "add", CROSS_ARCH2])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect([
|
||
"rustup",
|
||
"update",
|
||
"--force-non-host",
|
||
&format!("stable-{MULTI_ARCH1}"),
|
||
])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "show"])
|
||
.await
|
||
.extend_redactions([("[RUSTUP_DIR]", &cx.config.rustupdir.to_string())])
|
||
.with_stdout(snapbox::str![[r#"
|
||
Default host: [HOST_TUPLE]
|
||
rustup home: [RUSTUP_DIR]
|
||
|
||
installed toolchains
|
||
--------------------
|
||
stable-[MULTI_ARCH_I]
|
||
nightly-[MULTI_ARCH_I] (active, default)
|
||
|
||
active toolchain
|
||
----------------
|
||
name: nightly-[MULTI_ARCH_I]
|
||
active because: it's the default toolchain
|
||
installed targets:
|
||
[CROSS_ARCH_II]
|
||
[MULTI_ARCH_I]
|
||
|
||
"#]])
|
||
.with_stderr(snapbox::str![[""]])
|
||
.is_ok();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn list_default_toolchain() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(["rustup", "default", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "toolchain", "list"])
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
nightly-[HOST_TUPLE] (active, default)
|
||
|
||
"#]])
|
||
.with_stderr(snapbox::str![[""]])
|
||
.is_ok();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn list_default_toolchain_quiet() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(["rustup", "default", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "toolchain", "list", "--quiet"])
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
nightly-[HOST_TUPLE]
|
||
|
||
"#]])
|
||
.with_stderr(snapbox::str![[""]])
|
||
.is_ok();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn list_no_default_toolchain() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(["rustup", "install", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "default", "none"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "toolchain", "list"])
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
nightly-[HOST_TUPLE]
|
||
|
||
"#]])
|
||
.with_stderr(snapbox::str![[""]])
|
||
.is_ok();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn list_no_default_override_toolchain() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(["rustup", "override", "set", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "toolchain", "list"])
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
nightly-[HOST_TUPLE] (active)
|
||
|
||
"#]])
|
||
.with_stderr(snapbox::str![[""]])
|
||
.is_ok();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn list_default_and_override_toolchain() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(&["rustup", "default", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(&["rustup", "override", "set", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(&["rustup", "toolchain", "list"])
|
||
.await
|
||
.is_ok()
|
||
.with_stdout(snapbox::str![[r#"
|
||
nightly-[HOST_TUPLE] (active, default)
|
||
|
||
"#]])
|
||
.with_stderr(snapbox::str![[""]]);
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn show_toolchain_override() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(["rustup", "override", "add", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "show"])
|
||
.await
|
||
.extend_redactions([("[RUSTUP_DIR]", &cx.config.rustupdir.to_string())])
|
||
.with_stdout(snapbox::str![[r#"
|
||
Default host: [HOST_TUPLE]
|
||
rustup home: [RUSTUP_DIR]
|
||
|
||
installed toolchains
|
||
--------------------
|
||
nightly-[HOST_TUPLE] (active)
|
||
|
||
active toolchain
|
||
----------------
|
||
name: nightly-[HOST_TUPLE]
|
||
active because: directory override for '[..]'
|
||
installed targets:
|
||
[HOST_TUPLE]
|
||
|
||
"#]])
|
||
.with_stderr(snapbox::str![[""]])
|
||
.is_ok();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn show_toolchain_toolchain_file_override() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(["rustup", "default", "stable"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "toolchain", "install", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
|
||
let cwd = cx.config.current_dir();
|
||
let toolchain_file = cwd.join("rust-toolchain");
|
||
|
||
raw::write_file(&toolchain_file, "nightly").unwrap();
|
||
|
||
cx.config
|
||
.expect(["rustup", "show"])
|
||
.await
|
||
.extend_redactions([("[RUSTUP_DIR]", &cx.config.rustupdir.to_string())])
|
||
.with_stdout(snapbox::str![[r#"
|
||
Default host: [HOST_TUPLE]
|
||
rustup home: [RUSTUP_DIR]
|
||
|
||
installed toolchains
|
||
--------------------
|
||
stable-[HOST_TUPLE] (default)
|
||
nightly-[HOST_TUPLE] (active)
|
||
|
||
active toolchain
|
||
----------------
|
||
name: nightly-[HOST_TUPLE]
|
||
active because: overridden by '[..]'
|
||
installed targets:
|
||
[HOST_TUPLE]
|
||
|
||
"#]])
|
||
.with_stderr(snapbox::str![[""]])
|
||
.is_ok();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn show_toolchain_version_nested_file_override() {
|
||
let mut cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(["rustup", "toolchain", "add", "stable", "beta", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "default", "stable"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "toolchain", "install", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
|
||
let cwd = cx.config.current_dir();
|
||
let toolchain_file = cwd.join("rust-toolchain");
|
||
|
||
raw::write_file(&toolchain_file, "nightly").unwrap();
|
||
|
||
let subdir = cwd.join("foo");
|
||
|
||
fs::create_dir_all(&subdir).unwrap();
|
||
let cx = cx.change_dir(&subdir);
|
||
cx.config
|
||
.expect(["rustup", "show"])
|
||
.await
|
||
.extend_redactions([("[RUSTUP_DIR]", &cx.config.rustupdir.to_string())])
|
||
.with_stdout(snapbox::str![[r#"
|
||
Default host: [HOST_TUPLE]
|
||
rustup home: [RUSTUP_DIR]
|
||
|
||
installed toolchains
|
||
--------------------
|
||
stable-[HOST_TUPLE] (default)
|
||
beta-[HOST_TUPLE]
|
||
nightly-[HOST_TUPLE] (active)
|
||
|
||
active toolchain
|
||
----------------
|
||
name: nightly-[HOST_TUPLE]
|
||
active because: overridden by '[..]'
|
||
installed targets:
|
||
[HOST_TUPLE]
|
||
|
||
"#]])
|
||
.with_stderr(snapbox::str![[""]])
|
||
.is_ok();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn show_toolchain_toolchain_file_override_not_installed() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(["rustup", "default", "stable"])
|
||
.await
|
||
.is_ok();
|
||
|
||
let cwd = cx.config.current_dir();
|
||
let toolchain_file = cwd.join("rust-toolchain");
|
||
|
||
raw::write_file(&toolchain_file, "nightly").unwrap();
|
||
|
||
// I'm not sure this should really be erroring when the toolchain
|
||
// is not installed; just capturing the behavior.
|
||
cx.config
|
||
.expect_with_env(["rustup", "show"], [("RUSTUP_AUTO_INSTALL", "0")])
|
||
.await
|
||
.extend_redactions([
|
||
("[RUSTUP_DIR]", &cx.config.rustupdir.rustupdir),
|
||
("[TOOLCHAIN_FILE]", &toolchain_file),
|
||
])
|
||
.with_stdout(snapbox::str![[r#"
|
||
Default host: [HOST_TUPLE]
|
||
rustup home: [RUSTUP_DIR]
|
||
|
||
|
||
"#]])
|
||
.with_stderr(snapbox::str![[r#"
|
||
error: toolchain 'nightly-[HOST_TUPLE]' is not installed
|
||
help: run `rustup toolchain install` to install it
|
||
|
||
"#]])
|
||
.is_err();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn show_toolchain_override_not_installed() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(["rustup", "override", "add", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "toolchain", "remove", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "show"])
|
||
.await
|
||
.extend_redactions([("[RUSTUP_DIR]", &cx.config.rustupdir.to_string())])
|
||
.with_stdout(snapbox::str![[r#"
|
||
Default host: [HOST_TUPLE]
|
||
rustup home: [RUSTUP_DIR]
|
||
|
||
installed toolchains
|
||
--------------------
|
||
|
||
active toolchain
|
||
----------------
|
||
name: nightly-[HOST_TUPLE]
|
||
active because: directory override for '[..]'
|
||
installed targets:
|
||
[HOST_TUPLE]
|
||
|
||
"#]])
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "component", "list", "--installed"])
|
||
.await
|
||
.is_ok()
|
||
.with_stdout(snapbox::str![[r#"
|
||
cargo-[HOST_TUPLE]
|
||
rust-docs-[HOST_TUPLE]
|
||
rust-std-[HOST_TUPLE]
|
||
rustc-[HOST_TUPLE]
|
||
|
||
"#]]);
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn override_set_unset_with_path() {
|
||
let mut cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
let cwd = fs::canonicalize(cx.config.current_dir()).unwrap();
|
||
let mut cwd_str = cwd.to_str().unwrap();
|
||
|
||
if cfg!(windows) {
|
||
cwd_str = &cwd_str[4..];
|
||
}
|
||
|
||
let emptydir = tempfile::tempdir().unwrap();
|
||
{
|
||
let cx = cx.change_dir(emptydir.path());
|
||
cx.config
|
||
.expect(["rustup", "override", "set", "nightly", "--path", cwd_str])
|
||
.await
|
||
.is_ok();
|
||
}
|
||
|
||
cx.config
|
||
.expect(["rustup", "override", "list"])
|
||
.await
|
||
.extend_redactions([("[CWD]", cwd_str.to_string())])
|
||
.with_stdout(snapbox::str![[r#"
|
||
[CWD] nightly-[HOST_TUPLE]
|
||
|
||
"#]])
|
||
.with_stderr(snapbox::str![[""]])
|
||
.is_ok();
|
||
|
||
{
|
||
let cx = cx.change_dir(emptydir.path());
|
||
cx.config
|
||
.expect(["rustup", "override", "unset", "--path", cwd_str])
|
||
.await
|
||
.is_ok();
|
||
}
|
||
|
||
cx.config
|
||
.expect(["rustup", "override", "list"])
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
no overrides
|
||
|
||
"#]])
|
||
.with_stderr(snapbox::str![[""]])
|
||
.is_ok();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn show_toolchain_env() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(&["rustup", "default", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect_with_env(["rustup", "show"], [("RUSTUP_TOOLCHAIN", "nightly")])
|
||
.await
|
||
.extend_redactions([("[RUSTUP_DIR]", &cx.config.rustupdir.to_string())])
|
||
.is_ok()
|
||
.with_stdout(snapbox::str![[r#"
|
||
Default host: [HOST_TUPLE]
|
||
rustup home: [RUSTUP_DIR]
|
||
|
||
installed toolchains
|
||
--------------------
|
||
nightly-[HOST_TUPLE] (active, default)
|
||
|
||
active toolchain
|
||
----------------
|
||
name: nightly-[HOST_TUPLE]
|
||
active because: overridden by environment variable RUSTUP_TOOLCHAIN
|
||
installed targets:
|
||
[HOST_TUPLE]
|
||
|
||
"#]]);
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn show_toolchain_env_not_installed() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect_with_env(["rustup", "show"], [("RUSTUP_TOOLCHAIN", "nightly")])
|
||
.await
|
||
.extend_redactions([("[RUSTUP_DIR]", &cx.config.rustupdir.to_string())])
|
||
.is_ok()
|
||
.with_stdout(snapbox::str![[r#"
|
||
Default host: [HOST_TUPLE]
|
||
rustup home: [RUSTUP_DIR]
|
||
|
||
installed toolchains
|
||
--------------------
|
||
|
||
active toolchain
|
||
----------------
|
||
name: nightly-[HOST_TUPLE]
|
||
active because: overridden by environment variable RUSTUP_TOOLCHAIN
|
||
installed targets:
|
||
[HOST_TUPLE]
|
||
|
||
"#]]);
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn show_active_toolchain() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(&["rustup", "default", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(&["rustup", "show", "active-toolchain"])
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
nightly-[HOST_TUPLE] (default)
|
||
|
||
"#]])
|
||
.with_stderr(snapbox::str![[""]])
|
||
.is_ok();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn show_with_verbose() {
|
||
let mut cx = CliTestContext::new(Scenario::None).await;
|
||
|
||
{
|
||
let cx = cx.with_dist_dir(Scenario::SimpleV2);
|
||
cx.config
|
||
.expect(["rustup", "default", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
}
|
||
|
||
let cx = cx.with_dist_dir(Scenario::ArchivesV2_2015_01_01);
|
||
let config = &cx.config;
|
||
config
|
||
.expect(["rustup", "update", "nightly-2015-01-01"])
|
||
.await
|
||
.is_ok();
|
||
config
|
||
.expect(["rustup", "show", "--verbose"])
|
||
.await
|
||
.extend_redactions([("[RUSTUP_DIR]", &cx.config.rustupdir.to_string())])
|
||
.with_stdout(snapbox::str![[r#"
|
||
Default host: [HOST_TUPLE]
|
||
rustup home: [RUSTUP_DIR]
|
||
|
||
installed toolchains
|
||
--------------------
|
||
nightly-[HOST_TUPLE] (active, default)
|
||
1.3.0 (hash-nightly-2)
|
||
path: [RUSTUP_DIR]/toolchains/nightly-[HOST_TUPLE]
|
||
|
||
nightly-2015-01-01-[HOST_TUPLE]
|
||
1.2.0 (hash-nightly-1)
|
||
path: [RUSTUP_DIR]/toolchains/nightly-2015-01-01-[HOST_TUPLE]
|
||
|
||
active toolchain
|
||
----------------
|
||
name: nightly-[HOST_TUPLE]
|
||
active because: it's the default toolchain
|
||
compiler: 1.3.0 (hash-nightly-2)
|
||
path: [RUSTUP_DIR]/toolchains/nightly-[HOST_TUPLE]
|
||
installed targets:
|
||
[HOST_TUPLE]
|
||
|
||
"#]])
|
||
.with_stderr(snapbox::str![[""]])
|
||
.is_ok();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn show_active_toolchain_with_verbose() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(["rustup", "default", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "show", "active-toolchain", "--verbose"])
|
||
.await
|
||
.extend_redactions([("[RUSTUP_DIR]", &cx.config.rustupdir.to_string())])
|
||
.with_stdout(snapbox::str![[r#"
|
||
nightly-[HOST_TUPLE]
|
||
active because: it's the default toolchain
|
||
compiler: 1.3.0 (hash-nightly-2)
|
||
path: [RUSTUP_DIR]/toolchains/nightly-[HOST_TUPLE]
|
||
|
||
"#]])
|
||
.with_stderr(snapbox::str![[""]])
|
||
.is_ok();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn show_active_toolchain_with_override() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(["rustup", "default", "stable"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "default", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "override", "set", "stable"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "show", "active-toolchain"])
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
stable-[HOST_TUPLE] (directory override for '[..]')
|
||
|
||
"#]])
|
||
.is_ok();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn show_active_toolchain_with_override_verbose() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(["rustup", "default", "stable"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "default", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "override", "set", "stable"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "show", "active-toolchain", "--verbose"])
|
||
.await
|
||
.extend_redactions([("[RUSTUP_DIR]", &cx.config.rustupdir.to_string())])
|
||
.with_stdout(snapbox::str![[r#"
|
||
stable-[HOST_TUPLE]
|
||
active because: directory override for '[..]'
|
||
compiler: 1.1.0 (hash-stable-1.1.0)
|
||
path: [RUSTUP_DIR]/toolchains/stable-[HOST_TUPLE]
|
||
|
||
"#]])
|
||
.with_stderr(snapbox::str![[""]])
|
||
.is_ok();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn show_active_toolchain_none() {
|
||
let cx = CliTestContext::new(Scenario::None).await;
|
||
cx.config
|
||
.expect(["rustup", "show", "active-toolchain"])
|
||
.await
|
||
.with_stdout(snapbox::str![[""]])
|
||
.with_stderr(snapbox::str![[r#"
|
||
error: no active toolchain
|
||
|
||
"#]])
|
||
.is_err();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn show_profile() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(["rustup", "default", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "show", "profile"])
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
default
|
||
|
||
"#]])
|
||
.is_ok();
|
||
|
||
// Check we get the same thing after we add or remove a component.
|
||
cx.config
|
||
.expect(["rustup", "component", "add", "rust-src"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "show", "profile"])
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
default
|
||
|
||
"#]])
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "component", "remove", "rustc"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "show", "profile"])
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
default
|
||
|
||
"#]])
|
||
.is_ok();
|
||
}
|
||
|
||
// #846
|
||
#[tokio::test]
|
||
async fn set_default_host() {
|
||
let cx = CliTestContext::new(Scenario::None).await;
|
||
cx.config
|
||
.expect(["rustup", "set", "default-host", &this_host_tuple()])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "show"])
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
...
|
||
Default host: [HOST_TUPLE]
|
||
...
|
||
"#]])
|
||
.is_ok();
|
||
}
|
||
|
||
// #846
|
||
#[tokio::test]
|
||
async fn set_default_host_invalid_triple() {
|
||
let cx = CliTestContext::new(Scenario::None).await;
|
||
cx.config
|
||
.expect(["rustup", "set", "default-host", "foo"])
|
||
.await
|
||
.with_stderr(snapbox::str![[r#"
|
||
error: Provided host 'foo' couldn't be converted to partial triple
|
||
|
||
"#]])
|
||
.is_err();
|
||
}
|
||
|
||
// #745
|
||
#[tokio::test]
|
||
async fn set_default_host_invalid_triple_valid_partial() {
|
||
let cx = CliTestContext::new(Scenario::None).await;
|
||
cx.config
|
||
.expect(["rustup", "set", "default-host", "x86_64-msvc"])
|
||
.await
|
||
.with_stderr(snapbox::str![[r#"
|
||
error: Provided host 'x86_64-msvc' did not specify an operating system
|
||
|
||
"#]])
|
||
.is_err();
|
||
}
|
||
|
||
// #422
|
||
#[tokio::test]
|
||
async fn update_doesnt_update_non_tracking_channels() {
|
||
let mut cx = CliTestContext::new(Scenario::None).await;
|
||
|
||
{
|
||
let cx = cx.with_dist_dir(Scenario::SimpleV2);
|
||
cx.config
|
||
.expect(["rustup", "default", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
}
|
||
|
||
let cx = cx.with_dist_dir(Scenario::ArchivesV2_2015_01_01);
|
||
cx.config
|
||
.expect(["rustup", "update", "nightly-2015-01-01"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "update"])
|
||
.await
|
||
.is_ok()
|
||
.without_stderr(&format!(
|
||
"syncing channel updates for 'nightly-2015-01-01-{}'",
|
||
this_host_tuple(),
|
||
));
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn toolchain_install_is_like_update() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(["rustup", "toolchain", "install", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "run", "nightly", "rustc", "--version"])
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
1.3.0 (hash-nightly-2)
|
||
|
||
"#]])
|
||
.is_ok();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn toolchain_install_is_like_update_quiet() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(["rustup", "--quiet", "toolchain", "install", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "run", "nightly", "rustc", "--version"])
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
1.3.0 (hash-nightly-2)
|
||
|
||
"#]])
|
||
.is_ok();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn toolchain_install_without_args_installs_active() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
|
||
let cwd = cx.config.current_dir();
|
||
let toolchain_file = cwd.join("rust-toolchain.toml");
|
||
raw::write_file(
|
||
&toolchain_file,
|
||
r#"
|
||
[toolchain]
|
||
profile = "minimal"
|
||
channel = "nightly"
|
||
"#,
|
||
)
|
||
.unwrap();
|
||
|
||
cx.config
|
||
.expect(["rustup", "toolchain", "install"])
|
||
.await
|
||
.extend_redactions([("[TOOLCHAIN_FILE]", &toolchain_file)])
|
||
.with_stderr(snapbox::str![[r#"
|
||
info: syncing channel updates for nightly-[HOST_TUPLE]
|
||
info: latest update on 2015-01-02 for version 1.3.0 (hash-nightly-2)
|
||
info: downloading component rustc
|
||
info: the active toolchain `nightly-[HOST_TUPLE]` has been installed
|
||
info: it's active because: overridden by '[TOOLCHAIN_FILE]'
|
||
|
||
"#]])
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "+nightly", "component", "list", "--installed"])
|
||
.await
|
||
.is_ok()
|
||
.with_stdout(snapbox::str![[r#"
|
||
rustc-[HOST_TUPLE]
|
||
|
||
"#]]);
|
||
|
||
cx.config
|
||
.expect(["rustup", "toolchain", "install"])
|
||
.await
|
||
.extend_redactions([("[TOOLCHAIN_FILE]", &toolchain_file)])
|
||
.with_stderr(snapbox::str![[r#"
|
||
info: using existing install for nightly-[HOST_TUPLE]
|
||
info: the active toolchain `nightly-[HOST_TUPLE]` has been installed
|
||
info: it's active because: overridden by '[TOOLCHAIN_FILE]'
|
||
|
||
"#]])
|
||
.is_ok();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn toolchain_install_no_change_with_no_update() {
|
||
let mut cx = CliTestContext::new(Scenario::None).await;
|
||
|
||
{
|
||
let cx = cx.with_dist_dir(Scenario::ArchivesV2_2015_01_01);
|
||
cx.config
|
||
.expect(["rustup", "toolchain", "add", "stable"])
|
||
.await
|
||
.is_ok();
|
||
}
|
||
|
||
let cx = cx.with_dist_dir(Scenario::SimpleV2);
|
||
cx.config
|
||
.expect(["rustup", "install", "--no-update", "stable"])
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
|
||
stable-[HOST_TUPLE] unchanged - 1.0.0 (hash-stable-1.0.0)
|
||
|
||
|
||
"#]])
|
||
.with_stderr(snapbox::str![[""]])
|
||
.is_ok();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn toolchain_update_is_like_update() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(["rustup", "toolchain", "update", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "run", "nightly", "rustc", "--version"])
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
1.3.0 (hash-nightly-2)
|
||
|
||
"#]])
|
||
.is_ok();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn toolchain_uninstall_is_like_uninstall() {
|
||
let mut cx = CliTestContext::new(Scenario::None).await;
|
||
|
||
{
|
||
let cx = cx.with_dist_dir(Scenario::SimpleV2);
|
||
cx.config
|
||
.expect(["rustup", "toolchain", "install", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
}
|
||
|
||
cx.config
|
||
.expect(["rustup", "default", "none"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "uninstall", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "show"])
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
...
|
||
installed toolchains
|
||
--------------------
|
||
|
||
active toolchain
|
||
----------------
|
||
no active toolchain
|
||
|
||
"#]])
|
||
.is_ok();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn uninstall_multiple_toolchains_sequentially() {
|
||
let mut cx = CliTestContext::new(Scenario::None).await;
|
||
|
||
{
|
||
let cx = cx.with_dist_dir(Scenario::SimpleV2);
|
||
cx.config
|
||
.expect(["rustup", "toolchain", "install", "stable"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "toolchain", "install", "beta"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "toolchain", "install", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
}
|
||
|
||
cx.config
|
||
.expect(["rustup", "default", "none"])
|
||
.await
|
||
.is_ok();
|
||
|
||
cx.config
|
||
.expect([
|
||
"rustup",
|
||
"toolchain",
|
||
"uninstall",
|
||
"stable",
|
||
"beta",
|
||
"nightly",
|
||
])
|
||
.await
|
||
.is_ok();
|
||
|
||
cx.config
|
||
.expect(["rustup", "toolchain", "list"])
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
no installed toolchains
|
||
|
||
"#]])
|
||
.is_ok();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn proxy_toolchain_shorthand() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(["rustup", "default", "stable"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "toolchain", "update", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustc", "--version"])
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
1.1.0 (hash-stable-1.1.0)
|
||
|
||
"#]])
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustc", "+stable", "--version"])
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
1.1.0 (hash-stable-1.1.0)
|
||
|
||
"#]])
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustc", "+nightly", "--version"])
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
1.3.0 (hash-nightly-2)
|
||
|
||
"#]])
|
||
.is_ok();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn add_component() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(["rustup", "default", "stable"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "component", "add", "rust-src"])
|
||
.await
|
||
.is_ok();
|
||
let path = format!(
|
||
"toolchains/stable-{}/lib/rustlib/src/rust-src/foo.rs",
|
||
this_host_tuple()
|
||
);
|
||
assert!(cx.config.rustupdir.has(path));
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn add_component_by_target_triple() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(["rustup", "default", "stable"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect([
|
||
"rustup",
|
||
"component",
|
||
"add",
|
||
&format!("rust-std-{CROSS_ARCH1}"),
|
||
])
|
||
.await
|
||
.is_ok();
|
||
let path = format!(
|
||
"toolchains/stable-{}/lib/rustlib/{CROSS_ARCH1}/lib/libstd.rlib",
|
||
this_host_tuple()
|
||
);
|
||
assert!(cx.config.rustupdir.has(path));
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn add_component_by_target_triple_renamed_from() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(["rustup", "default", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect([
|
||
"rustup",
|
||
"component",
|
||
"add",
|
||
&format!("rls-{}", this_host_tuple()),
|
||
])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "component", "list", "--installed"])
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
...
|
||
rls-[HOST_TUPLE]
|
||
...
|
||
"#]])
|
||
.is_ok();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn add_component_by_target_triple_renamed_to() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(["rustup", "default", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect([
|
||
"rustup",
|
||
"component",
|
||
"add",
|
||
&format!("rls-preview-{}", this_host_tuple()),
|
||
])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "component", "list", "--installed"])
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
...
|
||
rls-[HOST_TUPLE]
|
||
...
|
||
"#]])
|
||
.is_ok();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn fail_invalid_component_name() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(&["rustup", "default", "stable"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(&[
|
||
"rustup",
|
||
"component",
|
||
"add",
|
||
&format!("dummy-{CROSS_ARCH1}"),
|
||
])
|
||
.await
|
||
.with_stderr(snapbox::str![[r#"
|
||
error: toolchain 'stable-[HOST_TUPLE]' does not contain component 'dummy-[CROSS_ARCH_I]' for target '[HOST_TUPLE]'
|
||
|
||
"#]])
|
||
.is_err();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn fail_invalid_component_target() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(&["rustup", "default", "stable"])
|
||
.await
|
||
.is_ok();
|
||
cx.config.expect(&[
|
||
"rustup",
|
||
"component",
|
||
"add",
|
||
"rust-std-invalid-target",
|
||
])
|
||
.await
|
||
.with_stderr(snapbox::str![[r#"
|
||
...
|
||
error: toolchain 'stable-[HOST_TUPLE]' does not contain component 'rust-std-invalid-target' for target '[HOST_TUPLE]'
|
||
...
|
||
"#]])
|
||
.is_err();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn remove_component() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(&["rustup", "default", "stable"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(&["rustup", "component", "add", "rust-src"])
|
||
.await
|
||
.is_ok();
|
||
let path = PathBuf::from(format!(
|
||
"toolchains/stable-{}/lib/rustlib/src/rust-src/foo.rs",
|
||
this_host_tuple(),
|
||
));
|
||
assert!(cx.config.rustupdir.has(&path));
|
||
cx.config
|
||
.expect(&["rustup", "component", "remove", "rust-src"])
|
||
.await
|
||
.is_ok();
|
||
assert!(!cx.config.rustupdir.has(path.parent().unwrap()));
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn remove_component_by_target_triple() {
|
||
let component_with_triple = format!("rust-std-{CROSS_ARCH1}");
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(&["rustup", "default", "stable"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(&["rustup", "component", "add", &component_with_triple])
|
||
.await
|
||
.is_ok();
|
||
let path = PathBuf::from(format!(
|
||
"toolchains/stable-{}/lib/rustlib/{CROSS_ARCH1}/lib/libstd.rlib",
|
||
this_host_tuple()
|
||
));
|
||
assert!(cx.config.rustupdir.has(&path));
|
||
cx.config
|
||
.expect(&["rustup", "component", "remove", &component_with_triple])
|
||
.await
|
||
.is_ok();
|
||
assert!(!cx.config.rustupdir.has(path.parent().unwrap()));
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn add_remove_multiple_components() {
|
||
let files = [
|
||
"lib/rustlib/src/rust-src/foo.rs".to_owned(),
|
||
format!("lib/rustlib/{}/analysis/libfoo.json", this_host_tuple()),
|
||
format!("lib/rustlib/{CROSS_ARCH1}/lib/libstd.rlib"),
|
||
format!("lib/rustlib/{CROSS_ARCH2}/lib/libstd.rlib"),
|
||
];
|
||
let component_with_triple1 = format!("rust-std-{CROSS_ARCH1}");
|
||
let component_with_triple2 = format!("rust-std-{CROSS_ARCH2}");
|
||
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(&["rustup", "default", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(&[
|
||
"rustup",
|
||
"component",
|
||
"add",
|
||
"rust-src",
|
||
"rust-analysis",
|
||
&component_with_triple1,
|
||
&component_with_triple2,
|
||
])
|
||
.await
|
||
.is_ok();
|
||
for file in &files {
|
||
let path = format!("toolchains/nightly-{}/{}", this_host_tuple(), file);
|
||
assert!(cx.config.rustupdir.has(&path));
|
||
}
|
||
cx.config
|
||
.expect(&[
|
||
"rustup",
|
||
"component",
|
||
"remove",
|
||
"rust-src",
|
||
"rust-analysis",
|
||
&component_with_triple1,
|
||
&component_with_triple2,
|
||
])
|
||
.await
|
||
.is_ok();
|
||
for file in &files {
|
||
let path = PathBuf::from(format!("toolchains/nightly-{}/{}", this_host_tuple(), file));
|
||
assert!(!cx.config.rustupdir.has(path.parent().unwrap()));
|
||
}
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn remove_multiple_components_best_effort() {
|
||
let files = [
|
||
"lib/rustlib/src/rust-src/foo.rs",
|
||
for_host!("lib/rustlib/{}/analysis/libfoo.json"),
|
||
];
|
||
|
||
for (one, two, three) in [
|
||
("bad-component", "rust-src", "rust-analysis"),
|
||
("rust-src", "bad-component", "rust-analysis"),
|
||
("rust-src", "rust-analysis", "bad-component"),
|
||
] {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(&["rustup", "default", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(&["rustup", "component", "add", "rust-src", "rust-analysis"])
|
||
.await
|
||
.is_ok();
|
||
|
||
for file in &files {
|
||
let path = for_host!("toolchains/nightly-{0}/{file}");
|
||
assert!(cx.config.rustupdir.has(path));
|
||
}
|
||
|
||
cx.config
|
||
.expect(&["rustup", "component", "remove", one, two, three])
|
||
.await
|
||
.is_err();
|
||
|
||
for file in &files {
|
||
let path = PathBuf::from(for_host!("toolchains/nightly-{0}/{file}"));
|
||
assert!(!cx.config.rustupdir.has(path.parent().unwrap()));
|
||
}
|
||
}
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn remove_multiple_components_reports_all_invalid_names() {
|
||
let files = [
|
||
"lib/rustlib/src/rust-src/foo.rs",
|
||
for_host!("lib/rustlib/{}/analysis/libfoo.json"),
|
||
];
|
||
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(["rustup", "default", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
|
||
cx.config
|
||
.expect(["rustup", "component", "add", "rust-src", "rust-analysis"])
|
||
.await
|
||
.is_ok();
|
||
|
||
for file in &files {
|
||
let path = for_host!("toolchains/nightly-{0}/{file}");
|
||
assert!(cx.config.rustupdir.has(path));
|
||
}
|
||
|
||
cx.config
|
||
.expect([
|
||
"rustup",
|
||
"component",
|
||
"remove",
|
||
"bad-component-1",
|
||
"rust-src",
|
||
"bad-component-2",
|
||
"rust-analysis",
|
||
])
|
||
.await
|
||
.with_stderr(snapbox::str![[r#"
|
||
info: removing component rust-src
|
||
info: removing component rust-analysis
|
||
error: toolchain 'nightly-[HOST_TUPLE]' does not contain these components:
|
||
- 'bad-component-1'
|
||
- 'bad-component-2'
|
||
|
||
|
||
"#]])
|
||
.is_err();
|
||
|
||
for file in &files {
|
||
let path = PathBuf::from(for_host!("toolchains/nightly-{0}/{file}",));
|
||
assert!(!cx.config.rustupdir.has(path.parent().unwrap()));
|
||
}
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn file_override() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(&["rustup", "default", "stable"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(&["rustup", "toolchain", "install", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
|
||
cx.config
|
||
.expect(&["rustc", "--version"])
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
1.1.0 (hash-stable-1.1.0)
|
||
|
||
"#]])
|
||
.is_ok();
|
||
|
||
let cwd = cx.config.current_dir();
|
||
let toolchain_file = cwd.join("rust-toolchain");
|
||
raw::write_file(&toolchain_file, "nightly").unwrap();
|
||
|
||
cx.config
|
||
.expect(&["rustc", "--version"])
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
1.3.0 (hash-nightly-2)
|
||
|
||
"#]])
|
||
.is_ok();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn env_override_path() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(&["rustup", "default", "stable"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(&["rustup", "toolchain", "install", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
|
||
let toolchain_path = cx
|
||
.config
|
||
.rustupdir
|
||
.join("toolchains")
|
||
.join(format!("nightly-{}", this_host_tuple()));
|
||
|
||
cx.config
|
||
.expect_with_env(
|
||
["rustc", "--version"],
|
||
[("RUSTUP_TOOLCHAIN", toolchain_path.to_str().unwrap())],
|
||
)
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
1.3.0 (hash-nightly-2)
|
||
|
||
"#]])
|
||
.is_ok();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn plus_override_relpath_is_not_supported() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(["rustup", "default", "stable"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "toolchain", "install", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
|
||
let toolchain_path = Path::new("..")
|
||
.join(cx.config.rustupdir.rustupdir.file_name().unwrap())
|
||
.join("toolchains")
|
||
.join(format!("nightly-{}", this_host_tuple()));
|
||
cx.config
|
||
.expect([
|
||
"rustc",
|
||
format!("+{}", toolchain_path.to_str().unwrap()).as_str(),
|
||
"--version",
|
||
])
|
||
.await
|
||
.with_stderr(snapbox::str![[r#"
|
||
error: relative path toolchain '[..]/toolchains/nightly-[HOST_TUPLE]'
|
||
|
||
"#]])
|
||
.is_err();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn run_with_relpath_is_not_supported() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(["rustup", "default", "stable"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "toolchain", "install", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
|
||
let toolchain_path = Path::new("..")
|
||
.join(cx.config.rustupdir.rustupdir.file_name().unwrap())
|
||
.join("toolchains")
|
||
.join(format!("nightly-{}", this_host_tuple()));
|
||
cx.config
|
||
.expect([
|
||
"rustup",
|
||
"run",
|
||
toolchain_path.to_str().unwrap(),
|
||
"rustc",
|
||
"--version",
|
||
])
|
||
.await
|
||
.with_stderr(snapbox::str![[r#"
|
||
...
|
||
error:[..] relative path toolchain '[..]/toolchains/nightly-[HOST_TUPLE]'
|
||
...
|
||
"#]])
|
||
.is_err();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn run_with_plus_prefix_fails_with_helpful_message() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(["rustup", "default", "stable"])
|
||
.await
|
||
.is_ok();
|
||
|
||
cx.config
|
||
.expect(["rustup", "run", "+stable", "cargo", "check"])
|
||
.await
|
||
.with_stderr(snapbox::str![[r#"
|
||
...
|
||
error:[..] invalid toolchain name '+stable'; valid toolchain names do not start with '+'
|
||
...
|
||
"#]])
|
||
.is_err();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn plus_override_abspath_is_supported() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(["rustup", "default", "stable"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "toolchain", "install", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
|
||
let toolchain_path = cx
|
||
.config
|
||
.rustupdir
|
||
.join("toolchains")
|
||
.join(format!("nightly-{}", this_host_tuple()))
|
||
.canonicalize()
|
||
.unwrap();
|
||
cx.config
|
||
.expect([
|
||
"rustc",
|
||
format!("+{}", toolchain_path.to_str().unwrap()).as_str(),
|
||
"--version",
|
||
])
|
||
.await
|
||
.is_ok();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn run_with_abspath_is_supported() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(["rustup", "default", "stable"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "toolchain", "install", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
|
||
let toolchain_path = cx
|
||
.config
|
||
.rustupdir
|
||
.join("toolchains")
|
||
.join(format!("nightly-{}", this_host_tuple()))
|
||
.canonicalize()
|
||
.unwrap();
|
||
cx.config
|
||
.expect([
|
||
"rustup",
|
||
"run",
|
||
toolchain_path.to_str().unwrap(),
|
||
"rustc",
|
||
"--version",
|
||
])
|
||
.await
|
||
.is_ok();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn file_override_path() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(["rustup", "default", "stable"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "toolchain", "install", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
|
||
let toolchain_path = cx
|
||
.config
|
||
.rustupdir
|
||
.join("toolchains")
|
||
.join(format!("nightly-{}", this_host_tuple()));
|
||
let toolchain_file = cx.config.current_dir().join("rust-toolchain.toml");
|
||
raw::write_file(
|
||
&toolchain_file,
|
||
&format!("[toolchain]\npath='{}'", toolchain_path.to_str().unwrap()),
|
||
)
|
||
.unwrap();
|
||
|
||
cx.config
|
||
.expect(["rustc", "--version"])
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
1.3.0 (hash-nightly-2)
|
||
|
||
"#]])
|
||
.is_ok();
|
||
|
||
// Check that the toolchain has the right name
|
||
cx.config
|
||
.expect(["rustup", "show", "active-toolchain"])
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
[..]/toolchains/nightly-[HOST_TUPLE] (overridden by '[..]/rust-toolchain.toml')
|
||
|
||
"#]])
|
||
.is_ok();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn proxy_override_path() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(["rustup", "default", "stable"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "toolchain", "install", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
|
||
let toolchain_path = cx
|
||
.config
|
||
.rustupdir
|
||
.join("toolchains")
|
||
.join(format!("nightly-{}", this_host_tuple()));
|
||
let toolchain_file = cx.config.current_dir().join("rust-toolchain.toml");
|
||
raw::write_file(
|
||
&toolchain_file,
|
||
&format!("[toolchain]\npath='{}'", toolchain_path.to_str().unwrap()),
|
||
)
|
||
.unwrap();
|
||
|
||
cx.config
|
||
.expect(["cargo", "--call-rustc"])
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
1.3.0 (hash-nightly-2)
|
||
|
||
"#]])
|
||
.is_ok();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn file_override_path_relative_not_supported() {
|
||
let mut cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(["rustup", "default", "stable"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "toolchain", "install", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
|
||
let toolchain_path = cx
|
||
.config
|
||
.rustupdir
|
||
.join("toolchains")
|
||
.join(format!("nightly-{}", this_host_tuple()));
|
||
let toolchain_file = cx.config.current_dir().join("rust-toolchain.toml");
|
||
|
||
// Find shared prefix so we can determine a relative path
|
||
let mut p1 = toolchain_path.components().peekable();
|
||
let mut p2 = toolchain_file.components().peekable();
|
||
while let (Some(p1p), Some(p2p)) = (p1.peek(), p2.peek()) {
|
||
if p1p == p2p {
|
||
let _ = p1.next();
|
||
let _ = p2.next();
|
||
} else {
|
||
// The two paths diverge here
|
||
break;
|
||
}
|
||
}
|
||
let mut relative_path = PathBuf::new();
|
||
// NOTE: We skip 1 since we don't need to .. across the .toml file at the end of the path
|
||
for _ in p2.skip(1) {
|
||
relative_path.push("..");
|
||
}
|
||
for p in p1 {
|
||
relative_path.push(p);
|
||
}
|
||
assert!(relative_path.is_relative());
|
||
|
||
raw::write_file(
|
||
&toolchain_file,
|
||
&format!("[toolchain]\npath='{}'", relative_path.to_str().unwrap()),
|
||
)
|
||
.unwrap();
|
||
|
||
// Change into an ephemeral dir so that we test that the path is relative to the override
|
||
let ephemeral = cx.config.current_dir().join("ephemeral");
|
||
fs::create_dir_all(&ephemeral).unwrap();
|
||
|
||
let cx = cx.change_dir(&ephemeral);
|
||
cx.config
|
||
.expect(["rustc", "--version"])
|
||
.await
|
||
.with_stderr(snapbox::str![[r#"
|
||
error: relative path toolchain '[..]/toolchains/nightly-[HOST_TUPLE]'
|
||
|
||
"#]])
|
||
.is_err();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn file_override_path_no_options() {
|
||
let cx = CliTestContext::new(Scenario::None).await;
|
||
// Make a plausible-looking toolchain
|
||
let cwd = cx.config.current_dir();
|
||
let toolchain_path = cwd.join("ephemeral");
|
||
let toolchain_bin = toolchain_path.join("bin");
|
||
fs::create_dir_all(toolchain_bin).unwrap();
|
||
|
||
let toolchain_file = cwd.join("rust-toolchain.toml");
|
||
raw::write_file(
|
||
&toolchain_file,
|
||
"[toolchain]\npath=\"ephemeral\"\ntargets=[\"dummy\"]",
|
||
)
|
||
.unwrap();
|
||
|
||
cx.config
|
||
.expect(["rustc", "--version"])
|
||
.await
|
||
.with_stderr(snapbox::str![[r#"
|
||
error: toolchain options are ignored for path toolchain (ephemeral)
|
||
|
||
"#]])
|
||
.is_err();
|
||
|
||
raw::write_file(
|
||
&toolchain_file,
|
||
"[toolchain]\npath=\"ephemeral\"\ncomponents=[\"dummy\"]",
|
||
)
|
||
.unwrap();
|
||
|
||
cx.config
|
||
.expect(["rustc", "--version"])
|
||
.await
|
||
.with_stderr(snapbox::str![[r#"
|
||
error: toolchain options are ignored for path toolchain (ephemeral)
|
||
|
||
"#]])
|
||
.is_err();
|
||
|
||
raw::write_file(
|
||
&toolchain_file,
|
||
"[toolchain]\npath=\"ephemeral\"\nprofile=\"minimal\"",
|
||
)
|
||
.unwrap();
|
||
|
||
cx.config
|
||
.expect(["rustc", "--version"])
|
||
.await
|
||
.with_stderr(snapbox::str![[r#"
|
||
error: toolchain options are ignored for path toolchain (ephemeral)
|
||
|
||
"#]])
|
||
.is_err();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn file_override_path_xor_channel() {
|
||
let cx = CliTestContext::new(Scenario::None).await;
|
||
// Make a plausible-looking toolchain
|
||
let cwd = cx.config.current_dir();
|
||
let toolchain_path = cwd.join("ephemeral");
|
||
let toolchain_bin = toolchain_path.join("bin");
|
||
fs::create_dir_all(toolchain_bin).unwrap();
|
||
|
||
let toolchain_file = cwd.join("rust-toolchain.toml");
|
||
raw::write_file(
|
||
&toolchain_file,
|
||
"[toolchain]\npath=\"ephemeral\"\nchannel=\"nightly\"",
|
||
)
|
||
.unwrap();
|
||
|
||
cx.config
|
||
.expect(["rustc", "--version"])
|
||
.await
|
||
.with_stderr(snapbox::str![[r#"
|
||
[..]cannot specify both channel (nightly) and path (ephemeral) simultaneously[..]
|
||
"#]])
|
||
.is_err();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn file_override_subdir() {
|
||
let mut cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(["rustup", "default", "stable"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "toolchain", "install", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
|
||
cx.config
|
||
.expect(["rustc", "--version"])
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
1.1.0 (hash-stable-1.1.0)
|
||
|
||
"#]])
|
||
.is_ok();
|
||
|
||
let cwd = cx.config.current_dir();
|
||
let toolchain_file = cwd.join("rust-toolchain");
|
||
raw::write_file(&toolchain_file, "nightly").unwrap();
|
||
|
||
let subdir = cwd.join("subdir");
|
||
fs::create_dir_all(&subdir).unwrap();
|
||
let cx = cx.change_dir(&subdir);
|
||
cx.config
|
||
.expect(["rustc", "--version"])
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
1.3.0 (hash-nightly-2)
|
||
|
||
"#]])
|
||
.is_ok();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn file_override_with_archive() {
|
||
let mut cx = CliTestContext::new(Scenario::None).await;
|
||
|
||
{
|
||
let cx = cx.with_dist_dir(Scenario::SimpleV2);
|
||
cx.config
|
||
.expect(["rustup", "default", "stable"])
|
||
.await
|
||
.is_ok();
|
||
}
|
||
|
||
let cx = cx.with_dist_dir(Scenario::ArchivesV2_2015_01_01);
|
||
cx.config
|
||
.expect(["rustup", "toolchain", "install", "nightly-2015-01-01"])
|
||
.await
|
||
.is_ok();
|
||
|
||
cx.config
|
||
.expect(["rustc", "--version"])
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
1.1.0 (hash-stable-1.1.0)
|
||
|
||
"#]])
|
||
.is_ok();
|
||
|
||
let cwd = cx.config.current_dir();
|
||
let toolchain_file = cwd.join("rust-toolchain");
|
||
raw::write_file(&toolchain_file, "nightly-2015-01-01").unwrap();
|
||
|
||
cx.config
|
||
.expect(["rustc", "--version"])
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
1.2.0 (hash-nightly-1)
|
||
|
||
"#]])
|
||
.is_ok();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn file_override_toml_format_select_installed_toolchain() {
|
||
let mut cx = CliTestContext::new(Scenario::None).await;
|
||
|
||
{
|
||
let cx = cx.with_dist_dir(Scenario::SimpleV2);
|
||
cx.config
|
||
.expect(["rustup", "default", "stable"])
|
||
.await
|
||
.is_ok();
|
||
}
|
||
|
||
let cx = cx.with_dist_dir(Scenario::ArchivesV2_2015_01_01);
|
||
cx.config
|
||
.expect(["rustup", "toolchain", "install", "nightly-2015-01-01"])
|
||
.await
|
||
.is_ok();
|
||
|
||
cx.config
|
||
.expect(["rustc", "--version"])
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
1.1.0 (hash-stable-1.1.0)
|
||
|
||
"#]])
|
||
.is_ok();
|
||
|
||
let cwd = cx.config.current_dir();
|
||
let toolchain_file = cwd.join("rust-toolchain");
|
||
raw::write_file(
|
||
&toolchain_file,
|
||
r#"
|
||
[toolchain]
|
||
channel = "nightly-2015-01-01"
|
||
"#,
|
||
)
|
||
.unwrap();
|
||
|
||
cx.config
|
||
.expect(["rustc", "--version"])
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
1.2.0 (hash-nightly-1)
|
||
|
||
"#]])
|
||
.is_ok();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn file_override_toml_format_install_both_toolchain_and_components() {
|
||
let mut cx = CliTestContext::new(Scenario::None).await;
|
||
|
||
{
|
||
let cx = cx.with_dist_dir(Scenario::SimpleV2);
|
||
cx.config
|
||
.expect(["rustup", "default", "stable"])
|
||
.await
|
||
.is_ok();
|
||
}
|
||
|
||
let cx = cx.with_dist_dir(Scenario::ArchivesV2_2015_01_01);
|
||
cx.config
|
||
.expect(["rustc", "--version"])
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
1.1.0 (hash-stable-1.1.0)
|
||
|
||
"#]])
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "component", "list"])
|
||
.await
|
||
.is_ok()
|
||
.without_stdout("rust-src (installed)");
|
||
|
||
let cwd = cx.config.current_dir();
|
||
let toolchain_file = cwd.join("rust-toolchain");
|
||
raw::write_file(
|
||
&toolchain_file,
|
||
r#"
|
||
[toolchain]
|
||
channel = "nightly-2015-01-01"
|
||
components = [ "rust-src" ]
|
||
"#,
|
||
)
|
||
.unwrap();
|
||
|
||
cx.config
|
||
.expect(["rustup", "toolchain", "install"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustc", "--version"])
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
1.2.0 (hash-nightly-1)
|
||
|
||
"#]])
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "component", "list"])
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
...
|
||
rust-src (installed)
|
||
...
|
||
"#]])
|
||
.is_ok();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn file_override_toml_format_add_missing_components() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(["rustup", "default", "stable"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "component", "list"])
|
||
.await
|
||
.is_ok()
|
||
.without_stdout("rust-src (installed)");
|
||
|
||
let cwd = cx.config.current_dir();
|
||
let toolchain_file = cwd.join("rust-toolchain");
|
||
raw::write_file(
|
||
&toolchain_file,
|
||
r#"
|
||
[toolchain]
|
||
components = [ "rust-src" ]
|
||
"#,
|
||
)
|
||
.unwrap();
|
||
|
||
cx.config
|
||
.expect(["rustup", "toolchain", "install"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "component", "list"])
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
...
|
||
rust-src (installed)
|
||
...
|
||
"#]])
|
||
.is_ok();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn file_override_toml_format_add_missing_targets() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(["rustup", "default", "stable"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "component", "list"])
|
||
.await
|
||
.is_ok()
|
||
.without_stdout(&format!("{CROSS_ARCH2} (installed)"));
|
||
|
||
let cwd = cx.config.current_dir();
|
||
let toolchain_file = cwd.join("rust-toolchain");
|
||
raw::write_file(
|
||
&toolchain_file,
|
||
&format!(
|
||
r#"
|
||
[toolchain]
|
||
targets = [ "{CROSS_ARCH2}" ]
|
||
"#,
|
||
),
|
||
)
|
||
.unwrap();
|
||
|
||
cx.config
|
||
.expect(["rustup", "toolchain", "install"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "component", "list"])
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
...
|
||
rust-std-[CROSS_ARCH_II] (installed)
|
||
...
|
||
"#]])
|
||
.is_ok();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn file_override_toml_format_skip_invalid_component() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(["rustup", "default", "stable"])
|
||
.await
|
||
.is_ok();
|
||
|
||
let cwd = cx.config.current_dir();
|
||
let toolchain_file = cwd.join("rust-toolchain");
|
||
raw::write_file(
|
||
&toolchain_file,
|
||
r#"
|
||
[toolchain]
|
||
components = [ "rust-bongo" ]
|
||
"#,
|
||
)
|
||
.unwrap();
|
||
|
||
cx.config
|
||
.expect(&["rustup", "toolchain", "install"])
|
||
.await
|
||
.with_stderr(snapbox::str![[r#"
|
||
...
|
||
warn: skipping unavailable component rust-bongo
|
||
...
|
||
"#]])
|
||
.is_ok();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn file_override_toml_format_specify_profile() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(&["rustup", "set", "profile", "default"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(&["rustup", "default", "stable"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(&["rustup", "component", "list"])
|
||
.await
|
||
// The `rust-docs-[HOST_TUPLE]` component is installed.
|
||
.with_stdout(snapbox::str![[r#"
|
||
...
|
||
rust-docs-[HOST_TUPLE] (installed)
|
||
...
|
||
"#]])
|
||
.is_ok();
|
||
|
||
let cwd = cx.config.current_dir();
|
||
let toolchain_file = cwd.join("rust-toolchain");
|
||
raw::write_file(
|
||
&toolchain_file,
|
||
r#"
|
||
[toolchain]
|
||
profile = "minimal"
|
||
channel = "nightly"
|
||
"#,
|
||
)
|
||
.unwrap();
|
||
cx.config
|
||
.expect(&["rustup", "toolchain", "install"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(&["rustup", "component", "list"])
|
||
.await
|
||
// The `rust-docs-[HOST_TUPLE]` component is not installed.
|
||
.with_stdout(snapbox::str![[r#"
|
||
...
|
||
rust-docs-[HOST_TUPLE]
|
||
...
|
||
"#]])
|
||
.is_ok();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn default_profile_is_respected_with_rust_toolchain_file() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(&["rustup", "set", "profile", "minimal"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(&["rustup", "default", "stable"])
|
||
.await
|
||
.is_ok();
|
||
|
||
let cwd = cx.config.current_dir();
|
||
let toolchain_file = cwd.join("rust-toolchain");
|
||
raw::write_file(
|
||
&toolchain_file,
|
||
r#"
|
||
[toolchain]
|
||
channel = "nightly"
|
||
"#,
|
||
)
|
||
.unwrap();
|
||
cx.config
|
||
.expect(&["rustup", "toolchain", "install"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(&["rustup", "component", "list"])
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
...
|
||
rust-docs-[HOST_TUPLE]
|
||
...
|
||
"#]])
|
||
.is_ok();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn close_file_override_beats_far_directory_override() {
|
||
let mut cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(&["rustup", "default", "stable"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(&["rustup", "toolchain", "install", "beta"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(&["rustup", "toolchain", "install", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
|
||
cx.config
|
||
.expect(["rustup", "override", "set", "beta"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustc", "--version"])
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
1.2.0 (hash-beta-1.2.0)
|
||
|
||
"#]])
|
||
.is_ok();
|
||
|
||
let cwd = cx.config.current_dir();
|
||
|
||
let subdir = cwd.join("subdir");
|
||
fs::create_dir_all(&subdir).unwrap();
|
||
|
||
let toolchain_file = subdir.join("rust-toolchain");
|
||
raw::write_file(&toolchain_file, "nightly").unwrap();
|
||
|
||
let cx = cx.change_dir(&subdir);
|
||
cx.config
|
||
.expect(["rustc", "--version"])
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
1.3.0 (hash-nightly-2)
|
||
|
||
"#]])
|
||
.is_ok();
|
||
}
|
||
|
||
// Check that toolchain overrides have the correct priority.
|
||
#[tokio::test]
|
||
async fn override_order() {
|
||
let cx = CliTestContext::new(Scenario::ArchivesV2).await;
|
||
let host = this_host_tuple();
|
||
// give each override type a different toolchain
|
||
let default_tc = &format!("beta-2015-01-01-{host}");
|
||
let env_tc = &format!("stable-2015-01-01-{host}");
|
||
let dir_tc = &format!("beta-2015-01-02-{host}");
|
||
let file_tc = &format!("stable-2015-01-02-{host}");
|
||
let command_tc = &format!("nightly-2015-01-01-{host}");
|
||
cx.config
|
||
.expect(["rustup", "install", default_tc])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "install", env_tc])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "install", dir_tc])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "install", file_tc])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "install", command_tc])
|
||
.await
|
||
.is_ok();
|
||
|
||
// No default
|
||
cx.config
|
||
.expect(["rustup", "default", "none"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "show", "active-toolchain"])
|
||
.await
|
||
.with_stdout(snapbox::str![[""]])
|
||
.with_stderr(snapbox::str![[r#"
|
||
error: no active toolchain
|
||
|
||
"#]])
|
||
.is_err();
|
||
|
||
// Default
|
||
cx.config
|
||
.expect(["rustup", "default", default_tc])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "show", "active-toolchain"])
|
||
.await
|
||
.extend_redactions([("[DEFAULT_TC]", default_tc)])
|
||
.with_stdout(snapbox::str![[r#"
|
||
[DEFAULT_TC] (default)
|
||
|
||
"#]])
|
||
.is_ok();
|
||
|
||
// file > default
|
||
let toolchain_file = cx.config.current_dir().join("rust-toolchain.toml");
|
||
raw::write_file(
|
||
&toolchain_file,
|
||
&format!("[toolchain]\nchannel='{file_tc}'"),
|
||
)
|
||
.unwrap();
|
||
cx.config
|
||
.expect(["rustup", "show", "active-toolchain"])
|
||
.await
|
||
.extend_redactions([("[FILE_TC]", file_tc)])
|
||
.with_stdout(snapbox::str![[r#"
|
||
[FILE_TC] (overridden by '[..]/rust-toolchain.toml')
|
||
|
||
"#]])
|
||
.is_ok();
|
||
|
||
// dir override > file > default
|
||
cx.config
|
||
.expect(["rustup", "override", "set", dir_tc])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "show", "active-toolchain"])
|
||
.await
|
||
.extend_redactions([("[DIR_TC]", dir_tc)])
|
||
.with_stdout(snapbox::str![[r#"
|
||
[DIR_TC] (directory override for '[..]')
|
||
|
||
"#]])
|
||
.is_ok();
|
||
|
||
// env > dir override > file > default
|
||
cx.config
|
||
.expect_with_env(
|
||
["rustup", "show", "active-toolchain"],
|
||
[("RUSTUP_TOOLCHAIN", &**env_tc)],
|
||
)
|
||
.await
|
||
.extend_redactions([("[ENV_TC]", env_tc)])
|
||
.with_stdout(snapbox::str![[r#"
|
||
[ENV_TC] (overridden by environment variable RUSTUP_TOOLCHAIN)
|
||
|
||
"#]])
|
||
.is_ok();
|
||
|
||
// +toolchain > env > dir override > file > default
|
||
cx.config
|
||
.expect_with_env(
|
||
[
|
||
"rustup",
|
||
&format!("+{command_tc}"),
|
||
"show",
|
||
"active-toolchain",
|
||
],
|
||
[("RUSTUP_TOOLCHAIN", &**env_tc)],
|
||
)
|
||
.await
|
||
.extend_redactions([("[COMMAND_TC]", command_tc)])
|
||
.with_stdout(snapbox::str![[r#"
|
||
[COMMAND_TC] (overridden by +toolchain on the command line)
|
||
|
||
"#]])
|
||
.is_ok();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn rustup_toolchain_source_cli() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(&["rustup", "install", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["cargo", "+nightly", "--echo-rustup-toolchain-source"])
|
||
.await
|
||
.with_stderr(snapbox::str![[r#"
|
||
...
|
||
cli
|
||
|
||
"#]]);
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn rustup_toolchain_source_env() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect_with_env(
|
||
["cargo", "--echo-rustup-toolchain-source"],
|
||
[("RUSTUP_TOOLCHAIN", "nightly")],
|
||
)
|
||
.await
|
||
.with_stderr(snapbox::str![[r#"
|
||
...
|
||
env
|
||
|
||
"#]]);
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn rustup_toolchain_source_path_override() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(["rustup", "override", "set", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["cargo", "--echo-rustup-toolchain-source"])
|
||
.await
|
||
.with_stderr(snapbox::str![[r#"
|
||
...
|
||
path-override
|
||
|
||
"#]]);
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn rustup_toolchain_source_toolchain_file() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
let toolchain_file = cx.config.current_dir().join("rust-toolchain.toml");
|
||
raw::write_file(&toolchain_file, "[toolchain]\nchannel='nightly'").unwrap();
|
||
cx.config
|
||
.expect(["cargo", "--echo-rustup-toolchain-source"])
|
||
.await
|
||
.with_stderr(snapbox::str![[r#"
|
||
...
|
||
toolchain-file
|
||
|
||
"#]]);
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn rustup_toolchain_source_default() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(&["rustup", "default", "stable"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["cargo", "--echo-rustup-toolchain-source"])
|
||
.await
|
||
.with_stderr(snapbox::str![[r#"
|
||
...
|
||
default
|
||
|
||
"#]]);
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn directory_override_doesnt_need_to_exist_unless_it_is_selected() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(["rustup", "default", "stable"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "toolchain", "install", "beta"])
|
||
.await
|
||
.is_ok();
|
||
// not installing nightly
|
||
|
||
cx.config
|
||
.expect(["rustup", "override", "set", "beta"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustc", "--version"])
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
1.2.0 (hash-beta-1.2.0)
|
||
|
||
"#]])
|
||
.is_ok();
|
||
|
||
let cwd = cx.config.current_dir();
|
||
let toolchain_file = cwd.join("rust-toolchain");
|
||
raw::write_file(&toolchain_file, "nightly").unwrap();
|
||
|
||
cx.config
|
||
.expect(["rustc", "--version"])
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
1.2.0 (hash-beta-1.2.0)
|
||
|
||
"#]])
|
||
.is_ok();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn env_override_beats_file_override() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(["rustup", "default", "stable"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "toolchain", "install", "beta"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "toolchain", "install", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
|
||
let cwd = cx.config.current_dir();
|
||
let toolchain_file = cwd.join("rust-toolchain");
|
||
raw::write_file(&toolchain_file, "nightly").unwrap();
|
||
|
||
cx.config
|
||
.expect_with_env(["rustc", "--version"], [("RUSTUP_TOOLCHAIN", "beta")])
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
1.2.0 (hash-beta-1.2.0)
|
||
|
||
"#]])
|
||
.is_ok();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn plus_override_beats_file_override() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(["rustup", "default", "stable"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "toolchain", "install", "beta"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "toolchain", "install", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
|
||
let cwd = cx.config.current_dir();
|
||
let toolchain_file = cwd.join("rust-toolchain");
|
||
raw::write_file(&toolchain_file, "nightly").unwrap();
|
||
|
||
cx.config
|
||
.expect(["rustc", "+beta", "--version"])
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
1.2.0 (hash-beta-1.2.0)
|
||
|
||
"#]])
|
||
.is_ok();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn file_override_not_installed_custom() {
|
||
let cx = CliTestContext::new(Scenario::None).await;
|
||
let cwd = cx.config.current_dir();
|
||
let toolchain_file = cwd.join("rust-toolchain");
|
||
raw::write_file(&toolchain_file, "gumbo").unwrap();
|
||
|
||
cx.config
|
||
.expect(["rustup", "show", "active-toolchain"])
|
||
.await
|
||
.with_stderr(snapbox::str![[r#"
|
||
...
|
||
error: custom toolchain 'gumbo' specified in override file '[..]/rust-toolchain' is not installed
|
||
...
|
||
"#]])
|
||
.is_err();
|
||
cx.config
|
||
.expect(["rustc", "--version"])
|
||
.await
|
||
.with_stderr(snapbox::str![[r#"
|
||
...
|
||
error: custom toolchain 'gumbo' specified in override file '[..]/rust-toolchain' is not installed
|
||
...
|
||
"#]])
|
||
.is_err();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn file_override_not_installed_custom_toml() {
|
||
let cx = CliTestContext::new(Scenario::None).await;
|
||
let cwd = cx.config.current_dir();
|
||
let toolchain_file = cwd.join("rust-toolchain.toml");
|
||
raw::write_file(&toolchain_file, r#"toolchain.channel = "i-am-the-walrus""#).unwrap();
|
||
|
||
cx.config
|
||
.expect(["rustup", "show", "active-toolchain"])
|
||
.await
|
||
.with_stderr(snapbox::str![[r#"
|
||
...
|
||
error: custom toolchain 'i-am-the-walrus' specified in override file '[..]/rust-toolchain.toml' is not installed
|
||
...
|
||
"#]])
|
||
.is_err();
|
||
cx.config
|
||
.expect(["rustc", "--version"])
|
||
.await
|
||
.with_stderr(snapbox::str![[r#"
|
||
...
|
||
error: custom toolchain 'i-am-the-walrus' specified in override file '[..]/rust-toolchain.toml' is not installed
|
||
...
|
||
"#]])
|
||
.is_err();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn bad_file_override() {
|
||
let cx = CliTestContext::new(Scenario::None).await;
|
||
let cwd = cx.config.current_dir();
|
||
let toolchain_file = cwd.join("rust-toolchain");
|
||
// invalid name - cannot specify no toolchain in a toolchain file
|
||
raw::write_file(&toolchain_file, "none").unwrap();
|
||
|
||
cx.config
|
||
.expect(["rustc", "--version"])
|
||
.await
|
||
.with_stderr(snapbox::str![[r#"
|
||
...
|
||
error: invalid toolchain name detected in override file '[..]/rust-toolchain'
|
||
...
|
||
"#]])
|
||
.is_err();
|
||
}
|
||
|
||
// https://github.com/rust-lang/rustup/issues/4053
|
||
#[tokio::test]
|
||
async fn bad_file_override_with_manip() {
|
||
let cx = CliTestContext::new(Scenario::None).await;
|
||
let cwd = cx.config.current_dir();
|
||
let toolchain_file = cwd.join("rust-toolchain.toml");
|
||
raw::write_file(
|
||
&toolchain_file,
|
||
r#"toolchain.channel = "nightly', please install with 'curl --proto '=https' --tlsv1.2 -sSf https://sh.rust-toolchain.rs/ | sh -s -- --default-toolchain nightly -y""#,
|
||
).unwrap();
|
||
|
||
cx.config
|
||
.expect(["rustup", "show", "active-toolchain"])
|
||
.await
|
||
.with_stderr(snapbox::str![[r#"
|
||
...
|
||
error: invalid toolchain name detected in override file '[..]/rust-toolchain.toml'
|
||
...
|
||
"#]])
|
||
.is_err();
|
||
cx.config
|
||
.expect(["rustc", "--version"])
|
||
.await
|
||
.with_stderr(snapbox::str![[r#"
|
||
...
|
||
error: invalid toolchain name detected in override file '[..]/rust-toolchain.toml'
|
||
...
|
||
"#]])
|
||
.is_err();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn valid_override_settings() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
let cwd = cx.config.current_dir();
|
||
let toolchain_file = cwd.join("rust-toolchain");
|
||
cx.config
|
||
.expect(&["rustup", "default", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
let nightly_with_host = format!("nightly-{}", this_host_tuple());
|
||
raw::write_file(&toolchain_file, "nightly").unwrap();
|
||
cx.config.expect(&["rustc", "--version"]).await.is_ok();
|
||
// Special case: same version as is installed is permitted.
|
||
raw::write_file(&toolchain_file, &nightly_with_host).unwrap();
|
||
cx.config.expect(&["rustc", "--version"]).await.is_ok();
|
||
let fullpath = cx
|
||
.config
|
||
.rustupdir
|
||
.clone()
|
||
.join("toolchains")
|
||
.join(&nightly_with_host);
|
||
cx.config
|
||
.expect(&[
|
||
"rustup",
|
||
"toolchain",
|
||
"link",
|
||
"system",
|
||
&format!("{}", fullpath.display()),
|
||
])
|
||
.await
|
||
.is_ok();
|
||
raw::write_file(&toolchain_file, "system").unwrap();
|
||
cx.config.expect(&["rustc", "--version"]).await.is_ok();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn file_override_with_target_info() {
|
||
// Target info is not portable between machines, so we reject toolchain
|
||
// files that include it.
|
||
let cx = CliTestContext::new(Scenario::None).await;
|
||
let cwd = cx.config.current_dir();
|
||
let toolchain_file = cwd.join("rust-toolchain");
|
||
raw::write_file(&toolchain_file, "nightly-x86_64-unknown-linux-gnu").unwrap();
|
||
|
||
cx.config
|
||
.expect(["rustc", "--version"])
|
||
.await
|
||
.remove_redactions(["[HOST_TUPLE]"])
|
||
.with_stderr(snapbox::str![[r#"
|
||
...
|
||
error: target tuple in channel name 'nightly-x86_64-unknown-linux-gnu'
|
||
...
|
||
"#]])
|
||
.is_err();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn docs_with_path() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(&["rustup", "default", "stable"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(&["rustup", "toolchain", "install", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
|
||
cx.config
|
||
.expect(["rustup", "doc", "--path"])
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
[..]/toolchains/stable-[HOST_TUPLE]/share/doc/rust/html/index.html
|
||
|
||
"#]])
|
||
.is_ok();
|
||
|
||
cx.config
|
||
.expect(["rustup", "doc", "--path", "--toolchain", "nightly"])
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
[..]/toolchains/nightly-[HOST_TUPLE]/share/doc/rust/html/index.html
|
||
|
||
"#]])
|
||
.is_ok();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn docs_topical_with_path() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(["rustup", "default", "stable"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "toolchain", "install", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
|
||
for (args, path) in topical_doc_data::test_cases() {
|
||
let mut cmd = vec!["rustup", "doc", "--path"];
|
||
cmd.extend(args);
|
||
cx.config
|
||
.expect(cmd)
|
||
.await
|
||
.extend_redactions([("[PATH]", path)])
|
||
.is_ok()
|
||
.with_stdout(snapbox::str![[r#"
|
||
[..]/toolchains/stable-[HOST_TUPLE]/[PATH]
|
||
|
||
"#]])
|
||
.with_stderr(snapbox::str![""]);
|
||
}
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn docs_missing() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(["rustup", "set", "profile", "minimal"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "default", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "doc"])
|
||
.await
|
||
.with_stderr(snapbox::str![[r#"
|
||
info: `rust-docs` not installed in toolchain `nightly-[HOST_TUPLE]`
|
||
help: run `rustup component add --toolchain nightly-[HOST_TUPLE] rust-docs` to install it
|
||
error: unable to view documentation which is not installed
|
||
|
||
"#]])
|
||
.is_err();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn docs_custom() {
|
||
let cx = CliTestContext::new(Scenario::None).await;
|
||
let path = cx.config.customdir.join("custom-1");
|
||
let path = path.to_string_lossy();
|
||
cx.config
|
||
.expect(["rustup", "toolchain", "link", "custom", &path])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "default", "custom"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "doc", "--path"])
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
[..]/toolchains/custom/share/doc/rust/html/index.html
|
||
|
||
"#]])
|
||
.is_ok();
|
||
}
|
||
|
||
#[cfg(unix)]
|
||
#[tokio::test]
|
||
async fn non_utf8_arg() {
|
||
use std::ffi::OsStr;
|
||
use std::os::unix::ffi::OsStrExt;
|
||
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(["rustup", "default", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect_with_env(
|
||
[
|
||
OsStr::new("rustc"),
|
||
OsStr::new("--echo-args"),
|
||
OsStr::new("echoed non-utf8 arg:"),
|
||
OsStr::from_bytes(b"\xc3\x28"),
|
||
],
|
||
[("RUST_BACKTRACE", "1")],
|
||
)
|
||
.await
|
||
.with_stderr(snapbox::str![[r#"
|
||
echoed non-utf8 arg:
|
||
...
|
||
"#]]);
|
||
}
|
||
|
||
#[cfg(windows)]
|
||
#[tokio::test]
|
||
async fn non_utf8_arg() {
|
||
use std::ffi::OsString;
|
||
use std::os::windows::ffi::OsStringExt;
|
||
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(["rustup", "default", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect_with_env(
|
||
[
|
||
OsString::from("rustc"),
|
||
OsString::from("--echo-args"),
|
||
OsString::from("echoed non-utf8 arg:"),
|
||
OsString::from_wide(&[0xd801, 0xd801]),
|
||
],
|
||
[("RUST_BACKTRACE", "1")],
|
||
)
|
||
.await
|
||
.with_stderr(snapbox::str![[r#"
|
||
echoed non-utf8 arg:
|
||
...
|
||
"#]]);
|
||
}
|
||
|
||
#[cfg(unix)]
|
||
#[tokio::test]
|
||
async fn non_utf8_toolchain() {
|
||
use std::ffi::OsStr;
|
||
use std::os::unix::ffi::OsStrExt;
|
||
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(["rustup", "default", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect_with_env(
|
||
[OsStr::new("rustc"), OsStr::from_bytes(b"+\xc3\x28")],
|
||
[("RUST_BACKTRACE", "1")],
|
||
)
|
||
.await
|
||
.with_stderr(snapbox::str![[r#"
|
||
...
|
||
error: toolchain '<27>(' is not installed
|
||
...
|
||
"#]]);
|
||
}
|
||
|
||
#[cfg(windows)]
|
||
#[tokio::test]
|
||
async fn non_utf8_toolchain() {
|
||
use std::ffi::OsString;
|
||
use std::os::windows::ffi::OsStringExt;
|
||
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(["rustup", "default", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect_with_env(
|
||
[
|
||
OsString::from("rustc"),
|
||
OsString::from_wide(&[u16::from(b'+'), 0xd801, 0xd801]),
|
||
],
|
||
[("RUST_BACKTRACE", "1")],
|
||
)
|
||
.await
|
||
.with_stderr(snapbox::str![[r#"
|
||
...
|
||
error: toolchain '<27><>' is not installed
|
||
...
|
||
"#]]);
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn check_host_goes_away() {
|
||
let mut cx = CliTestContext::new(Scenario::None).await;
|
||
|
||
{
|
||
let cx = cx.with_dist_dir(Scenario::HostGoesMissingBefore);
|
||
cx.config
|
||
.expect(["rustup", "default", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
}
|
||
|
||
let cx = cx.with_dist_dir(Scenario::HostGoesMissingAfter);
|
||
cx.config
|
||
.expect(&["rustup", "update", "nightly"])
|
||
.await
|
||
.with_stderr(snapbox::str![[r#"
|
||
...
|
||
error: target '[HOST_TUPLE]' not found in channel[..]
|
||
...
|
||
"#]])
|
||
.is_err();
|
||
}
|
||
|
||
#[cfg(unix)]
|
||
#[tokio::test]
|
||
async fn check_unix_settings_fallback() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
// No default toolchain specified yet
|
||
cx.config
|
||
.expect(["rustup", "default"])
|
||
.await
|
||
.with_stdout(snapbox::str![[""]])
|
||
.with_stderr(snapbox::str![[r#"
|
||
error: no default toolchain is configured
|
||
|
||
"#]])
|
||
.is_err();
|
||
|
||
// Default toolchain specified in fallback settings file
|
||
let mock_settings_file = cx.config.current_dir().join("mock_fallback_settings.toml");
|
||
raw::write_file(
|
||
&mock_settings_file,
|
||
&format!("default_toolchain = 'nightly-{}'", this_host_tuple()),
|
||
)
|
||
.unwrap();
|
||
|
||
cx.config
|
||
.expect_with_env(
|
||
["rustup", "default"],
|
||
[(
|
||
"RUSTUP_OVERRIDE_UNIX_FALLBACK_SETTINGS",
|
||
&*mock_settings_file.display().to_string(),
|
||
)],
|
||
)
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
nightly-[HOST_TUPLE] (default)
|
||
|
||
"#]])
|
||
.is_ok();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn deny_incompatible_toolchain_install() {
|
||
let cx = CliTestContext::new(Scenario::MultiHost).await;
|
||
let arch = MULTI_ARCH1;
|
||
cx.config
|
||
.expect(["rustup", "toolchain", "install", &format!("nightly-{arch}")])
|
||
.await
|
||
.extend_redactions([("[ARCH]", arch)])
|
||
.with_stderr(snapbox::str![[r#"
|
||
error: toolchain 'nightly-[ARCH]' may not be able to run on this system
|
||
note: to build software for that platform, try `rustup target add [ARCH]` instead
|
||
note: add the `--force-non-host` flag to install the toolchain anyway
|
||
|
||
"#]])
|
||
.is_err();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn deny_incompatible_toolchain_default() {
|
||
let cx = CliTestContext::new(Scenario::MultiHost).await;
|
||
let arch = MULTI_ARCH1;
|
||
cx.config
|
||
.expect(["rustup", "default", &format!("nightly-{arch}")])
|
||
.await
|
||
.extend_redactions([("[ARCH]", arch)])
|
||
.with_stderr(snapbox::str![[r#"
|
||
error: toolchain 'nightly-[ARCH]' may not be able to run on this system
|
||
note: to build software for that platform, try `rustup target add [ARCH]` instead
|
||
note: add the `--force-non-host` flag to install the toolchain anyway
|
||
|
||
"#]])
|
||
.is_err();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn dont_warn_on_partial_build() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
let arch = this_host_tuple().split_once('-').unwrap().0.to_owned();
|
||
cx.config
|
||
.expect(["rustup", "toolchain", "install", &format!("nightly-{arch}")])
|
||
.await
|
||
.with_stderr(snapbox::str![[r#"
|
||
...
|
||
info: syncing channel updates for nightly-[HOST_TUPLE]
|
||
...
|
||
"#]])
|
||
.is_ok()
|
||
.without_stderr(&format!(
|
||
"toolchain 'nightly-{arch}' may not be able to run on this system."
|
||
));
|
||
}
|
||
|
||
/// Checks that `rust-toolchain.toml` files are considered
|
||
#[tokio::test]
|
||
async fn rust_toolchain_toml() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(["rustc", "--version"])
|
||
.await
|
||
.with_stderr(snapbox::str![[r#"
|
||
...
|
||
error: rustup could not choose a version of rustc to run, because one wasn't specified explicitly, and no default is configured.
|
||
...
|
||
"#]])
|
||
.is_err();
|
||
|
||
let cwd = cx.config.current_dir();
|
||
let toolchain_file = cwd.join("rust-toolchain.toml");
|
||
raw::write_file(&toolchain_file, "[toolchain]\nchannel = \"nightly\"").unwrap();
|
||
cx.config
|
||
.expect(["rustup", "toolchain", "install"])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustc", "--version"])
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
1.3.0 (hash-nightly-2)
|
||
|
||
"#]])
|
||
.is_ok();
|
||
}
|
||
|
||
/// Ensures that `rust-toolchain.toml` files (with `.toml` extension) only allow TOML contents
|
||
#[tokio::test]
|
||
async fn only_toml_in_rust_toolchain_toml() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
let cwd = cx.config.current_dir();
|
||
let toolchain_file = cwd.join("rust-toolchain.toml");
|
||
raw::write_file(&toolchain_file, "nightly").unwrap();
|
||
|
||
cx.config
|
||
.expect(["rustc", "--version"])
|
||
.await
|
||
.extend_redactions([("[CWD]", &cwd)])
|
||
.with_stderr(snapbox::str![[r#"
|
||
...
|
||
error: could not parse override file: '[CWD]/rust-toolchain.toml'[..]
|
||
...
|
||
"#]])
|
||
.is_err();
|
||
}
|
||
|
||
/// Checks that a warning occurs if both `rust-toolchain` and `rust-toolchain.toml` files exist
|
||
#[tokio::test]
|
||
async fn warn_on_duplicate_rust_toolchain_file() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
let cwd = cx.config.current_dir();
|
||
let toolchain_file_1 = cwd.join("rust-toolchain");
|
||
raw::write_file(&toolchain_file_1, "stable").unwrap();
|
||
let toolchain_file_2 = cwd.join("rust-toolchain.toml");
|
||
raw::write_file(&toolchain_file_2, "[toolchain]").unwrap();
|
||
|
||
cx.config
|
||
.expect(&["rustup", "toolchain", "install"])
|
||
.await
|
||
.extend_redactions([("[CWD]", &cwd.canonicalize().unwrap())])
|
||
.with_stderr(snapbox::str![[r#"
|
||
...
|
||
warn: both [CWD]/rust-toolchain and [CWD]/rust-toolchain.toml exist; using contents of [CWD]/rust-toolchain
|
||
...
|
||
"#]])
|
||
.is_ok();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn custom_toolchain_with_components_toolchains_profile_does_not_err() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
|
||
let cwd = cx.config.current_dir();
|
||
let toolchain_file = cwd.join("rust-toolchain.toml");
|
||
|
||
// install a toolchain so we can make a custom toolchain that links to it
|
||
cx.config
|
||
.expect(&[
|
||
"rustup",
|
||
"toolchain",
|
||
"install",
|
||
"nightly",
|
||
"--profile=minimal",
|
||
"--component=cargo",
|
||
])
|
||
.await
|
||
.with_stderr(snapbox::str![[r#"
|
||
info: syncing channel updates for nightly-[HOST_TUPLE]
|
||
info: latest update on 2015-01-02 for version 1.3.0 (hash-nightly-2)
|
||
info: downloading 2 components
|
||
info: default toolchain set to nightly-[HOST_TUPLE]
|
||
|
||
"#]])
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "+nightly", "component", "list", "--installed"])
|
||
.await
|
||
.is_ok()
|
||
.with_stdout(snapbox::str![[r#"
|
||
cargo-[HOST_TUPLE]
|
||
rustc-[HOST_TUPLE]
|
||
|
||
"#]]);
|
||
|
||
// link the toolchain
|
||
let toolchains = cx.config.rustupdir.join("toolchains");
|
||
raw::symlink_dir(
|
||
&toolchains.join(format!("nightly-{}", this_host_tuple())),
|
||
&toolchains.join("my-custom"),
|
||
)
|
||
.expect("failed to symlink");
|
||
|
||
raw::write_file(
|
||
&toolchain_file,
|
||
r#"
|
||
[toolchain]
|
||
channel = "my-custom"
|
||
components = ["rustc-dev"]
|
||
targets = ["x86_64-unknown-linux-gnu"]
|
||
profile = "minimal"
|
||
"#,
|
||
)
|
||
.unwrap();
|
||
|
||
cx.config
|
||
.expect(&["rustup", "show", "active-toolchain"])
|
||
.await
|
||
.extend_redactions([("[CWD]", &cwd)])
|
||
.with_stdout(snapbox::str![[r#"
|
||
my-custom (overridden by '[CWD]/rust-toolchain.toml')
|
||
|
||
"#]])
|
||
.is_ok();
|
||
|
||
cx.config
|
||
.expect(&["rustc", "--version"])
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
1.3.0 (hash-nightly-2)
|
||
|
||
"#]])
|
||
.is_ok();
|
||
|
||
cx.config
|
||
.expect(&["cargo", "--version"])
|
||
.await
|
||
.with_stdout(snapbox::str![[r#"
|
||
1.3.0 (hash-nightly-2)
|
||
|
||
"#]])
|
||
.is_ok();
|
||
}
|
||
|
||
// Issue #4251
|
||
#[tokio::test]
|
||
async fn show_custom_toolchain() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(&["rustup", "default", "stable"])
|
||
.await
|
||
.is_ok();
|
||
let stable_path = cx
|
||
.config
|
||
.rustupdir
|
||
.join("toolchains")
|
||
.join(format!("stable-{}", this_host_tuple()));
|
||
cx.config
|
||
.expect([
|
||
"rustup",
|
||
"toolchain",
|
||
"link",
|
||
"stuff",
|
||
&stable_path.to_string_lossy(),
|
||
])
|
||
.await
|
||
.is_ok();
|
||
cx.config
|
||
.expect(["rustup", "+stuff", "show"])
|
||
.await
|
||
.extend_redactions([("[RUSTUP_DIR]", cx.config.rustupdir.to_string())])
|
||
.with_stdout(snapbox::str![[r#"
|
||
Default host: [HOST_TUPLE]
|
||
rustup home: [RUSTUP_DIR]
|
||
|
||
installed toolchains
|
||
--------------------
|
||
stable-[HOST_TUPLE] (default)
|
||
stuff (active)
|
||
|
||
active toolchain
|
||
----------------
|
||
name: stuff
|
||
active because: overridden by +toolchain on the command line
|
||
installed targets:
|
||
[HOST_TUPLE]
|
||
|
||
"#]])
|
||
.with_stderr(snapbox::str![[""]])
|
||
.is_ok();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn show_custom_toolchain_without_components_file() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
cx.config
|
||
.expect(["rustup", "default", "stable"])
|
||
.await
|
||
.is_ok();
|
||
let stable_path = cx
|
||
.config
|
||
.rustupdir
|
||
.join("toolchains")
|
||
.join(format!("stable-{}", this_host_tuple()));
|
||
cx.config
|
||
.expect([
|
||
"rustup",
|
||
"toolchain",
|
||
"link",
|
||
"stuff",
|
||
&stable_path.to_string_lossy(),
|
||
])
|
||
.await
|
||
.is_ok();
|
||
|
||
let components_file = stable_path.join("lib").join("rustlib").join("components");
|
||
fs::remove_file(&components_file).unwrap();
|
||
cx.config
|
||
.expect(["rustup", "+stuff", "show"])
|
||
.await
|
||
.extend_redactions([("[RUSTUP_DIR]", cx.config.rustupdir.to_string())])
|
||
.with_stdout(snapbox::str![[r#"
|
||
Default host: [HOST_TUPLE]
|
||
rustup home: [RUSTUP_DIR]
|
||
|
||
installed toolchains
|
||
--------------------
|
||
stable-[HOST_TUPLE] (default)
|
||
stuff (active)
|
||
|
||
active toolchain
|
||
----------------
|
||
name: stuff
|
||
active because: overridden by +toolchain on the command line
|
||
installed targets:
|
||
|
||
"#]])
|
||
.with_stderr(snapbox::str![[""]])
|
||
.is_ok();
|
||
}
|
||
|
||
#[tokio::test]
|
||
async fn missing_manifest_shows_reinstall_help() {
|
||
let cx = CliTestContext::new(Scenario::SimpleV2).await;
|
||
|
||
cx.config
|
||
.expect(["rustup", "toolchain", "install", "nightly"])
|
||
.await
|
||
.is_ok();
|
||
|
||
let manifest_path = cx
|
||
.config
|
||
.rustupdir
|
||
.join("toolchains")
|
||
.join(format!("nightly-{}", this_host_tuple()))
|
||
.join("lib")
|
||
.join("rustlib")
|
||
.join("multirust-channel-manifest.toml");
|
||
|
||
fs::remove_file(&manifest_path).unwrap();
|
||
|
||
cx.config
|
||
.expect(["rustup", "component", "list", "--toolchain", "nightly"])
|
||
.await
|
||
.with_stderr(snapbox::str![[r#"
|
||
error: missing manifest in toolchain 'nightly-[HOST_TUPLE]'
|
||
help: this may happen if the toolchain installation was interrupted
|
||
help: try reinstalling or updating the toolchain
|
||
|
||
"#]])
|
||
.is_err();
|
||
}
|