diff --git a/src/test/clitools.rs b/src/test/clitools.rs index 80f46db499..1b6dbd6e27 100644 --- a/src/test/clitools.rs +++ b/src/test/clitools.rs @@ -101,6 +101,15 @@ impl Assert { self } + pub fn remove_redactions(&mut self, vars: impl IntoIterator) -> &mut Self { + for var in vars { + self.redactions + .remove(var) + .expect("invalid redactions detected"); + } + self + } + /// Asserts that the command exited with an ok status. pub fn is_ok(&self) -> &Self { assert!(self.output.ok); @@ -224,20 +233,32 @@ impl Config { /// Returns an [`Assert`] object to check the output of running the command /// specified by `args` under the default environment. #[must_use] - pub async fn expect(&self, args: impl AsRef<[&str]>) -> Assert { + pub async fn expect + Clone + Debug>(&self, args: impl AsRef<[S]>) -> Assert { self.expect_with_env(args, &[]).await } /// Returns an [`Assert`] object to check the output of running the command /// specified by `args` and under the environment specified by `env`. #[must_use] - pub async fn expect_with_env( + pub async fn expect_with_env + Clone + Debug>( &self, - args: impl AsRef<[&str]>, + args: impl AsRef<[S]>, env: impl AsRef<[(&str, &str)]>, ) -> Assert { - let args = args.as_ref(); - let output = self.run(args[0], &args[1..], env.as_ref()).await; + let (program, args) = args + .as_ref() + .split_first() + .expect("args should not be empty"); + let output = self + .run( + program + .as_ref() + .to_str() + .expect("invalid UTF-8 in program name"), + args, + env.as_ref(), + ) + .await; Assert::new(output) } diff --git a/tests/suite/cli_rustup.rs b/tests/suite/cli_rustup.rs index d4c64a18ba..408d01a1bb 100644 --- a/tests/suite/cli_rustup.rs +++ b/tests/suite/cli_rustup.rs @@ -1,47 +1,39 @@ //! Test cases for new rustup UI -#![allow(deprecated)] - use std::fs; -use std::path::{MAIN_SEPARATOR, PathBuf}; +use std::path::PathBuf; use std::{env::consts::EXE_SUFFIX, path::Path}; -use rustup::for_host; use rustup::test::{ CROSS_ARCH1, CROSS_ARCH2, CliTestContext, MULTI_ARCH1, Scenario, this_host_triple, topical_doc_data, }; use rustup::utils::raw; -macro_rules! for_host_and_home { - ($config:expr, $s:tt $($arg:tt)*) => { - &format!($s, this_host_triple(), $config.rustupdir $($arg)*) - }; -} - #[tokio::test] async fn rustup_stable() { let mut cx = CliTestContext::new(Scenario::None).await; { - let mut cx = cx.with_dist_dir(Scenario::ArchivesV2_2015_01_01); + let cx = cx.with_dist_dir(Scenario::ArchivesV2_2015_01_01); cx.config - .expect_ok(&["rustup", "toolchain", "add", "stable"]) - .await; + .expect(["rustup", "toolchain", "add", "stable"]) + .await + .is_ok(); } - let mut cx = cx.with_dist_dir(Scenario::SimpleV2); + let cx = cx.with_dist_dir(Scenario::SimpleV2); cx.config - .expect_ok_ex( - &["rustup", "update"], - for_host!( - r" - stable-{0} updated - 1.1.0 (hash-stable-1.1.0) (from 1.0.0 (hash-stable-1.0.0)) + .expect(["rustup", "update"]) + .await + .with_stdout(snapbox::str![[r#" -" - ), - for_host!( - r"info: syncing channel updates for 'stable-{0}' + stable-[HOST_TRIPLE] 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_TRIPLE]' info: latest update on 2015-01-02, rust version 1.1.0 (hash-stable-1.1.0) info: downloading component 'cargo' info: downloading component 'rust-docs' @@ -56,10 +48,9 @@ info: installing component 'rust-docs' info: installing component 'rust-std' info: installing component 'rustc' info: cleaning up downloads & tmp directories -" - ), - ) - .await; + +"#]]) + .is_ok(); } #[tokio::test] @@ -67,47 +58,49 @@ async fn rustup_stable_quiet() { let mut cx = CliTestContext::new(Scenario::None).await; { - let mut cx = cx.with_dist_dir(Scenario::ArchivesV2_2015_01_01); + let cx = cx.with_dist_dir(Scenario::ArchivesV2_2015_01_01); cx.config - .expect_ok(&["rustup", "--quiet", "update", "stable"]) - .await; + .expect(["rustup", "--quiet", "update", "stable"]) + .await + .is_ok(); } - let mut cx = cx.with_dist_dir(Scenario::SimpleV2); + let cx = cx.with_dist_dir(Scenario::SimpleV2); cx.config - .expect_ok_ex( - &["rustup", "--quiet", "update"], - for_host!( - r" - stable-{0} updated - 1.1.0 (hash-stable-1.1.0) (from 1.0.0 (hash-stable-1.0.0)) + .expect(["rustup", "--quiet", "update"]) + .await + .with_stdout(snapbox::str![[r#" -" - ), - "", - ) - .await; + stable-[HOST_TRIPLE] 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 mut cx = CliTestContext::new(Scenario::ArchivesV2_2015_01_01).await; - cx.config.expect_ok(&["rustup", "update", "stable"]).await; - cx.config - .expect_ok_ex( - &["rustup", "update"], - for_host!( - r" - stable-{0} unchanged - 1.0.0 (hash-stable-1.0.0) - -" - ), - for_host!( - r"info: syncing channel updates for 'stable-{0}' + 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_TRIPLE] unchanged - 1.0.0 (hash-stable-1.0.0) + + +"#]]) + .with_stderr(snapbox::str![[r#" +info: syncing channel updates for 'stable-[HOST_TRIPLE]' info: cleaning up downloads & tmp directories -" - ), - ) - .await; + +"#]]) + .is_ok(); } #[tokio::test] @@ -115,26 +108,27 @@ async fn rustup_all_channels() { let mut cx = CliTestContext::new(Scenario::None).await; { - let mut cx = cx.with_dist_dir(Scenario::ArchivesV2_2015_01_01); + let cx = cx.with_dist_dir(Scenario::ArchivesV2_2015_01_01); cx.config - .expect_ok(&["rustup", "toolchain", "add", "stable", "beta", "nightly"]) - .await; + .expect(["rustup", "toolchain", "add", "stable", "beta", "nightly"]) + .await + .is_ok(); } - let mut cx = cx.with_dist_dir(Scenario::SimpleV2); + let cx = cx.with_dist_dir(Scenario::SimpleV2); cx.config - .expect_ok_ex( - &["rustup", "update"], - for_host!( - r" - stable-{0} updated - 1.1.0 (hash-stable-1.1.0) (from 1.0.0 (hash-stable-1.0.0)) - beta-{0} updated - 1.2.0 (hash-beta-1.2.0) (from 1.1.0 (hash-beta-1.1.0)) - nightly-{0} updated - 1.3.0 (hash-nightly-2) (from 1.2.0 (hash-nightly-1)) + .expect(["rustup", "update"]) + .await + .with_stdout(snapbox::str![[r#" + + stable-[HOST_TRIPLE] updated - 1.1.0 (hash-stable-1.1.0) (from 1.0.0 (hash-stable-1.0.0)) + beta-[HOST_TRIPLE] updated - 1.2.0 (hash-beta-1.2.0) (from 1.1.0 (hash-beta-1.1.0)) + nightly-[HOST_TRIPLE] updated - 1.3.0 (hash-nightly-2) (from 1.2.0 (hash-nightly-1)) + -" - ), - for_host!( - r"info: syncing channel updates for 'stable-{0}' +"#]]) + .with_stderr(snapbox::str![[r#" +info: syncing channel updates for 'stable-[HOST_TRIPLE]' info: latest update on 2015-01-02, rust version 1.1.0 (hash-stable-1.1.0) info: downloading component 'cargo' info: downloading component 'rust-docs' @@ -148,7 +142,7 @@ info: installing component 'cargo' info: installing component 'rust-docs' info: installing component 'rust-std' info: installing component 'rustc' -info: syncing channel updates for 'beta-{0}' +info: syncing channel updates for 'beta-[HOST_TRIPLE]' info: latest update on 2015-01-02, rust version 1.2.0 (hash-beta-1.2.0) info: downloading component 'cargo' info: downloading component 'rust-docs' @@ -162,7 +156,7 @@ info: installing component 'cargo' info: installing component 'rust-docs' info: installing component 'rust-std' info: installing component 'rustc' -info: syncing channel updates for 'nightly-{0}' +info: syncing channel updates for 'nightly-[HOST_TRIPLE]' info: latest update on 2015-01-02, rust version 1.3.0 (hash-nightly-2) info: downloading component 'cargo' info: downloading component 'rust-docs' @@ -177,10 +171,9 @@ info: installing component 'rust-docs' info: installing component 'rust-std' info: installing component 'rustc' info: cleaning up downloads & tmp directories -" - ), - ) - .await; + +"#]]) + .is_ok(); } #[tokio::test] @@ -188,27 +181,28 @@ async fn rustup_some_channels_up_to_date() { let mut cx = CliTestContext::new(Scenario::None).await; { - let mut cx = cx.with_dist_dir(Scenario::ArchivesV2_2015_01_01); + let cx = cx.with_dist_dir(Scenario::ArchivesV2_2015_01_01); cx.config - .expect_ok(&["rustup", "toolchain", "add", "stable", "beta", "nightly"]) - .await; + .expect(["rustup", "toolchain", "add", "stable", "beta", "nightly"]) + .await + .is_ok(); } - let mut cx = cx.with_dist_dir(Scenario::SimpleV2); - cx.config.expect_ok(&["rustup", "update", "beta"]).await; - cx.config - .expect_ok_ex( - &["rustup", "update"], - for_host!( - r" - stable-{0} updated - 1.1.0 (hash-stable-1.1.0) (from 1.0.0 (hash-stable-1.0.0)) - beta-{0} unchanged - 1.2.0 (hash-beta-1.2.0) - nightly-{0} updated - 1.3.0 (hash-nightly-2) (from 1.2.0 (hash-nightly-1)) - -" - ), - for_host!( - r"info: syncing channel updates for 'stable-{0}' + 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_TRIPLE] updated - 1.1.0 (hash-stable-1.1.0) (from 1.0.0 (hash-stable-1.0.0)) + beta-[HOST_TRIPLE] unchanged - 1.2.0 (hash-beta-1.2.0) + nightly-[HOST_TRIPLE] 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_TRIPLE]' info: latest update on 2015-01-02, rust version 1.1.0 (hash-stable-1.1.0) info: downloading component 'cargo' info: downloading component 'rust-docs' @@ -222,8 +216,8 @@ info: installing component 'cargo' info: installing component 'rust-docs' info: installing component 'rust-std' info: installing component 'rustc' -info: syncing channel updates for 'beta-{0}' -info: syncing channel updates for 'nightly-{0}' +info: syncing channel updates for 'beta-[HOST_TRIPLE]' +info: syncing channel updates for 'nightly-[HOST_TRIPLE]' info: latest update on 2015-01-02, rust version 1.3.0 (hash-nightly-2) info: downloading component 'cargo' info: downloading component 'rust-docs' @@ -238,40 +232,40 @@ info: installing component 'rust-docs' info: installing component 'rust-std' info: installing component 'rustc' info: cleaning up downloads & tmp directories -" - ), - ) - .await; + +"#]]) + .is_ok(); } #[tokio::test] async fn rustup_no_channels() { - let mut cx = CliTestContext::new(Scenario::SimpleV2).await; + let cx = CliTestContext::new(Scenario::SimpleV2).await; cx.config - .expect_ok_ex( - &["rustup", "update"], - r"", - r"info: no updatable toolchains installed + .expect(["rustup", "update"]) + .await + .with_stdout(snapbox::str![""]) + .with_stderr(snapbox::str![[r#" +info: no updatable toolchains installed info: cleaning up downloads & tmp directories -", - ) - .await; + +"#]]) + .is_ok(); } #[tokio::test] async fn default() { - let mut cx = CliTestContext::new(Scenario::SimpleV2).await; + let cx = CliTestContext::new(Scenario::SimpleV2).await; cx.config - .expect_ok_ex( - &["rustup", "default", "nightly"], - for_host!( - r" - nightly-{0} installed - 1.3.0 (hash-nightly-2) + .expect(["rustup", "default", "nightly"]) + .await + .with_stdout(snapbox::str![[r#" + + nightly-[HOST_TRIPLE] installed - 1.3.0 (hash-nightly-2) + -" - ), - for_host!( - r"info: syncing channel updates for 'nightly-{0}' +"#]]) + .with_stderr(snapbox::str![[r#" +info: syncing channel updates for 'nightly-[HOST_TRIPLE]' info: latest update on 2015-01-02, rust version 1.3.0 (hash-nightly-2) info: downloading component 'cargo' info: downloading component 'rust-docs' @@ -281,87 +275,107 @@ info: installing component 'cargo' info: installing component 'rust-docs' info: installing component 'rust-std' info: installing component 'rustc' -info: default toolchain set to 'nightly-{0}' -" - ), - ) - .await; +info: default toolchain set to 'nightly-[HOST_TRIPLE]' + +"#]]) + .is_ok(); } #[tokio::test] async fn default_override() { - let mut cx = CliTestContext::new(Scenario::SimpleV2).await; + let cx = CliTestContext::new(Scenario::SimpleV2).await; cx.config - .expect_ok(&["rustup", "toolchain", "add", "nightly"]) - .await; - cx.config.expect_ok(&["rustup", "default", "stable"]).await; + .expect(["rustup", "toolchain", "add", "nightly"]) + .await + .is_ok(); cx.config - .expect_ok(&["rustup", "override", "set", "nightly"]) - .await; + .expect(["rustup", "default", "stable"]) + .await + .is_ok(); cx.config - .expect_stderr_ok( - &["rustup", "default", "stable"], - for_host!( - r"info: using existing install for 'stable-{0}' -info: default toolchain set to 'stable-{0}' -info: note that the toolchain 'nightly-{0}' is currently in use (directory override for" - ), - ) - .await; + .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_TRIPLE]' +info: default toolchain set to 'stable-[HOST_TRIPLE]' +info: note that the toolchain 'nightly-[HOST_TRIPLE]' 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_stderr_ok( - &["rustup", "--verbose", "toolchain", "add", "nightly"], - for_host!(r"dist/2015-01-01/rust-std-nightly-{0}.tar.zst"), - ) - .await; + .expect(["rustup", "--verbose", "toolchain", "add", "nightly"]) + .await + .with_stderr(snapbox::str![[r#" +... +[..]dist/2015-01-01/rust-std-nightly-[HOST_TRIPLE].tar.zst[..] +... +"#]]) + .is_ok(); } #[tokio::test] async fn add_target() { - let mut cx = CliTestContext::new(Scenario::SimpleV2).await; + let cx = CliTestContext::new(Scenario::SimpleV2).await; let path = format!( "toolchains/nightly-{}/lib/rustlib/{}/lib/libstd.rlib", &this_host_triple(), CROSS_ARCH1 ); - cx.config.expect_ok(&["rustup", "default", "nightly"]).await; cx.config - .expect_ok(&["rustup", "target", "add", CROSS_ARCH1]) - .await; + .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 mut cx = CliTestContext::new(Scenario::SimpleV2).await; + let cx = CliTestContext::new(Scenario::SimpleV2).await; let path = format!( "toolchains/nightly-{}/lib/rustlib/{}/lib/libstd.rlib", &this_host_triple(), CROSS_ARCH1 ); - cx.config.expect_ok(&["rustup", "default", "nightly"]).await; cx.config - .expect_ok(&["rustup", "target", "add", CROSS_ARCH1]) - .await; + .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_ok(&["rustup", "target", "remove", CROSS_ARCH1]) - .await; + .expect(["rustup", "target", "remove", CROSS_ARCH1]) + .await + .is_ok(); assert!(!cx.config.rustupdir.has(&path)); } #[tokio::test] async fn add_remove_multiple_targets() { - let mut cx = CliTestContext::new(Scenario::SimpleV2).await; - cx.config.expect_ok(&["rustup", "default", "nightly"]).await; + let cx = CliTestContext::new(Scenario::SimpleV2).await; cx.config - .expect_ok(&["rustup", "target", "add", CROSS_ARCH1, CROSS_ARCH2]) - .await; + .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_triple(), @@ -376,8 +390,9 @@ async fn add_remove_multiple_targets() { assert!(cx.config.rustupdir.has(path)); cx.config - .expect_ok(&["rustup", "target", "remove", CROSS_ARCH1, CROSS_ARCH2]) - .await; + .expect(["rustup", "target", "remove", CROSS_ARCH1, CROSS_ARCH2]) + .await + .is_ok(); let path = format!( "toolchains/nightly-{}/lib/rustlib/{}/lib/libstd.rlib", &this_host_triple(), @@ -394,37 +409,54 @@ async fn add_remove_multiple_targets() { #[tokio::test] async fn list_targets() { - let mut cx = CliTestContext::new(Scenario::SimpleV2).await; - cx.config.expect_ok(&["rustup", "default", "nightly"]).await; + let cx = CliTestContext::new(Scenario::SimpleV2).await; + cx.config + .expect(["rustup", "default", "nightly"]) + .await + .is_ok(); cx.config - .expect_stdout_ok(&["rustup", "target", "list"], CROSS_ARCH1) - .await; + .expect(["rustup", "target", "list"]) + .await + .with_stdout(snapbox::str![[r#" +... +[CROSS_ARCH_I] +... +"#]]) + .is_ok(); } #[tokio::test] async fn list_installed_targets() { - let mut cx = CliTestContext::new(Scenario::SimpleV2).await; - let trip = this_host_triple(); + let cx = CliTestContext::new(Scenario::SimpleV2).await; - cx.config.expect_ok(&["rustup", "default", "nightly"]).await; cx.config - .expect_stdout_ok(&["rustup", "target", "list", "--installed"], &trip) - .await; + .expect(["rustup", "default", "nightly"]) + .await + .is_ok(); + cx.config + .expect(["rustup", "target", "list", "--installed"]) + .await + .with_stdout(snapbox::str![[r#" +[HOST_TRIPLE] + +"#]]) + .is_ok(); } #[tokio::test] async fn add_target_explicit() { - let mut cx = CliTestContext::new(Scenario::SimpleV2).await; + let cx = CliTestContext::new(Scenario::SimpleV2).await; let path = format!( "toolchains/nightly-{}/lib/rustlib/{}/lib/libstd.rlib", &this_host_triple(), CROSS_ARCH1 ); cx.config - .expect_ok(&["rustup", "toolchain", "add", "nightly"]) - .await; + .expect(["rustup", "toolchain", "add", "nightly"]) + .await + .is_ok(); cx.config - .expect_ok(&[ + .expect([ "rustup", "target", "add", @@ -432,23 +464,25 @@ async fn add_target_explicit() { "nightly", CROSS_ARCH1, ]) - .await; + .await + .is_ok(); assert!(cx.config.rustupdir.has(path)); } #[tokio::test] async fn remove_target_explicit() { - let mut cx = CliTestContext::new(Scenario::SimpleV2).await; + let cx = CliTestContext::new(Scenario::SimpleV2).await; let path = format!( "toolchains/nightly-{}/lib/rustlib/{}/lib/libstd.rlib", &this_host_triple(), CROSS_ARCH1 ); cx.config - .expect_ok(&["rustup", "toolchain", "add", "nightly"]) - .await; + .expect(["rustup", "toolchain", "add", "nightly"]) + .await + .is_ok(); cx.config - .expect_ok(&[ + .expect([ "rustup", "target", "add", @@ -456,10 +490,11 @@ async fn remove_target_explicit() { "nightly", CROSS_ARCH1, ]) - .await; + .await + .is_ok(); assert!(cx.config.rustupdir.has(&path)); cx.config - .expect_ok(&[ + .expect([ "rustup", "target", "remove", @@ -467,44 +502,76 @@ async fn remove_target_explicit() { "nightly", CROSS_ARCH1, ]) - .await; + .await + .is_ok(); assert!(!cx.config.rustupdir.has(&path)); } #[tokio::test] async fn list_targets_explicit() { - let mut cx = CliTestContext::new(Scenario::SimpleV2).await; + let cx = CliTestContext::new(Scenario::SimpleV2).await; cx.config - .expect_ok(&["rustup", "toolchain", "add", "nightly"]) - .await; + .expect(["rustup", "toolchain", "add", "nightly"]) + .await + .is_ok(); cx.config - .expect_stdout_ok( - &["rustup", "target", "list", "--toolchain", "nightly"], - CROSS_ARCH1, - ) - .await; + .expect(["rustup", "target", "list", "--toolchain", "nightly"]) + .await + .with_stdout(snapbox::str![[r#" +... +[CROSS_ARCH_I] +... +"#]]) + .is_ok(); } #[tokio::test] async fn link() { - let mut cx = CliTestContext::new(Scenario::SimpleV2).await; + let cx = CliTestContext::new(Scenario::SimpleV2).await; let path = cx.config.customdir.join("custom-1"); let path = path.to_string_lossy(); cx.config - .expect_ok(&["rustup", "toolchain", "link", "custom", &path]) - .await; - cx.config.expect_ok(&["rustup", "default", "custom"]).await; - cx.config - .expect_stdout_ok(&["rustc", "--version"], "hash-c-1") - .await; - cx.config - .expect_stdout_ok(&["rustup", "show"], "custom (active, default)") - .await; - cx.config.expect_ok(&["rustup", "update", "nightly"]).await; - cx.config.expect_ok(&["rustup", "default", "nightly"]).await; - cx.config - .expect_stdout_ok(&["rustup", "show"], "custom") - .await; + .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 @@ -512,7 +579,7 @@ async fn link() { // That way the proxy can pick the correct toolchain. #[tokio::test] async fn fallback_cargo_calls_correct_rustc() { - let mut cx = CliTestContext::new(Scenario::SimpleV2).await; + 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}")); @@ -525,16 +592,33 @@ async fn fallback_cargo_calls_correct_rustc() { let path = cx.config.customdir.join("custom-1"); let path = path.to_string_lossy(); cx.config - .expect_ok(&["rustup", "toolchain", "link", "custom", &path]) - .await; - cx.config.expect_ok(&["rustup", "default", "custom"]).await; - cx.config.expect_ok(&["rustup", "update", "nightly"]).await; + .expect(["rustup", "toolchain", "link", "custom", &path]) + .await + .is_ok(); + cx.config + .expect(["rustup", "default", "custom"]) + .await + .is_ok(); cx.config - .expect_stdout_ok(&["rustc", "--version"], "hash-c-1") - .await; + .expect(["rustup", "update", "nightly"]) + .await + .is_ok(); cx.config - .expect_stdout_ok(&["cargo", "--version"], "hash-nightly-2") - .await; + .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()); @@ -543,8 +627,13 @@ async fn fallback_cargo_calls_correct_rustc() { // RUSTUP_TOOLCHAIN variable set by the original "cargo" proxy, and // interpreted by the nested "rustc" proxy. cx.config - .expect_stdout_ok(&["cargo", "--call-rustc"], "hash-c-1") - .await; + .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 @@ -567,8 +656,11 @@ async fn fallback_cargo_calls_correct_rustc() { // and the first argument would be `+nightly` which would be an error. #[tokio::test] async fn recursive_cargo() { - let mut cx = CliTestContext::new(Scenario::ArchivesV2).await; - cx.config.expect_ok(&["rustup", "default", "nightly"]).await; + 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 @@ -585,36 +677,40 @@ async fn recursive_cargo() { fs::copy(real_mock_cargo, cargo_subcommand).unwrap(); cx.config - .expect_stdout_ok(&["cargo", "--recursive-cargo-subcommand"], "hash-nightly-2") - .await; + .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 mut cx = CliTestContext::new(Scenario::None).await; + let cx = CliTestContext::new(Scenario::None).await; cx.config - .expect_ok_ex( - &["rustup", "show", "home"], - &format!( - r"{} -", - cx.config.rustupdir - ), - r"", - ) - .await; + .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 mut cx = CliTestContext::new(Scenario::None).await; + let cx = CliTestContext::new(Scenario::None).await; cx.config - .expect_ok_ex( - &["rustup", "show"], - for_host_and_home!( - &cx.config, - r"Default host: {0} -rustup home: {1} + .expect(["rustup", "show"]) + .await + .extend_redactions([("[RUSTUP_DIR]", &cx.config.rustupdir.to_string())]) + .with_stdout(snapbox::str![[r#" +Default host: [HOST_TRIPLE] +rustup home: [RUSTUP_DIR] installed toolchains -------------------- @@ -622,156 +718,177 @@ installed toolchains active toolchain ---------------- no active toolchain -" - ), - r"", - ) - .await; + +"#]]) + .with_stderr(snapbox::str![[""]]) + .is_ok(); } #[tokio::test] async fn show_toolchain_default() { - let mut cx = CliTestContext::new(Scenario::SimpleV2).await; - cx.config.expect_ok(&["rustup", "default", "nightly"]).await; + let cx = CliTestContext::new(Scenario::SimpleV2).await; + cx.config + .expect(["rustup", "default", "nightly"]) + .await + .is_ok(); cx.config - .expect_ok_ex( - &["rustup", "show"], - for_host_and_home!( - cx.config, - r"Default host: {0} -rustup home: {1} + .expect(["rustup", "show"]) + .await + .extend_redactions([("[RUSTUP_DIR]", &cx.config.rustupdir.to_string())]) + .with_stdout(snapbox::str![[r#" +Default host: [HOST_TRIPLE] +rustup home: [RUSTUP_DIR] installed toolchains -------------------- -nightly-{0} (active, default) +nightly-[HOST_TRIPLE] (active, default) active toolchain ---------------- -name: nightly-{0} +name: nightly-[HOST_TRIPLE] active because: it's the default toolchain installed targets: - {0} -" - ), - r"", - ) - .await; + [HOST_TRIPLE] + +"#]]) + .with_stderr(snapbox::str![[""]]) + .is_ok(); } #[tokio::test] async fn show_no_default() { - let mut cx = CliTestContext::new(Scenario::SimpleV2).await; - cx.config.expect_ok(&["rustup", "install", "nightly"]).await; - cx.config.expect_ok(&["rustup", "default", "none"]).await; + let cx = CliTestContext::new(Scenario::SimpleV2).await; + cx.config + .expect(["rustup", "install", "nightly"]) + .await + .is_ok(); cx.config - .expect_stdout_ok( - &["rustup", "show"], - for_host!( - "\ + .expect(["rustup", "default", "none"]) + .await + .is_ok(); + cx.config + .expect(["rustup", "show"]) + .await + .with_stdout(snapbox::str![[r#" +... installed toolchains -------------------- -nightly-{0} +nightly-[HOST_TRIPLE] active toolchain -" - ), - ) - .await; +---------------- +no active toolchain + +"#]]) + .is_ok(); } #[tokio::test] async fn show_no_default_active() { - let mut cx = CliTestContext::new(Scenario::SimpleV2).await; - cx.config.expect_ok(&["rustup", "install", "nightly"]).await; - cx.config.expect_ok(&["rustup", "default", "none"]).await; + let cx = CliTestContext::new(Scenario::SimpleV2).await; + cx.config + .expect(["rustup", "install", "nightly"]) + .await + .is_ok(); cx.config - .expect_stdout_ok( - &["rustup", "+nightly", "show"], - for_host!( - "\ + .expect(["rustup", "default", "none"]) + .await + .is_ok(); + cx.config + .expect(["rustup", "+nightly", "show"]) + .await + .with_stdout(snapbox::str![[r#" +... installed toolchains -------------------- -nightly-{0} (active) +nightly-[HOST_TRIPLE] (active) active toolchain -" - ), - ) - .await; +---------------- +name: nightly-[HOST_TRIPLE] +active because: overridden by +toolchain on the command line +installed targets: + [HOST_TRIPLE] + +"#]]) + .is_ok(); } #[tokio::test] async fn show_multiple_toolchains() { - let mut cx = CliTestContext::new(Scenario::SimpleV2).await; - cx.config.expect_ok(&["rustup", "default", "nightly"]).await; - cx.config.expect_ok(&["rustup", "update", "stable"]).await; + let cx = CliTestContext::new(Scenario::SimpleV2).await; + cx.config + .expect(["rustup", "default", "nightly"]) + .await + .is_ok(); cx.config - .expect_ok_ex( - &["rustup", "show"], - for_host_and_home!( - cx.config, - r"Default host: {0} -rustup home: {1} + .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_TRIPLE] +rustup home: [RUSTUP_DIR] installed toolchains -------------------- -stable-{0} -nightly-{0} (active, default) +stable-[HOST_TRIPLE] +nightly-[HOST_TRIPLE] (active, default) active toolchain ---------------- -name: nightly-{0} +name: nightly-[HOST_TRIPLE] active because: it's the default toolchain installed targets: - {0} -" - ), - r"", - ) - .await; + [HOST_TRIPLE] + +"#]]) + .with_stderr(snapbox::str![[""]]) + .is_ok(); } #[tokio::test] async fn show_multiple_targets() { - let mut cx = CliTestContext::new(Scenario::MultiHost).await; + let cx = CliTestContext::new(Scenario::MultiHost).await; cx.config - .expect_ok(&[ + .expect([ "rustup", "default", &format!("nightly-{MULTI_ARCH1}"), "--force-non-host", ]) - .await; + .await + .is_ok(); cx.config - .expect_ok(&["rustup", "target", "add", CROSS_ARCH2]) - .await; + .expect(["rustup", "target", "add", CROSS_ARCH2]) + .await + .is_ok(); cx.config - .expect_ok_ex( - &["rustup", "show"], - &format!( - r"Default host: {2} -rustup home: {3} + .expect(["rustup", "show"]) + .await + .extend_redactions([("[RUSTUP_DIR]", &cx.config.rustupdir.to_string())]) + .with_stdout(snapbox::str![[r#" +Default host: [HOST_TRIPLE] +rustup home: [RUSTUP_DIR] installed toolchains -------------------- -nightly-{0} (active, default) +nightly-[MULTI_ARCH_I] (active, default) active toolchain ---------------- -name: nightly-{0} +name: nightly-[MULTI_ARCH_I] active because: it's the default toolchain installed targets: - {1} - {0} -", - MULTI_ARCH1, - CROSS_ARCH2, - this_host_triple(), - cx.config.rustupdir - ), - r"", - ) - .await; + [CROSS_ARCH_II] + [MULTI_ARCH_I] + +"#]]) + .with_stderr(snapbox::str![[""]]) + .is_ok(); } #[tokio::test] @@ -780,162 +897,195 @@ async fn show_multiple_toolchains_and_targets() { return; } - let mut cx = CliTestContext::new(Scenario::MultiHost).await; + let cx = CliTestContext::new(Scenario::MultiHost).await; cx.config - .expect_ok(&[ + .expect([ "rustup", "default", &format!("nightly-{MULTI_ARCH1}"), "--force-non-host", ]) - .await; + .await + .is_ok(); cx.config - .expect_ok(&["rustup", "target", "add", CROSS_ARCH2]) - .await; + .expect(["rustup", "target", "add", CROSS_ARCH2]) + .await + .is_ok(); cx.config - .expect_ok(&[ + .expect([ "rustup", "update", "--force-non-host", &format!("stable-{MULTI_ARCH1}"), ]) - .await; + .await + .is_ok(); cx.config - .expect_ok_ex( - &["rustup", "show"], - &format!( - r"Default host: {2} -rustup home: {3} + .expect(["rustup", "show"]) + .await + .extend_redactions([("[RUSTUP_DIR]", &cx.config.rustupdir.to_string())]) + .with_stdout(snapbox::str![[r#" +Default host: [HOST_TRIPLE] +rustup home: [RUSTUP_DIR] installed toolchains -------------------- -stable-{0} -nightly-{0} (active, default) +stable-[MULTI_ARCH_I] +nightly-[MULTI_ARCH_I] (active, default) active toolchain ---------------- -name: nightly-{0} +name: nightly-[MULTI_ARCH_I] active because: it's the default toolchain installed targets: - {1} - {0} -", - MULTI_ARCH1, - CROSS_ARCH2, - this_host_triple(), - cx.config.rustupdir - ), - r"", - ) - .await; + [CROSS_ARCH_II] + [MULTI_ARCH_I] + +"#]]) + .with_stderr(snapbox::str![[""]]) + .is_ok(); } #[tokio::test] async fn list_default_toolchain() { - let mut cx = CliTestContext::new(Scenario::SimpleV2).await; - cx.config.expect_ok(&["rustup", "default", "nightly"]).await; + let cx = CliTestContext::new(Scenario::SimpleV2).await; cx.config - .expect_ok_ex( - &["rustup", "toolchain", "list"], - for_host!("nightly-{0} (active, default)\n"), - r"", - ) - .await; + .expect(["rustup", "default", "nightly"]) + .await + .is_ok(); + cx.config + .expect(["rustup", "toolchain", "list"]) + .await + .with_stdout(snapbox::str![[r#" +nightly-[HOST_TRIPLE] (active, default) + +"#]]) + .with_stderr(snapbox::str![[""]]) + .is_ok(); } #[tokio::test] async fn list_default_toolchain_quiet() { - let mut cx = CliTestContext::new(Scenario::SimpleV2).await; - cx.config.expect_ok(&["rustup", "default", "nightly"]).await; + let cx = CliTestContext::new(Scenario::SimpleV2).await; cx.config - .expect_ok_ex( - &["rustup", "toolchain", "list", "--quiet"], - for_host!("nightly-{0}\n"), - r"", - ) - .await; + .expect(["rustup", "default", "nightly"]) + .await + .is_ok(); + cx.config + .expect(["rustup", "toolchain", "list", "--quiet"]) + .await + .with_stdout(snapbox::str![[r#" +nightly-[HOST_TRIPLE] + +"#]]) + .with_stderr(snapbox::str![[""]]) + .is_ok(); } #[tokio::test] async fn list_no_default_toolchain() { - let mut cx = CliTestContext::new(Scenario::SimpleV2).await; - cx.config.expect_ok(&["rustup", "install", "nightly"]).await; - cx.config.expect_ok(&["rustup", "default", "none"]).await; + let cx = CliTestContext::new(Scenario::SimpleV2).await; cx.config - .expect_ok_ex( - &["rustup", "toolchain", "list"], - for_host!("nightly-{0}\n"), - r"", - ) - .await; + .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_TRIPLE] + +"#]]) + .with_stderr(snapbox::str![[""]]) + .is_ok(); } #[tokio::test] async fn list_no_default_override_toolchain() { - let mut cx = CliTestContext::new(Scenario::SimpleV2).await; + let cx = CliTestContext::new(Scenario::SimpleV2).await; cx.config - .expect_ok(&["rustup", "override", "set", "nightly"]) - .await; + .expect(["rustup", "override", "set", "nightly"]) + .await + .is_ok(); cx.config - .expect_ok_ex( - &["rustup", "toolchain", "list"], - for_host!("nightly-{0} (active)\n"), - r"", - ) - .await; + .expect(["rustup", "toolchain", "list"]) + .await + .with_stdout(snapbox::str![[r#" +nightly-[HOST_TRIPLE] (active) + +"#]]) + .with_stderr(snapbox::str![[""]]) + .is_ok(); } #[tokio::test] async fn list_default_and_override_toolchain() { - let mut cx = CliTestContext::new(Scenario::SimpleV2).await; - cx.config.expect_ok(&["rustup", "default", "nightly"]).await; + let cx = CliTestContext::new(Scenario::SimpleV2).await; cx.config - .expect_ok(&["rustup", "override", "set", "nightly"]) - .await; + .expect(&["rustup", "default", "nightly"]) + .await + .is_ok(); cx.config - .expect_ok_ex( - &["rustup", "toolchain", "list"], - for_host!("nightly-{0} (active, default)\n"), - r"", - ) - .await; + .expect(&["rustup", "override", "set", "nightly"]) + .await + .is_ok(); + cx.config + .expect(&["rustup", "toolchain", "list"]) + .await + .is_ok() + .with_stdout(snapbox::str![[r#" +nightly-[HOST_TRIPLE] (active, default) + +"#]]) + .with_stderr(snapbox::str![[""]]); } #[tokio::test] -#[ignore = "FIXME: Windows shows UNC paths"] async fn show_toolchain_override() { - let mut cx = CliTestContext::new(Scenario::SimpleV2).await; - let cwd = cx.config.current_dir(); + let cx = CliTestContext::new(Scenario::SimpleV2).await; cx.config - .expect_ok(&["rustup", "override", "add", "nightly"]) - .await; + .expect(["rustup", "override", "add", "nightly"]) + .await + .is_ok(); cx.config - .expect_ok_ex( - &["rustup", "show"], - &format!( - r"Default host: {0} -rustup home: {1} + .expect(["rustup", "show"]) + .await + .extend_redactions([("[RUSTUP_DIR]", &cx.config.rustupdir.to_string())]) + .with_stdout(snapbox::str![[r#" +Default host: [HOST_TRIPLE] +rustup home: [RUSTUP_DIR] -nightly-{0} (directory override for '{2}') -1.3.0 (hash-nightly-2) -", - this_host_triple(), - cx.config.rustupdir, - cwd.display(), - ), - r"", - ) - .await; +installed toolchains +-------------------- +nightly-[HOST_TRIPLE] (active) + +active toolchain +---------------- +name: nightly-[HOST_TRIPLE] +active because: directory override for '[..]' +installed targets: + [HOST_TRIPLE] + +"#]]) + .with_stderr(snapbox::str![[""]]) + .is_ok(); } #[tokio::test] -#[ignore = "FIXME: Windows shows UNC paths"] async fn show_toolchain_toolchain_file_override() { - let mut cx = CliTestContext::new(Scenario::SimpleV2).await; - cx.config.expect_ok(&["rustup", "default", "stable"]).await; + let cx = CliTestContext::new(Scenario::SimpleV2).await; + cx.config + .expect(["rustup", "default", "stable"]) + .await + .is_ok(); cx.config - .expect_ok(&["rustup", "toolchain", "install", "nightly"]) - .await; + .expect(["rustup", "toolchain", "install", "nightly"]) + .await + .is_ok(); let cwd = cx.config.current_dir(); let toolchain_file = cwd.join("rust-toolchain"); @@ -943,45 +1093,45 @@ async fn show_toolchain_toolchain_file_override() { raw::write_file(&toolchain_file, "nightly").unwrap(); cx.config - .expect_ok_ex( - &["rustup", "show"], - &format!( - r"Default host: {0} -rustup home: {1} + .expect(["rustup", "show"]) + .await + .extend_redactions([("[RUSTUP_DIR]", &cx.config.rustupdir.to_string())]) + .with_stdout(snapbox::str![[r#" +Default host: [HOST_TRIPLE] +rustup home: [RUSTUP_DIR] installed toolchains -------------------- - -stable-{0} (default) -nightly-{0} +stable-[HOST_TRIPLE] (default) +nightly-[HOST_TRIPLE] (active) active toolchain ---------------- +name: nightly-[HOST_TRIPLE] +active because: overridden by '[..]' +installed targets: + [HOST_TRIPLE] -nightly-{0} (overridden by '{2}') -1.3.0 (hash-nightly-2) - -", - this_host_triple(), - cx.config.rustupdir, - toolchain_file.display() - ), - r"", - ) - .await; +"#]]) + .with_stderr(snapbox::str![[""]]) + .is_ok(); } #[tokio::test] -#[ignore = "FIXME: Windows shows UNC paths"] async fn show_toolchain_version_nested_file_override() { let mut cx = CliTestContext::new(Scenario::SimpleV2).await; cx.config - .expect_ok(&["rustup", "toolchain", "add", "stable", "beta", "nightly"]) - .await; - cx.config.expect_ok(&["rustup", "default", "stable"]).await; + .expect(["rustup", "toolchain", "add", "stable", "beta", "nightly"]) + .await + .is_ok(); cx.config - .expect_ok(&["rustup", "toolchain", "install", "nightly"]) - .await; + .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"); @@ -991,39 +1141,40 @@ async fn show_toolchain_version_nested_file_override() { let subdir = cwd.join("foo"); fs::create_dir_all(&subdir).unwrap(); - let mut cx = cx.change_dir(&subdir); + let cx = cx.change_dir(&subdir); cx.config - .expect_ok_ex( - &["rustup", "show"], - &format!( - r"Default host: {0} + .expect(["rustup", "show"]) + .await + .extend_redactions([("[RUSTUP_DIR]", &cx.config.rustupdir.to_string())]) + .with_stdout(snapbox::str![[r#" +Default host: [HOST_TRIPLE] +rustup home: [RUSTUP_DIR] installed toolchains -------------------- - -stable-{0} (default) -nightly-{0} +stable-[HOST_TRIPLE] (default) +beta-[HOST_TRIPLE] +nightly-[HOST_TRIPLE] (active) active toolchain ---------------- +name: nightly-[HOST_TRIPLE] +active because: overridden by '[..]' +installed targets: + [HOST_TRIPLE] -nightly-{0} (overridden by '{1}') -1.3.0 (hash-nightly-2) - -", - this_host_triple(), - toolchain_file.display() - ), - r"", - ) - .await; +"#]]) + .with_stderr(snapbox::str![[""]]) + .is_ok(); } #[tokio::test] -#[ignore = "FIXME: Windows shows UNC paths"] async fn show_toolchain_toolchain_file_override_not_installed() { - let mut cx = CliTestContext::new(Scenario::SimpleV2).await; - cx.config.expect_ok(&["rustup", "default", "stable"]).await; + 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"); @@ -1032,34 +1183,63 @@ async fn show_toolchain_toolchain_file_override_not_installed() { // I'm not sure this should really be erroring when the toolchain // is not installed; just capturing the behavior. - let mut cmd = cx.config.cmd("rustup", ["show"]); - cx.config.env(&mut cmd); - let out = cmd.output().unwrap(); - assert!(!out.status.success()); - let stderr = String::from_utf8(out.stderr).unwrap(); - assert!(stderr.starts_with("error: override toolchain 'nightly' is not installed")); - assert!(stderr.contains(&format!( - "the toolchain file at '{}' specifies an uninstalled toolchain", - toolchain_file.display() - ))); + cx.config + .expect_with_env(["rustup", "show"], [("RUSTUP_AUTO_INSTALL", "0")]) + .await + .extend_redactions([ + ("[RUSTUP_DIR]", &cx.config.rustupdir.to_string()), + ("[TOOLCHAIN_FILE]", &toolchain_file.display().to_string()), + ]) + .with_stdout(snapbox::str![[r#" +Default host: [HOST_TRIPLE] +rustup home: [RUSTUP_DIR] + + +"#]]) + .with_stderr(snapbox::str![[r#" +error: toolchain 'nightly-[HOST_TRIPLE]' is not installed +help: run `rustup toolchain install` to install it + +"#]]) + .is_err(); } #[tokio::test] async fn show_toolchain_override_not_installed() { - let mut cx = CliTestContext::new(Scenario::SimpleV2).await; + let cx = CliTestContext::new(Scenario::SimpleV2).await; cx.config - .expect_ok(&["rustup", "override", "add", "nightly"]) - .await; + .expect(["rustup", "override", "add", "nightly"]) + .await + .is_ok(); cx.config - .expect_ok(&["rustup", "toolchain", "remove", "nightly"]) - .await; - let out = cx.config.run("rustup", ["show"], &[]).await; - assert!(out.ok); - assert!( - !out.stderr - .contains("is not installed: the directory override for") - ); - assert!(out.stderr.contains("info: installing component 'rustc'")); + .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_TRIPLE] +rustup home: [RUSTUP_DIR] + +installed toolchains +-------------------- + +active toolchain +---------------- +name: nightly-[HOST_TRIPLE] +active because: directory override for '[..]' +installed targets: + [HOST_TRIPLE] + +"#]]) + .with_stderr(snapbox::str![[r#" +... +info: installing component 'rustc' +... +"#]]) + .is_ok(); } #[tokio::test] @@ -1074,103 +1254,114 @@ async fn override_set_unset_with_path() { let emptydir = tempfile::tempdir().unwrap(); { - let mut cx = cx.change_dir(emptydir.path()); + let cx = cx.change_dir(emptydir.path()); cx.config - .expect_ok(&["rustup", "override", "set", "nightly", "--path", cwd_str]) - .await; + .expect(["rustup", "override", "set", "nightly", "--path", cwd_str]) + .await + .is_ok(); } cx.config - .expect_ok_ex( - &["rustup", "override", "list"], - &format!("{}\tnightly-{}\n", cwd_str, this_host_triple()), - r"", - ) - .await; + .expect(["rustup", "override", "list"]) + .await + .extend_redactions([("[CWD]", cwd_str.to_string())]) + .with_stdout(snapbox::str![[r#" +[CWD] nightly-[HOST_TRIPLE] + +"#]]) + .with_stderr(snapbox::str![[""]]) + .is_ok(); { - let mut cx = cx.change_dir(emptydir.path()); + let cx = cx.change_dir(emptydir.path()); cx.config - .expect_ok(&["rustup", "override", "unset", "--path", cwd_str]) - .await; + .expect(["rustup", "override", "unset", "--path", cwd_str]) + .await + .is_ok(); } cx.config - .expect_ok_ex(&["rustup", "override", "list"], "no overrides\n", r"") - .await; + .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 mut cx = CliTestContext::new(Scenario::SimpleV2).await; - cx.config.expect_ok(&["rustup", "default", "nightly"]).await; - let out = cx - .config - .run("rustup", ["show"], &[("RUSTUP_TOOLCHAIN", "nightly")]) - .await; - assert!(out.ok); - assert_eq!( - &out.stdout, - for_host_and_home!( - cx.config, - r"Default host: {0} -rustup home: {1} + 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_TRIPLE] +rustup home: [RUSTUP_DIR] installed toolchains -------------------- -nightly-{0} (active, default) +nightly-[HOST_TRIPLE] (active, default) active toolchain ---------------- -name: nightly-{0} +name: nightly-[HOST_TRIPLE] active because: overridden by environment variable RUSTUP_TOOLCHAIN installed targets: - {0} -" - ) - ); + [HOST_TRIPLE] + +"#]]); } #[tokio::test] async fn show_toolchain_env_not_installed() { let cx = CliTestContext::new(Scenario::SimpleV2).await; - let out = cx - .config - .run("rustup", ["show"], &[("RUSTUP_TOOLCHAIN", "nightly")]) - .await; - - assert!(out.ok); - - let expected_out = for_host_and_home!( - cx.config, - r"Default host: {0} -rustup home: {1} + 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_TRIPLE] +rustup home: [RUSTUP_DIR] installed toolchains -------------------- active toolchain ---------------- -name: nightly-{0} +name: nightly-[HOST_TRIPLE] active because: overridden by environment variable RUSTUP_TOOLCHAIN installed targets: - {0} -" - ); - assert!(&out.stdout == expected_out); + [HOST_TRIPLE] + +"#]]); } #[tokio::test] async fn show_active_toolchain() { - let mut cx = CliTestContext::new(Scenario::SimpleV2).await; - cx.config.expect_ok(&["rustup", "default", "nightly"]).await; + let cx = CliTestContext::new(Scenario::SimpleV2).await; cx.config - .expect_ok_ex( - &["rustup", "show", "active-toolchain"], - for_host!("nightly-{0} (default)\n"), - r"", - ) - .await; + .expect(&["rustup", "default", "nightly"]) + .await + .is_ok(); + cx.config + .expect(&["rustup", "show", "active-toolchain"]) + .await + .with_stdout(snapbox::str![[r#" +nightly-[HOST_TRIPLE] (default) + +"#]]) + .with_stderr(snapbox::str![[""]]) + .is_ok(); } #[tokio::test] @@ -1178,172 +1369,202 @@ async fn show_with_verbose() { let mut cx = CliTestContext::new(Scenario::None).await; { - let mut cx = cx.with_dist_dir(Scenario::SimpleV2); - cx.config.expect_ok(&["rustup", "default", "nightly"]).await; + let cx = cx.with_dist_dir(Scenario::SimpleV2); + cx.config + .expect(["rustup", "default", "nightly"]) + .await + .is_ok(); } - let mut cx = cx.with_dist_dir(Scenario::ArchivesV2_2015_01_01); - let config = &mut cx.config; + let cx = cx.with_dist_dir(Scenario::ArchivesV2_2015_01_01); + let config = &cx.config; config - .expect_ok(&["rustup", "update", "nightly-2015-01-01"]) - .await; + .expect(["rustup", "update", "nightly-2015-01-01"]) + .await + .is_ok(); config - .expect_ok_ex( - &["rustup", "show", "--verbose"], - for_host_and_home!( - config, - r"Default host: {0} -rustup home: {1} + .expect(["rustup", "show", "--verbose"]) + .await + .extend_redactions([("[RUSTUP_DIR]", &cx.config.rustupdir.to_string())]) + .with_stdout(snapbox::str![[r#" +Default host: [HOST_TRIPLE] +rustup home: [RUSTUP_DIR] installed toolchains -------------------- -nightly-{0} (active, default) +nightly-[HOST_TRIPLE] (active, default) 1.3.0 (hash-nightly-2) - path: {2} + path: [RUSTUP_DIR]/toolchains/nightly-[HOST_TRIPLE] -nightly-2015-01-01-{0} +nightly-2015-01-01-[HOST_TRIPLE] 1.2.0 (hash-nightly-1) - path: {3} + path: [RUSTUP_DIR]/toolchains/nightly-2015-01-01-[HOST_TRIPLE] active toolchain ---------------- -name: nightly-{0} +name: nightly-[HOST_TRIPLE] active because: it's the default toolchain compiler: 1.3.0 (hash-nightly-2) -path: {2} +path: [RUSTUP_DIR]/toolchains/nightly-[HOST_TRIPLE] installed targets: - {0} -", - config - .rustupdir - .join("toolchains") - .join(for_host!("nightly-{0}")) - .display(), - config - .rustupdir - .join("toolchains") - .join(for_host!("nightly-2015-01-01-{0}")) - .display() - ), - r"", - ) - .await; + [HOST_TRIPLE] + +"#]]) + .with_stderr(snapbox::str![[""]]) + .is_ok(); } #[tokio::test] async fn show_active_toolchain_with_verbose() { - let mut cx = CliTestContext::new(Scenario::SimpleV2).await; - cx.config.expect_ok(&["rustup", "default", "nightly"]).await; + let cx = CliTestContext::new(Scenario::SimpleV2).await; + cx.config + .expect(["rustup", "default", "nightly"]) + .await + .is_ok(); cx.config - .expect_ok_ex( - &["rustup", "show", "active-toolchain", "--verbose"], - for_host!( - r"nightly-{0} + .expect(["rustup", "show", "active-toolchain", "--verbose"]) + .await + .extend_redactions([("[RUSTUP_DIR]", &cx.config.rustupdir.to_string())]) + .with_stdout(snapbox::str![[r#" +nightly-[HOST_TRIPLE] active because: it's the default toolchain compiler: 1.3.0 (hash-nightly-2) -path: {1} -", - cx.config - .rustupdir - .join("toolchains") - .join(for_host!("nightly-{0}")) - .display() - ), - r"", - ) - .await; +path: [RUSTUP_DIR]/toolchains/nightly-[HOST_TRIPLE] + +"#]]) + .with_stderr(snapbox::str![[""]]) + .is_ok(); } #[tokio::test] async fn show_active_toolchain_with_override() { - let mut cx = CliTestContext::new(Scenario::SimpleV2).await; - cx.config.expect_ok(&["rustup", "default", "stable"]).await; - cx.config.expect_ok(&["rustup", "default", "nightly"]).await; + let cx = CliTestContext::new(Scenario::SimpleV2).await; cx.config - .expect_ok(&["rustup", "override", "set", "stable"]) - .await; + .expect(["rustup", "default", "stable"]) + .await + .is_ok(); cx.config - .expect_stdout_ok( - &["rustup", "show", "active-toolchain"], - for_host!("stable-{0}"), - ) - .await; + .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_TRIPLE] (directory override for '[..]') + +"#]]) + .is_ok(); } #[tokio::test] async fn show_active_toolchain_with_override_verbose() { - let mut cx = CliTestContext::new(Scenario::SimpleV2).await; - cx.config.expect_ok(&["rustup", "default", "stable"]).await; - cx.config.expect_ok(&["rustup", "default", "nightly"]).await; + let cx = CliTestContext::new(Scenario::SimpleV2).await; + cx.config + .expect(["rustup", "default", "stable"]) + .await + .is_ok(); cx.config - .expect_ok(&["rustup", "override", "set", "stable"]) - .await; + .expect(["rustup", "default", "nightly"]) + .await + .is_ok(); cx.config - .expect_ok_ex( - &["rustup", "show", "active-toolchain", "--verbose"], - for_host!( - r"stable-{0} -active because: directory override for '{1}' + .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_TRIPLE] +active because: directory override for '[..]' compiler: 1.1.0 (hash-stable-1.1.0) -path: {2} -", - cx.config.current_dir().display(), - cx.config - .rustupdir - .join("toolchains") - .join(for_host!("stable-{0}")) - .display(), - ), - r"", - ) - .await; +path: [RUSTUP_DIR]/toolchains/stable-[HOST_TRIPLE] + +"#]]) + .with_stderr(snapbox::str![[""]]) + .is_ok(); } #[tokio::test] async fn show_active_toolchain_none() { let cx = CliTestContext::new(Scenario::None).await; cx.config - .expect_err_ex( - &["rustup", "show", "active-toolchain"], - "", - "error: no active toolchain\n", - ) - .await; + .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 mut cx = CliTestContext::new(Scenario::SimpleV2).await; - cx.config.expect_ok(&["rustup", "default", "nightly"]).await; + let cx = CliTestContext::new(Scenario::SimpleV2).await; + cx.config + .expect(["rustup", "default", "nightly"]) + .await + .is_ok(); cx.config - .expect_stdout_ok(&["rustup", "show", "profile"], "default") - .await; + .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_ok(&["rustup", "component", "add", "rust-src"]) - .await; + .expect(["rustup", "component", "add", "rust-src"]) + .await + .is_ok(); cx.config - .expect_stdout_ok(&["rustup", "show", "profile"], "default") - .await; + .expect(["rustup", "show", "profile"]) + .await + .with_stdout(snapbox::str![[r#" +default + +"#]]) + .is_ok(); cx.config - .expect_ok(&["rustup", "component", "remove", "rustc"]) - .await; + .expect(["rustup", "component", "remove", "rustc"]) + .await + .is_ok(); cx.config - .expect_stdout_ok(&["rustup", "show", "profile"], "default") - .await; + .expect(["rustup", "show", "profile"]) + .await + .with_stdout(snapbox::str![[r#" +default + +"#]]) + .is_ok(); } // #846 #[tokio::test] async fn set_default_host() { - let mut cx = CliTestContext::new(Scenario::None).await; + let cx = CliTestContext::new(Scenario::None).await; cx.config - .expect_ok(&["rustup", "set", "default-host", &this_host_triple()]) - .await; + .expect(["rustup", "set", "default-host", &this_host_triple()]) + .await + .is_ok(); cx.config - .expect_stdout_ok(&["rustup", "show"], for_host!("Default host: {0}")) - .await; + .expect(["rustup", "show"]) + .await + .with_stdout(snapbox::str![[r#" +... +Default host: [HOST_TRIPLE] +... +"#]]) + .is_ok(); } // #846 @@ -1351,11 +1572,13 @@ async fn set_default_host() { async fn set_default_host_invalid_triple() { let cx = CliTestContext::new(Scenario::None).await; cx.config - .expect_err( - &["rustup", "set", "default-host", "foo"], - "error: Provided host 'foo' couldn't be converted to partial triple", - ) - .await; + .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 @@ -1363,11 +1586,13 @@ async fn set_default_host_invalid_triple() { async fn set_default_host_invalid_triple_valid_partial() { let cx = CliTestContext::new(Scenario::None).await; cx.config - .expect_err( - &["rustup", "set", "default-host", "x86_64-msvc"], - "error: Provided host 'x86_64-msvc' did not specify an operating system", - ) - .await; + .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 @@ -1376,49 +1601,60 @@ async fn update_doesnt_update_non_tracking_channels() { let mut cx = CliTestContext::new(Scenario::None).await; { - let mut cx = cx.with_dist_dir(Scenario::SimpleV2); - cx.config.expect_ok(&["rustup", "default", "nightly"]).await; + let cx = cx.with_dist_dir(Scenario::SimpleV2); + cx.config + .expect(["rustup", "default", "nightly"]) + .await + .is_ok(); } - let mut cx = cx.with_dist_dir(Scenario::ArchivesV2_2015_01_01); + let cx = cx.with_dist_dir(Scenario::ArchivesV2_2015_01_01); cx.config - .expect_ok(&["rustup", "update", "nightly-2015-01-01"]) - .await; - let mut cmd = cx.config.cmd("rustup", ["update"]); - cx.config.env(&mut cmd); - let out = cmd.output().unwrap(); - let stderr = String::from_utf8(out.stderr).unwrap(); - assert!(!stderr.contains(for_host!( - "syncing channel updates for 'nightly-2015-01-01-{}'" - ))); + .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_triple(), + )); } #[tokio::test] async fn toolchain_install_is_like_update() { - let mut cx = CliTestContext::new(Scenario::SimpleV2).await; + let cx = CliTestContext::new(Scenario::SimpleV2).await; cx.config - .expect_ok(&["rustup", "toolchain", "install", "nightly"]) - .await; + .expect(["rustup", "toolchain", "install", "nightly"]) + .await + .is_ok(); cx.config - .expect_stdout_ok( - &["rustup", "run", "nightly", "rustc", "--version"], - "hash-nightly-2", - ) - .await; + .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 mut cx = CliTestContext::new(Scenario::SimpleV2).await; + let cx = CliTestContext::new(Scenario::SimpleV2).await; cx.config - .expect_ok(&["rustup", "--quiet", "toolchain", "install", "nightly"]) - .await; + .expect(["rustup", "--quiet", "toolchain", "install", "nightly"]) + .await + .is_ok(); cx.config - .expect_stdout_ok( - &["rustup", "run", "nightly", "rustc", "--version"], - "hash-nightly-2", - ) - .await; + .expect(["rustup", "run", "nightly", "rustc", "--version"]) + .await + .with_stdout(snapbox::str![[r#" +1.3.0 (hash-nightly-2) + +"#]]) + .is_ok(); } #[tokio::test] @@ -1438,49 +1674,48 @@ channel = "nightly" .unwrap(); cx.config - .expect_stderr_ok( - &["rustup", "toolchain", "install"], - &format!( - "\ -info: syncing channel updates for 'nightly-{0}' + .expect(["rustup", "toolchain", "install"]) + .await + .extend_redactions([("[TOOLCHAIN_FILE]", &toolchain_file.display().to_string())]) + .with_stderr(snapbox::str![[r#" +info: syncing channel updates for 'nightly-[HOST_TRIPLE]' info: latest update on 2015-01-02, rust version 1.3.0 (hash-nightly-2) info: downloading component 'rustc' info: installing component 'rustc' -info: the active toolchain `nightly-{0}` has been installed -info: it's active because: overridden by '{1}'", - this_host_triple(), - toolchain_file.display(), - ), - ) - .await; - - cx.config - .expect_stderr_ok( - &["rustup", "toolchain", "install"], - &format!( - "\ -info: using existing install for 'nightly-{0}' -info: the active toolchain `nightly-{0}` has been installed -info: it's active because: overridden by '{1}'", - this_host_triple(), - toolchain_file.display(), - ), - ) - .await; +info: the active toolchain `nightly-[HOST_TRIPLE]` has been installed +info: it's active because: overridden by '[TOOLCHAIN_FILE]' + +"#]]) + .is_ok(); + + cx.config + .expect(["rustup", "toolchain", "install"]) + .await + .extend_redactions([("[TOOLCHAIN_FILE]", &toolchain_file.display().to_string())]) + .with_stderr(snapbox::str![[r#" +info: using existing install for 'nightly-[HOST_TRIPLE]' +info: the active toolchain `nightly-[HOST_TRIPLE]` has been installed +info: it's active because: overridden by '[TOOLCHAIN_FILE]' + +"#]]) + .is_ok(); } #[tokio::test] async fn toolchain_update_is_like_update() { - let mut cx = CliTestContext::new(Scenario::SimpleV2).await; + let cx = CliTestContext::new(Scenario::SimpleV2).await; cx.config - .expect_ok(&["rustup", "toolchain", "update", "nightly"]) - .await; + .expect(["rustup", "toolchain", "update", "nightly"]) + .await + .is_ok(); cx.config - .expect_stdout_ok( - &["rustup", "run", "nightly", "rustc", "--version"], - "hash-nightly-2", - ) - .await; + .expect(["rustup", "run", "nightly", "rustc", "--version"]) + .await + .with_stdout(snapbox::str![[r#" +1.3.0 (hash-nightly-2) + +"#]]) + .is_ok(); } #[tokio::test] @@ -1488,46 +1723,85 @@ async fn toolchain_uninstall_is_like_uninstall() { let mut cx = CliTestContext::new(Scenario::None).await; { - let mut cx = cx.with_dist_dir(Scenario::SimpleV2); + let cx = cx.with_dist_dir(Scenario::SimpleV2); cx.config - .expect_ok(&["rustup", "toolchain", "install", "nightly"]) - .await; + .expect(["rustup", "toolchain", "install", "nightly"]) + .await + .is_ok(); } - cx.config.expect_ok(&["rustup", "default", "none"]).await; cx.config - .expect_ok(&["rustup", "uninstall", "nightly"]) - .await; + .expect(["rustup", "default", "none"]) + .await + .is_ok(); + cx.config + .expect(["rustup", "uninstall", "nightly"]) + .await + .is_ok(); cx.config - .expect_not_stdout_ok(&["rustup", "show"], for_host!("'nightly-{}'")) - .await; + .expect(["rustup", "show"]) + .await + .with_stdout(snapbox::str![[r#" +... +installed toolchains +-------------------- + +active toolchain +---------------- +no active toolchain + +"#]]) + .is_ok(); } #[tokio::test] async fn proxy_toolchain_shorthand() { - let mut cx = CliTestContext::new(Scenario::SimpleV2).await; - cx.config.expect_ok(&["rustup", "default", "stable"]).await; + let cx = CliTestContext::new(Scenario::SimpleV2).await; cx.config - .expect_ok(&["rustup", "toolchain", "update", "nightly"]) - .await; + .expect(["rustup", "default", "stable"]) + .await + .is_ok(); cx.config - .expect_stdout_ok(&["rustc", "--version"], "hash-stable-1.1.0") - .await; + .expect(["rustup", "toolchain", "update", "nightly"]) + .await + .is_ok(); cx.config - .expect_stdout_ok(&["rustc", "+stable", "--version"], "hash-stable-1.1.0") - .await; + .expect(["rustc", "--version"]) + .await + .with_stdout(snapbox::str![[r#" +1.1.0 (hash-stable-1.1.0) + +"#]]) + .is_ok(); cx.config - .expect_stdout_ok(&["rustc", "+nightly", "--version"], "hash-nightly-2") - .await; + .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 mut cx = CliTestContext::new(Scenario::SimpleV2).await; - cx.config.expect_ok(&["rustup", "default", "stable"]).await; + let cx = CliTestContext::new(Scenario::SimpleV2).await; cx.config - .expect_ok(&["rustup", "component", "add", "rust-src"]) - .await; + .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_triple() @@ -1537,128 +1811,169 @@ async fn add_component() { #[tokio::test] async fn add_component_by_target_triple() { - let mut cx = CliTestContext::new(Scenario::SimpleV2).await; - cx.config.expect_ok(&["rustup", "default", "stable"]).await; + let cx = CliTestContext::new(Scenario::SimpleV2).await; + cx.config + .expect(["rustup", "default", "stable"]) + .await + .is_ok(); cx.config - .expect_ok(&[ + .expect([ "rustup", "component", "add", &format!("rust-std-{CROSS_ARCH1}"), ]) - .await; + .await + .is_ok(); let path = format!( - "toolchains/stable-{}/lib/rustlib/{}/lib/libstd.rlib", - this_host_triple(), - CROSS_ARCH1 + "toolchains/stable-{}/lib/rustlib/{CROSS_ARCH1}/lib/libstd.rlib", + this_host_triple() ); assert!(cx.config.rustupdir.has(path)); } #[tokio::test] async fn add_component_by_target_triple_renamed_from() { - let mut cx = CliTestContext::new(Scenario::SimpleV2).await; - cx.config.expect_ok(&["rustup", "default", "nightly"]).await; + let cx = CliTestContext::new(Scenario::SimpleV2).await; cx.config - .expect_ok(&["rustup", "component", "add", for_host!("rls-{}")]) - .await; + .expect(["rustup", "default", "nightly"]) + .await + .is_ok(); cx.config - .expect_ok_contains( - &["rustup", "component", "list", "--installed"], - for_host!("rls-{}"), - "", - ) - .await; + .expect([ + "rustup", + "component", + "add", + &format!("rls-{}", this_host_triple()), + ]) + .await + .is_ok(); + cx.config + .expect(["rustup", "component", "list", "--installed"]) + .await + .with_stdout(snapbox::str![[r#" +... +rls-[HOST_TRIPLE] +... +"#]]) + .is_ok(); } #[tokio::test] async fn add_component_by_target_triple_renamed_to() { - let mut cx = CliTestContext::new(Scenario::SimpleV2).await; - cx.config.expect_ok(&["rustup", "default", "nightly"]).await; + let cx = CliTestContext::new(Scenario::SimpleV2).await; cx.config - .expect_ok(&["rustup", "component", "add", for_host!("rls-preview-{}")]) - .await; + .expect(["rustup", "default", "nightly"]) + .await + .is_ok(); cx.config - .expect_ok_contains( - &["rustup", "component", "list", "--installed"], - for_host!("rls-{}"), - "", - ) - .await; + .expect([ + "rustup", + "component", + "add", + &format!("rls-preview-{}", this_host_triple()), + ]) + .await + .is_ok(); + cx.config + .expect(["rustup", "component", "list", "--installed"]) + .await + .with_stdout(snapbox::str![[r#" +... +rls-[HOST_TRIPLE] +... +"#]]) + .is_ok(); } #[tokio::test] async fn fail_invalid_component_name() { - let mut cx = CliTestContext::new(Scenario::SimpleV2).await; - cx.config.expect_ok(&["rustup", "default", "stable"]).await; + let cx = CliTestContext::new(Scenario::SimpleV2).await; cx.config - .expect_err( - &[ - "rustup", - "component", - "add", - &format!("dummy-{CROSS_ARCH1}"), - ], - &format!( - "error: toolchain 'stable-{}' does not contain component 'dummy-{}' for target '{}'", - this_host_triple(), - CROSS_ARCH1, - this_host_triple() - ), - ) - .await; + .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_TRIPLE]' does not contain component 'dummy-[CROSS_ARCH_I]' for target '[HOST_TRIPLE]' + +"#]]) + .is_err(); } #[tokio::test] async fn fail_invalid_component_target() { - let mut cx = CliTestContext::new(Scenario::SimpleV2).await; - cx.config.expect_ok(&["rustup", "default", "stable"]).await; - cx.config.expect_err( - &[ - "rustup", - "component", - "add", - "rust-std-invalid-target", - ], - &format!("error: toolchain 'stable-{}' does not contain component 'rust-std-invalid-target' for target '{}'",this_host_triple(), this_host_triple()), - ).await; + 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_TRIPLE]' does not contain component 'rust-std-invalid-target' for target '[HOST_TRIPLE]' +... +"#]]) + .is_err(); } #[tokio::test] async fn remove_component() { - let mut cx = CliTestContext::new(Scenario::SimpleV2).await; - cx.config.expect_ok(&["rustup", "default", "stable"]).await; + let cx = CliTestContext::new(Scenario::SimpleV2).await; cx.config - .expect_ok(&["rustup", "component", "add", "rust-src"]) - .await; + .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_triple() + this_host_triple(), )); assert!(cx.config.rustupdir.has(&path)); cx.config - .expect_ok(&["rustup", "component", "remove", "rust-src"]) - .await; + .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 mut cx = CliTestContext::new(Scenario::SimpleV2).await; - cx.config.expect_ok(&["rustup", "default", "stable"]).await; + let cx = CliTestContext::new(Scenario::SimpleV2).await; + cx.config + .expect(&["rustup", "default", "stable"]) + .await + .is_ok(); cx.config - .expect_ok(&["rustup", "component", "add", &component_with_triple]) - .await; + .expect(&["rustup", "component", "add", &component_with_triple]) + .await + .is_ok(); let path = PathBuf::from(format!( - "toolchains/stable-{}/lib/rustlib/{}/lib/libstd.rlib", - this_host_triple(), - CROSS_ARCH1 + "toolchains/stable-{}/lib/rustlib/{CROSS_ARCH1}/lib/libstd.rlib", + this_host_triple() )); assert!(cx.config.rustupdir.has(&path)); cx.config - .expect_ok(&["rustup", "component", "remove", &component_with_triple]) - .await; + .expect(&["rustup", "component", "remove", &component_with_triple]) + .await + .is_ok(); assert!(!cx.config.rustupdir.has(path.parent().unwrap())); } @@ -1673,10 +1988,13 @@ async fn add_remove_multiple_components() { let component_with_triple1 = format!("rust-std-{CROSS_ARCH1}"); let component_with_triple2 = format!("rust-std-{CROSS_ARCH2}"); - let mut cx = CliTestContext::new(Scenario::SimpleV2).await; - cx.config.expect_ok(&["rustup", "default", "nightly"]).await; + let cx = CliTestContext::new(Scenario::SimpleV2).await; + cx.config + .expect(&["rustup", "default", "nightly"]) + .await + .is_ok(); cx.config - .expect_ok(&[ + .expect(&[ "rustup", "component", "add", @@ -1685,13 +2003,14 @@ async fn add_remove_multiple_components() { &component_with_triple1, &component_with_triple2, ]) - .await; + .await + .is_ok(); for file in &files { let path = format!("toolchains/nightly-{}/{}", this_host_triple(), file); assert!(cx.config.rustupdir.has(&path)); } cx.config - .expect_ok(&[ + .expect(&[ "rustup", "component", "remove", @@ -1700,7 +2019,8 @@ async fn add_remove_multiple_components() { &component_with_triple1, &component_with_triple2, ]) - .await; + .await + .is_ok(); for file in &files { let path = PathBuf::from(format!( "toolchains/nightly-{}/{}", @@ -1713,32 +2033,50 @@ async fn add_remove_multiple_components() { #[tokio::test] async fn file_override() { - let mut cx = CliTestContext::new(Scenario::SimpleV2).await; - cx.config.expect_ok(&["rustup", "default", "stable"]).await; + let cx = CliTestContext::new(Scenario::SimpleV2).await; cx.config - .expect_ok(&["rustup", "toolchain", "install", "nightly"]) - .await; + .expect(&["rustup", "default", "stable"]) + .await + .is_ok(); + cx.config + .expect(&["rustup", "toolchain", "install", "nightly"]) + .await + .is_ok(); cx.config - .expect_stdout_ok(&["rustc", "--version"], "hash-stable-1.1.0") - .await; + .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_stdout_ok(&["rustc", "--version"], "hash-nightly-2") - .await; + .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 mut cx = CliTestContext::new(Scenario::SimpleV2).await; - cx.config.expect_ok(&["rustup", "default", "stable"]).await; + let cx = CliTestContext::new(Scenario::SimpleV2).await; cx.config - .expect_ok(&["rustup", "toolchain", "install", "nightly"]) - .await; + .expect(&["rustup", "default", "stable"]) + .await + .is_ok(); + cx.config + .expect(&["rustup", "toolchain", "install", "nightly"]) + .await + .is_ok(); let toolchain_path = cx .config @@ -1746,75 +2084,93 @@ async fn env_override_path() { .join("toolchains") .join(format!("nightly-{}", this_host_triple())); - let out = cx - .config - .run( - "rustc", - ["--version"], - &[("RUSTUP_TOOLCHAIN", toolchain_path.to_str().unwrap())], + cx.config + .expect_with_env( + ["rustc", "--version"], + [("RUSTUP_TOOLCHAIN", toolchain_path.to_str().unwrap())], ) - .await; - assert!(out.ok); - assert!(out.stdout.contains("hash-nightly-2")); + .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 mut cx = CliTestContext::new(Scenario::SimpleV2).await; - cx.config.expect_ok(&["rustup", "default", "stable"]).await; + let cx = CliTestContext::new(Scenario::SimpleV2).await; cx.config - .expect_ok(&["rustup", "toolchain", "install", "nightly"]) - .await; + .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_triple())); cx.config - .expect_err( - &[ - "rustc", - format!("+{}", toolchain_path.to_str().unwrap()).as_str(), - "--version", - ], - "error: relative path toolchain", - ) - .await; + .expect([ + "rustc", + format!("+{}", toolchain_path.to_str().unwrap()).as_str(), + "--version", + ]) + .await + .with_stderr(snapbox::str![[r#" +error: relative path toolchain '[..]/toolchains/nightly-[HOST_TRIPLE]' + +"#]]) + .is_err(); } #[tokio::test] async fn run_with_relpath_is_not_supported() { - let mut cx = CliTestContext::new(Scenario::SimpleV2).await; - cx.config.expect_ok(&["rustup", "default", "stable"]).await; + let cx = CliTestContext::new(Scenario::SimpleV2).await; cx.config - .expect_ok(&["rustup", "toolchain", "install", "nightly"]) - .await; + .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_triple())); cx.config - .expect_err( - &[ - "rustup", - "run", - toolchain_path.to_str().unwrap(), - "rustc", - "--version", - ], - "relative path toolchain", - ) - .await; + .expect([ + "rustup", + "run", + toolchain_path.to_str().unwrap(), + "rustc", + "--version", + ]) + .await + .with_stderr(snapbox::str![[r#" +... +error:[..] relative path toolchain '[..]/toolchains/nightly-[HOST_TRIPLE]' +... +"#]]) + .is_err(); } #[tokio::test] async fn plus_override_abspath_is_supported() { - let mut cx = CliTestContext::new(Scenario::SimpleV2).await; - cx.config.expect_ok(&["rustup", "default", "stable"]).await; + let cx = CliTestContext::new(Scenario::SimpleV2).await; cx.config - .expect_ok(&["rustup", "toolchain", "install", "nightly"]) - .await; + .expect(["rustup", "default", "stable"]) + .await + .is_ok(); + cx.config + .expect(["rustup", "toolchain", "install", "nightly"]) + .await + .is_ok(); let toolchain_path = cx .config @@ -1824,21 +2180,26 @@ async fn plus_override_abspath_is_supported() { .canonicalize() .unwrap(); cx.config - .expect_ok(&[ + .expect([ "rustc", format!("+{}", toolchain_path.to_str().unwrap()).as_str(), "--version", ]) - .await; + .await + .is_ok(); } #[tokio::test] async fn run_with_abspath_is_supported() { - let mut cx = CliTestContext::new(Scenario::SimpleV2).await; - cx.config.expect_ok(&["rustup", "default", "stable"]).await; + let cx = CliTestContext::new(Scenario::SimpleV2).await; + cx.config + .expect(["rustup", "default", "stable"]) + .await + .is_ok(); cx.config - .expect_ok(&["rustup", "toolchain", "install", "nightly"]) - .await; + .expect(["rustup", "toolchain", "install", "nightly"]) + .await + .is_ok(); let toolchain_path = cx .config @@ -1848,23 +2209,28 @@ async fn run_with_abspath_is_supported() { .canonicalize() .unwrap(); cx.config - .expect_ok(&[ + .expect([ "rustup", "run", toolchain_path.to_str().unwrap(), "rustc", "--version", ]) - .await; + .await + .is_ok(); } #[tokio::test] async fn file_override_path() { - let mut cx = CliTestContext::new(Scenario::SimpleV2).await; - cx.config.expect_ok(&["rustup", "default", "stable"]).await; + let cx = CliTestContext::new(Scenario::SimpleV2).await; cx.config - .expect_ok(&["rustup", "toolchain", "install", "nightly"]) - .await; + .expect(["rustup", "default", "stable"]) + .await + .is_ok(); + cx.config + .expect(["rustup", "toolchain", "install", "nightly"]) + .await + .is_ok(); let toolchain_path = cx .config @@ -1879,25 +2245,36 @@ async fn file_override_path() { .unwrap(); cx.config - .expect_stdout_ok(&["rustc", "--version"], "hash-nightly-2") - .await; + .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_stdout_ok( - &["rustup", "show", "active-toolchain"], - &format!("nightly-{}", this_host_triple()), - ) - .await; + .expect(["rustup", "show", "active-toolchain"]) + .await + .with_stdout(snapbox::str![[r#" +[..]/toolchains/nightly-[HOST_TRIPLE] (overridden by '[..]/rust-toolchain.toml') + +"#]]) + .is_ok(); } #[tokio::test] async fn proxy_override_path() { - let mut cx = CliTestContext::new(Scenario::SimpleV2).await; - cx.config.expect_ok(&["rustup", "default", "stable"]).await; + let cx = CliTestContext::new(Scenario::SimpleV2).await; + cx.config + .expect(["rustup", "default", "stable"]) + .await + .is_ok(); cx.config - .expect_ok(&["rustup", "toolchain", "install", "nightly"]) - .await; + .expect(["rustup", "toolchain", "install", "nightly"]) + .await + .is_ok(); let toolchain_path = cx .config @@ -1912,17 +2289,26 @@ async fn proxy_override_path() { .unwrap(); cx.config - .expect_stdout_ok(&["cargo", "--call-rustc"], "hash-nightly-2") - .await; + .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_ok(&["rustup", "default", "stable"]).await; cx.config - .expect_ok(&["rustup", "toolchain", "install", "nightly"]) - .await; + .expect(["rustup", "default", "stable"]) + .await + .is_ok(); + cx.config + .expect(["rustup", "toolchain", "install", "nightly"]) + .await + .is_ok(); let toolchain_path = cx .config @@ -1965,8 +2351,13 @@ async fn file_override_path_relative_not_supported() { let cx = cx.change_dir(&ephemeral); cx.config - .expect_err(&["rustc", "--version"], "relative path toolchain") - .await; + .expect(["rustc", "--version"]) + .await + .with_stderr(snapbox::str![[r#" +error: relative path toolchain '[..]/toolchains/nightly-[HOST_TRIPLE]' + +"#]]) + .is_err(); } #[tokio::test] @@ -1986,11 +2377,13 @@ async fn file_override_path_no_options() { .unwrap(); cx.config - .expect_err( - &["rustc", "--version"], - "toolchain options are ignored for path toolchain (ephemeral)", - ) - .await; + .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, @@ -1999,11 +2392,13 @@ async fn file_override_path_no_options() { .unwrap(); cx.config - .expect_err( - &["rustc", "--version"], - "toolchain options are ignored for path toolchain (ephemeral)", - ) - .await; + .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, @@ -2012,11 +2407,13 @@ async fn file_override_path_no_options() { .unwrap(); cx.config - .expect_err( - &["rustc", "--version"], - "toolchain options are ignored for path toolchain (ephemeral)", - ) - .await; + .expect(["rustc", "--version"]) + .await + .with_stderr(snapbox::str![[r#" +error: toolchain options are ignored for path toolchain (ephemeral) + +"#]]) + .is_err(); } #[tokio::test] @@ -2036,24 +2433,34 @@ async fn file_override_path_xor_channel() { .unwrap(); cx.config - .expect_err( - &["rustc", "--version"], - "cannot specify both channel (nightly) and path (ephemeral) simultaneously", - ) - .await; + .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_ok(&["rustup", "default", "stable"]).await; cx.config - .expect_ok(&["rustup", "toolchain", "install", "nightly"]) - .await; + .expect(["rustup", "default", "stable"]) + .await + .is_ok(); + cx.config + .expect(["rustup", "toolchain", "install", "nightly"]) + .await + .is_ok(); cx.config - .expect_stdout_ok(&["rustc", "--version"], "hash-stable-1.1.0") - .await; + .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"); @@ -2063,8 +2470,13 @@ async fn file_override_subdir() { fs::create_dir_all(&subdir).unwrap(); let cx = cx.change_dir(&subdir); cx.config - .expect_stdout_ok(&["rustc", "--version"], "hash-nightly-2") - .await; + .expect(["rustc", "--version"]) + .await + .with_stdout(snapbox::str![[r#" +1.3.0 (hash-nightly-2) + +"#]]) + .is_ok(); } #[tokio::test] @@ -2072,26 +2484,40 @@ async fn file_override_with_archive() { let mut cx = CliTestContext::new(Scenario::None).await; { - let mut cx = cx.with_dist_dir(Scenario::SimpleV2); - cx.config.expect_ok(&["rustup", "default", "stable"]).await; + let cx = cx.with_dist_dir(Scenario::SimpleV2); + cx.config + .expect(["rustup", "default", "stable"]) + .await + .is_ok(); } - let mut cx = cx.with_dist_dir(Scenario::ArchivesV2_2015_01_01); + let cx = cx.with_dist_dir(Scenario::ArchivesV2_2015_01_01); cx.config - .expect_ok(&["rustup", "toolchain", "install", "nightly-2015-01-01"]) - .await; + .expect(["rustup", "toolchain", "install", "nightly-2015-01-01"]) + .await + .is_ok(); cx.config - .expect_stdout_ok(&["rustc", "--version"], "hash-stable-1.1.0") - .await; + .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_stdout_ok(&["rustc", "--version"], "hash-nightly-1") - .await; + .expect(["rustc", "--version"]) + .await + .with_stdout(snapbox::str![[r#" +1.2.0 (hash-nightly-1) + +"#]]) + .is_ok(); } #[tokio::test] @@ -2099,18 +2525,27 @@ async fn file_override_toml_format_select_installed_toolchain() { let mut cx = CliTestContext::new(Scenario::None).await; { - let mut cx = cx.with_dist_dir(Scenario::SimpleV2); - cx.config.expect_ok(&["rustup", "default", "stable"]).await; + let cx = cx.with_dist_dir(Scenario::SimpleV2); + cx.config + .expect(["rustup", "default", "stable"]) + .await + .is_ok(); } - let mut cx = cx.with_dist_dir(Scenario::ArchivesV2_2015_01_01); + let cx = cx.with_dist_dir(Scenario::ArchivesV2_2015_01_01); cx.config - .expect_ok(&["rustup", "toolchain", "install", "nightly-2015-01-01"]) - .await; + .expect(["rustup", "toolchain", "install", "nightly-2015-01-01"]) + .await + .is_ok(); cx.config - .expect_stdout_ok(&["rustc", "--version"], "hash-stable-1.1.0") - .await; + .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"); @@ -2124,8 +2559,13 @@ channel = "nightly-2015-01-01" .unwrap(); cx.config - .expect_stdout_ok(&["rustc", "--version"], "hash-nightly-1") - .await; + .expect(["rustc", "--version"]) + .await + .with_stdout(snapbox::str![[r#" +1.2.0 (hash-nightly-1) + +"#]]) + .is_ok(); } #[tokio::test] @@ -2133,17 +2573,27 @@ async fn file_override_toml_format_install_both_toolchain_and_components() { let mut cx = CliTestContext::new(Scenario::None).await; { - let mut cx = cx.with_dist_dir(Scenario::SimpleV2); - cx.config.expect_ok(&["rustup", "default", "stable"]).await; + let cx = cx.with_dist_dir(Scenario::SimpleV2); + cx.config + .expect(["rustup", "default", "stable"]) + .await + .is_ok(); } - let mut cx = cx.with_dist_dir(Scenario::ArchivesV2_2015_01_01); + let cx = cx.with_dist_dir(Scenario::ArchivesV2_2015_01_01); cx.config - .expect_stdout_ok(&["rustc", "--version"], "hash-stable-1.1.0") - .await; + .expect(["rustc", "--version"]) + .await + .with_stdout(snapbox::str![[r#" +1.1.0 (hash-stable-1.1.0) + +"#]]) + .is_ok(); cx.config - .expect_not_stdout_ok(&["rustup", "component", "list"], "rust-src (installed)") - .await; + .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"); @@ -2158,23 +2608,40 @@ components = [ "rust-src" ] .unwrap(); cx.config - .expect_ok(&["rustup", "toolchain", "install"]) - .await; + .expect(["rustup", "toolchain", "install"]) + .await + .is_ok(); cx.config - .expect_stdout_ok(&["rustc", "--version"], "hash-nightly-1") - .await; + .expect(["rustc", "--version"]) + .await + .with_stdout(snapbox::str![[r#" +1.2.0 (hash-nightly-1) + +"#]]) + .is_ok(); cx.config - .expect_stdout_ok(&["rustup", "component", "list"], "rust-src (installed)") - .await; + .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 mut cx = CliTestContext::new(Scenario::SimpleV2).await; - cx.config.expect_ok(&["rustup", "default", "stable"]).await; + let cx = CliTestContext::new(Scenario::SimpleV2).await; cx.config - .expect_not_stdout_ok(&["rustup", "component", "list"], "rust-src (installed)") - .await; + .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"); @@ -2188,56 +2655,78 @@ components = [ "rust-src" ] .unwrap(); cx.config - .expect_stderr_ok( - &["rustup", "toolchain", "install"], - "info: installing component 'rust-src'", - ) - .await; + .expect(["rustup", "toolchain", "install"]) + .await + .with_stderr(snapbox::str![[r#" +... +info: installing component 'rust-src' +... +"#]]) + .is_ok(); cx.config - .expect_stdout_ok(&["rustup", "component", "list"], "rust-src (installed)") - .await; + .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 mut cx = CliTestContext::new(Scenario::SimpleV2).await; - cx.config.expect_ok(&["rustup", "default", "stable"]).await; + let cx = CliTestContext::new(Scenario::SimpleV2).await; cx.config - .expect_not_stdout_ok( - &["rustup", "component", "list"], - "arm-linux-androideabi (installed)", - ) - .await; + .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, - r#" + &format!( + r#" [toolchain] -targets = [ "arm-linux-androideabi" ] +targets = [ "{CROSS_ARCH2}" ] "#, + ), ) .unwrap(); cx.config - .expect_stderr_ok( - &["rustup", "toolchain", "install"], - "info: installing component 'rust-std' for 'arm-linux-androideabi'", - ) - .await; + .expect(["rustup", "toolchain", "install"]) + .await + .with_stderr(snapbox::str![[r#" +... +info: installing component 'rust-std' for '[CROSS_ARCH_II]' +... +"#]]) + .is_ok(); cx.config - .expect_stdout_ok( - &["rustup", "component", "list"], - "arm-linux-androideabi (installed)", - ) - .await; + .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 mut cx = CliTestContext::new(Scenario::SimpleV2).await; - cx.config.expect_ok(&["rustup", "default", "stable"]).await; + 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"); @@ -2251,25 +2740,32 @@ components = [ "rust-bongo" ] .unwrap(); cx.config - .expect_stderr_ok( - &["rustup", "toolchain", "install"], - "warn: Force-skipping unavailable component 'rust-bongo", - ) - .await; + .expect(&["rustup", "toolchain", "install"]) + .await + .with_stderr(snapbox::str![[r#" +... +warn: Force-skipping unavailable component 'rust-bongo-[HOST_TRIPLE]' +... +"#]]) + .is_ok(); } #[tokio::test] async fn file_override_toml_format_specify_profile() { - let mut cx = CliTestContext::new(Scenario::SimpleV2).await; + let cx = CliTestContext::new(Scenario::SimpleV2).await; cx.config - .expect_ok(&["rustup", "set", "profile", "default"]) - .await; + .expect(&["rustup", "set", "profile", "default"]) + .await + .is_ok(); cx.config - .expect_stderr_ok( - &["rustup", "default", "stable"], - "downloading component 'rust-docs'", - ) - .await; + .expect(&["rustup", "default", "stable"]) + .await + .with_stderr(snapbox::str![[r#" +... +info: downloading component 'rust-docs' +... +"#]]) + .is_ok(); let cwd = cx.config.current_dir(); let toolchain_file = cwd.join("rust-toolchain"); @@ -2283,23 +2779,32 @@ channel = "nightly" ) .unwrap(); cx.config - .expect_ok(&["rustup", "toolchain", "install"]) - .await; + .expect(&["rustup", "toolchain", "install"]) + .await + .is_ok(); cx.config - .expect_not_stdout_ok( - &["rustup", "component", "list"], - for_host!("rust-docs-{} (installed)"), - ) - .await; + .expect(&["rustup", "component", "list"]) + .await + // The `rust-docs-[HOST_TRIPLE]` component is not installed. + .with_stdout(snapbox::str![[r#" +... +rust-docs-[HOST_TRIPLE] +... +"#]]) + .is_ok(); } #[tokio::test] async fn default_profile_is_respected_with_rust_toolchain_file() { - let mut cx = CliTestContext::new(Scenario::SimpleV2).await; + let cx = CliTestContext::new(Scenario::SimpleV2).await; + cx.config + .expect(&["rustup", "set", "profile", "minimal"]) + .await + .is_ok(); cx.config - .expect_ok(&["rustup", "set", "profile", "minimal"]) - .await; - cx.config.expect_ok(&["rustup", "default", "stable"]).await; + .expect(&["rustup", "default", "stable"]) + .await + .is_ok(); let cwd = cx.config.current_dir(); let toolchain_file = cwd.join("rust-toolchain"); @@ -2312,33 +2817,48 @@ channel = "nightly" ) .unwrap(); cx.config - .expect_ok(&["rustup", "toolchain", "install"]) - .await; + .expect(&["rustup", "toolchain", "install"]) + .await + .is_ok(); cx.config - .expect_not_stdout_ok( - &["rustup", "component", "list"], - for_host!("rust-docs-{} (installed)"), - ) - .await; + .expect(&["rustup", "component", "list"]) + .await + .with_stdout(snapbox::str![[r#" +... +rust-docs-[HOST_TRIPLE] +... +"#]]) + .is_ok(); } #[tokio::test] async fn close_file_override_beats_far_directory_override() { let mut cx = CliTestContext::new(Scenario::SimpleV2).await; - cx.config.expect_ok(&["rustup", "default", "stable"]).await; cx.config - .expect_ok(&["rustup", "toolchain", "install", "beta"]) - .await; + .expect(&["rustup", "default", "stable"]) + .await + .is_ok(); + cx.config + .expect(&["rustup", "toolchain", "install", "beta"]) + .await + .is_ok(); cx.config - .expect_ok(&["rustup", "toolchain", "install", "nightly"]) - .await; + .expect(&["rustup", "toolchain", "install", "nightly"]) + .await + .is_ok(); cx.config - .expect_ok(&["rustup", "override", "set", "beta"]) - .await; + .expect(["rustup", "override", "set", "beta"]) + .await + .is_ok(); cx.config - .expect_stdout_ok(&["rustc", "--version"], "hash-beta-1.2.0") - .await; + .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(); @@ -2350,14 +2870,19 @@ async fn close_file_override_beats_far_directory_override() { let cx = cx.change_dir(&subdir); cx.config - .expect_stdout_ok(&["rustc", "--version"], "hash-nightly-2") - .await; + .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 mut cx = CliTestContext::new(Scenario::ArchivesV2).await; + let cx = CliTestContext::new(Scenario::ArchivesV2).await; let host = this_host_triple(); // give each override type a different toolchain let default_tc = &format!("beta-2015-01-01-{host}"); @@ -2366,32 +2891,55 @@ async fn override_order() { let file_tc = &format!("stable-2015-01-02-{host}"); let command_tc = &format!("nightly-2015-01-01-{host}"); cx.config - .expect_ok(&["rustup", "install", default_tc]) - .await; - cx.config.expect_ok(&["rustup", "install", env_tc]).await; - cx.config.expect_ok(&["rustup", "install", dir_tc]).await; - cx.config.expect_ok(&["rustup", "install", file_tc]).await; + .expect(["rustup", "install", default_tc]) + .await + .is_ok(); + cx.config + .expect(["rustup", "install", env_tc]) + .await + .is_ok(); cx.config - .expect_ok(&["rustup", "install", command_tc]) - .await; + .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_ok(&["rustup", "default", "none"]).await; cx.config - .expect_err_ex( - &["rustup", "show", "active-toolchain"], - "", - "error: no active toolchain\n", - ) - .await; + .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_ok(&["rustup", "default", default_tc]) - .await; + .expect(["rustup", "default", default_tc]) + .await + .is_ok(); cx.config - .expect_stdout_ok(&["rustup", "show", "active-toolchain"], default_tc) - .await; + .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"); @@ -2401,112 +2949,162 @@ async fn override_order() { ) .unwrap(); cx.config - .expect_stdout_ok(&["rustup", "show", "active-toolchain"], file_tc) - .await; + .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_ok(&["rustup", "override", "set", dir_tc]) - .await; + .expect(["rustup", "override", "set", dir_tc]) + .await + .is_ok(); cx.config - .expect_stdout_ok(&["rustup", "show", "active-toolchain"], dir_tc) - .await; + .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 - let out = cx - .config - .run( - "rustup", - ["show", "active-toolchain"], - &[("RUSTUP_TOOLCHAIN", env_tc)], + cx.config + .expect_with_env( + ["rustup", "show", "active-toolchain"], + [("RUSTUP_TOOLCHAIN", &**env_tc)], ) - .await; - assert!(out.ok); - assert!(out.stdout.contains(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 - let out = cx - .config - .run( - "rustup", - [&format!("+{command_tc}"), "show", "active-toolchain"], - &[("RUSTUP_TOOLCHAIN", env_tc)], + cx.config + .expect_with_env( + [ + "rustup", + &format!("+{command_tc}"), + "show", + "active-toolchain", + ], + &[("RUSTUP_TOOLCHAIN", &**env_tc)], ) - .await; - assert!(out.ok); - assert!(out.stdout.contains(command_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 directory_override_doesnt_need_to_exist_unless_it_is_selected() { - let mut cx = CliTestContext::new(Scenario::SimpleV2).await; - cx.config.expect_ok(&["rustup", "default", "stable"]).await; + let cx = CliTestContext::new(Scenario::SimpleV2).await; + cx.config + .expect(["rustup", "default", "stable"]) + .await + .is_ok(); cx.config - .expect_ok(&["rustup", "toolchain", "install", "beta"]) - .await; + .expect(["rustup", "toolchain", "install", "beta"]) + .await + .is_ok(); // not installing nightly cx.config - .expect_ok(&["rustup", "override", "set", "beta"]) - .await; + .expect(["rustup", "override", "set", "beta"]) + .await + .is_ok(); cx.config - .expect_stdout_ok(&["rustc", "--version"], "hash-beta-1.2.0") - .await; + .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_stdout_ok(&["rustc", "--version"], "hash-beta-1.2.0") - .await; + .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 mut cx = CliTestContext::new(Scenario::SimpleV2).await; - cx.config.expect_ok(&["rustup", "default", "stable"]).await; + let cx = CliTestContext::new(Scenario::SimpleV2).await; cx.config - .expect_ok(&["rustup", "toolchain", "install", "beta"]) - .await; + .expect(["rustup", "default", "stable"]) + .await + .is_ok(); cx.config - .expect_ok(&["rustup", "toolchain", "install", "nightly"]) - .await; + .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(); - let mut cmd = cx.config.cmd("rustc", ["--version"]); - cx.config.env(&mut cmd); - cmd.env("RUSTUP_TOOLCHAIN", "beta"); + cx.config + .expect_with_env(["rustc", "--version"], [("RUSTUP_TOOLCHAIN", "beta")]) + .await + .with_stdout(snapbox::str![[r#" +1.2.0 (hash-beta-1.2.0) - let out = cmd.output().unwrap(); - assert!( - String::from_utf8(out.stdout) - .unwrap() - .contains("hash-beta-1.2.0") - ); +"#]]) + .is_ok(); } #[tokio::test] async fn plus_override_beats_file_override() { - let mut cx = CliTestContext::new(Scenario::SimpleV2).await; - cx.config.expect_ok(&["rustup", "default", "stable"]).await; + let cx = CliTestContext::new(Scenario::SimpleV2).await; + cx.config + .expect(["rustup", "default", "stable"]) + .await + .is_ok(); cx.config - .expect_ok(&["rustup", "toolchain", "install", "beta"]) - .await; + .expect(["rustup", "toolchain", "install", "beta"]) + .await + .is_ok(); cx.config - .expect_ok(&["rustup", "toolchain", "install", "nightly"]) - .await; + .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_stdout_ok(&["rustc", "+beta", "--version"], "hash-beta-1.2.0") - .await; + .expect(["rustc", "+beta", "--version"]) + .await + .with_stdout(snapbox::str![[r#" +1.2.0 (hash-beta-1.2.0) + +"#]]) + .is_ok(); } #[tokio::test] @@ -2517,17 +3115,23 @@ async fn file_override_not_installed_custom() { raw::write_file(&toolchain_file, "gumbo").unwrap(); cx.config - .expect_err( - &["rustup", "show", "active-toolchain"], - "custom toolchain 'gumbo' specified in override file", - ) - .await; + .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_err( - &["rustc", "--version"], - "custom toolchain 'gumbo' specified in override file", - ) - .await; + .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] @@ -2538,17 +3142,23 @@ async fn file_override_not_installed_custom_toml() { raw::write_file(&toolchain_file, r#"toolchain.channel = "i-am-the-walrus""#).unwrap(); cx.config - .expect_err( - &["rustup", "show", "active-toolchain"], - "custom toolchain 'i-am-the-walrus' specified in override file", - ) - .await; + .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_err( - &["rustc", "--version"], - "custom toolchain 'i-am-the-walrus' specified in override file", - ) - .await; + .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] @@ -2560,11 +3170,14 @@ async fn bad_file_override() { raw::write_file(&toolchain_file, "none").unwrap(); cx.config - .expect_err( - &["rustc", "--version"], - "invalid toolchain name detected in override file", - ) - .await; + .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 @@ -2579,47 +3192,58 @@ async fn bad_file_override_with_manip() { ).unwrap(); cx.config - .expect_err( - &["rustup", "show", "active-toolchain"], - "invalid toolchain name detected in override file", - ) - .await; + .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_err( - &["rustc", "--version"], - "invalid toolchain name detected in override file", - ) - .await; + .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 mut cx = CliTestContext::new(Scenario::SimpleV2).await; + let cx = CliTestContext::new(Scenario::SimpleV2).await; let cwd = cx.config.current_dir(); let toolchain_file = cwd.join("rust-toolchain"); - cx.config.expect_ok(&["rustup", "default", "nightly"]).await; + cx.config + .expect(&["rustup", "default", "nightly"]) + .await + .is_ok(); + let nightly_with_host = format!("nightly-{}", this_host_triple()); raw::write_file(&toolchain_file, "nightly").unwrap(); - cx.config.expect_ok(&["rustc", "--version"]).await; + cx.config.expect(&["rustc", "--version"]).await.is_ok(); // Special case: same version as is installed is permitted. - raw::write_file(&toolchain_file, for_host!("nightly-{}")).unwrap(); - cx.config.expect_ok(&["rustc", "--version"]).await; + 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(for_host!("nightly-{}")); + .join(&nightly_with_host); cx.config - .expect_ok(&[ + .expect(&[ "rustup", "toolchain", "link", "system", &format!("{}", fullpath.display()), ]) - .await; + .await + .is_ok(); raw::write_file(&toolchain_file, "system").unwrap(); - cx.config.expect_ok(&["rustc", "--version"]).await; + cx.config.expect(&["rustc", "--version"]).await.is_ok(); } #[tokio::test] @@ -2632,87 +3256,120 @@ async fn file_override_with_target_info() { raw::write_file(&toolchain_file, "nightly-x86_64-unknown-linux-gnu").unwrap(); cx.config - .expect_err( - &["rustc", "--version"], - "target triple in channel name 'nightly-x86_64-unknown-linux-gnu'", - ) - .await; + .expect(["rustc", "--version"]) + .await + .remove_redactions(["[HOST_TRIPLE]"]) + .with_stderr(snapbox::str![[r#" +... +error: target triple in channel name 'nightly-x86_64-unknown-linux-gnu' +... +"#]]) + .is_err(); } #[tokio::test] async fn docs_with_path() { - let mut cx = CliTestContext::new(Scenario::SimpleV2).await; - cx.config.expect_ok(&["rustup", "default", "stable"]).await; + let cx = CliTestContext::new(Scenario::SimpleV2).await; cx.config - .expect_ok(&["rustup", "toolchain", "install", "nightly"]) - .await; + .expect(&["rustup", "default", "stable"]) + .await + .is_ok(); + cx.config + .expect(&["rustup", "toolchain", "install", "nightly"]) + .await + .is_ok(); - let mut cmd = cx.config.cmd("rustup", ["doc", "--path"]); - cx.config.env(&mut cmd); + cx.config + .expect(["rustup", "doc", "--path"]) + .await + .with_stdout(snapbox::str![[r#" +[..]/toolchains/stable-[HOST_TRIPLE]/share/doc/rust/html/index.html - let out = cmd.output().unwrap(); - let path = format!("share{MAIN_SEPARATOR}doc{MAIN_SEPARATOR}rust{MAIN_SEPARATOR}html"); - assert!(String::from_utf8(out.stdout).unwrap().contains(&path)); +"#]]) + .is_ok(); cx.config - .expect_stdout_ok( - &["rustup", "doc", "--path", "--toolchain", "nightly"], - "nightly", - ) - .await; + .expect(["rustup", "doc", "--path", "--toolchain", "nightly"]) + .await + .with_stdout(snapbox::str![[r#" +[..]/toolchains/nightly-[HOST_TRIPLE]/share/doc/rust/html/index.html + +"#]]) + .is_ok(); } #[tokio::test] async fn docs_topical_with_path() { - let mut cx = CliTestContext::new(Scenario::SimpleV2).await; - cx.config.expect_ok(&["rustup", "default", "stable"]).await; + let cx = CliTestContext::new(Scenario::SimpleV2).await; + cx.config + .expect(["rustup", "default", "stable"]) + .await + .is_ok(); cx.config - .expect_ok(&["rustup", "toolchain", "install", "nightly"]) - .await; + .expect(["rustup", "toolchain", "install", "nightly"]) + .await + .is_ok(); for (args, path) in topical_doc_data::test_cases() { - let mut cmd = cx - .config - .cmd("rustup", ["doc", "--path"].iter().chain(args.iter())); - cx.config.env(&mut cmd); - - let out = cmd.output().unwrap(); - eprintln!("{:?}", String::from_utf8(out.stderr).unwrap()); - let out_str = String::from_utf8(out.stdout).unwrap(); - assert!( - out_str.contains(&path), - "comparing path\nargs: '{args:?}'\nexpected path: '{path}'\noutput: {out_str}\n\n\n", - ); + 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_TRIPLE]/[PATH] + +"#]]) + .with_stderr(snapbox::str![""]); } } #[tokio::test] async fn docs_missing() { - let mut cx = CliTestContext::new(Scenario::SimpleV2).await; + let cx = CliTestContext::new(Scenario::SimpleV2).await; cx.config - .expect_ok(&["rustup", "set", "profile", "minimal"]) - .await; - cx.config.expect_ok(&["rustup", "default", "nightly"]).await; + .expect(["rustup", "set", "profile", "minimal"]) + .await + .is_ok(); cx.config - .expect_err( - &["rustup", "doc"], - "error: unable to view documentation which is not installed", - ) - .await; + .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_TRIPLE]` +info: To install, try `rustup component add --toolchain nightly-[HOST_TRIPLE] rust-docs` +error: unable to view documentation which is not installed + +"#]]) + .is_err(); } #[tokio::test] async fn docs_custom() { - let mut cx = CliTestContext::new(Scenario::None).await; + let cx = CliTestContext::new(Scenario::None).await; let path = cx.config.customdir.join("custom-1"); let path = path.to_string_lossy(); cx.config - .expect_ok(&["rustup", "toolchain", "link", "custom", &path]) - .await; - cx.config.expect_ok(&["rustup", "default", "custom"]).await; + .expect(["rustup", "toolchain", "link", "custom", &path]) + .await + .is_ok(); cx.config - .expect_stdout_ok(&["rustup", "doc", "--path"], "custom") - .await; + .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)] @@ -2721,21 +3378,26 @@ async fn non_utf8_arg() { use std::ffi::OsStr; use std::os::unix::ffi::OsStrExt; - let mut cx = CliTestContext::new(Scenario::SimpleV2).await; - cx.config.expect_ok(&["rustup", "default", "nightly"]).await; - let out = cx - .config - .run( - "rustc", + 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")], + [("RUST_BACKTRACE", "1")], ) - .await; - assert!(out.stderr.contains("echoed non-utf8 arg")); + .await + .with_stderr(snapbox::str![[r#" +echoed non-utf8 arg: +... +"#]]); } #[cfg(windows)] @@ -2744,21 +3406,26 @@ async fn non_utf8_arg() { use std::ffi::OsString; use std::os::windows::ffi::OsStringExt; - let mut cx = CliTestContext::new(Scenario::SimpleV2).await; - cx.config.expect_ok(&["rustup", "default", "nightly"]).await; - let out = cx - .config - .run( - "rustc", + let cx = CliTestContext::new(Scenario::SimpleV2).await; + cx.config + .expect(["rustup", "default", "nightly"]) + .await + .is_ok(); + cx.config + .expect_with_env( [ - OsString::from("--echo-args".to_string()), - OsString::from("echoed non-utf8 arg:".to_string()), + OsString::from("rustc"), + OsString::from("--echo-args"), + OsString::from("echoed non-utf8 arg:"), OsString::from_wide(&[0xd801, 0xd801]), ], - &[("RUST_BACKTRACE", "1")], + [("RUST_BACKTRACE", "1")], ) - .await; - assert!(out.stderr.contains("echoed non-utf8 arg")); + .await + .with_stderr(snapbox::str![[r#" +echoed non-utf8 arg: +... +"#]]); } #[cfg(unix)] @@ -2767,17 +3434,22 @@ async fn non_utf8_toolchain() { use std::ffi::OsStr; use std::os::unix::ffi::OsStrExt; - let mut cx = CliTestContext::new(Scenario::SimpleV2).await; - cx.config.expect_ok(&["rustup", "default", "nightly"]).await; - let out = cx - .config - .run( - "rustc", - [OsStr::from_bytes(b"+\xc3\x28")], - &[("RUST_BACKTRACE", "1")], + 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; - assert!(out.stderr.contains("toolchain '�(' is not installed")); + .await + .with_stderr(snapbox::str![[r#" +... +error: toolchain '�(' is not installed +... +"#]]); } #[cfg(windows)] @@ -2786,17 +3458,25 @@ async fn non_utf8_toolchain() { use std::ffi::OsString; use std::os::windows::ffi::OsStringExt; - let mut cx = CliTestContext::new(Scenario::SimpleV2).await; - cx.config.expect_ok(&["rustup", "default", "nightly"]).await; - let out = cx - .config - .run( - "rustc", - [OsString::from_wide(&[u16::from(b'+'), 0xd801, 0xd801])], - &[("RUST_BACKTRACE", "1")], + 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; - assert!(out.stderr.contains("toolchain '��' is not installed")); + .await + .with_stderr(snapbox::str![[r#" +... +error: toolchain '��' is not installed +... +"#]]); } #[tokio::test] @@ -2804,17 +3484,23 @@ async fn check_host_goes_away() { let mut cx = CliTestContext::new(Scenario::None).await; { - let mut cx = cx.with_dist_dir(Scenario::HostGoesMissingBefore); - cx.config.expect_ok(&["rustup", "default", "nightly"]).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_err( - &["rustup", "update", "nightly"], - for_host!("target '{}' not found in channel"), - ) - .await; + .expect(&["rustup", "update", "nightly"]) + .await + .with_stderr(snapbox::str![[r#" +... +error: target '[HOST_TRIPLE]' not found in channel[..] +... +"#]]) + .is_err(); } #[cfg(unix)] @@ -2823,37 +3509,37 @@ async fn check_unix_settings_fallback() { let cx = CliTestContext::new(Scenario::SimpleV2).await; // No default toolchain specified yet cx.config - .expect_err_ex( - &["rustup", "default"], - "", - "error: no default toolchain is configured\n", - ) - .await; + .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, - for_host!(r"default_toolchain = 'nightly-{0}'"), + &format!("default_toolchain = 'nightly-{}'", this_host_triple()), ) .unwrap(); - let mut cmd = cx.config.cmd("rustup", ["default"]); - cx.config.env(&mut cmd); - - // Override the path to the fallback settings file to be the mock file - cmd.env("RUSTUP_OVERRIDE_UNIX_FALLBACK_SETTINGS", mock_settings_file); - - let out = cmd.output().unwrap(); - assert!(out.status.success()); - let stdout = String::from_utf8(out.stdout).unwrap(); - assert_eq!( - &stdout, - for_host!( - r"nightly-{0} (default) -" + 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_TRIPLE] (default) + +"#]]) + .is_ok(); } #[tokio::test] @@ -2861,14 +3547,16 @@ async fn deny_incompatible_toolchain_install() { let cx = CliTestContext::new(Scenario::MultiHost).await; let arch = MULTI_ARCH1; cx.config - .expect_err( - &["rustup", "toolchain", "install", &format!("nightly-{arch}")], - &format!( - "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", - ), - ) - .await; + .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] @@ -2876,57 +3564,65 @@ async fn deny_incompatible_toolchain_default() { let cx = CliTestContext::new(Scenario::MultiHost).await; let arch = MULTI_ARCH1; cx.config - .expect_err( - &["rustup", "default", &format!("nightly-{arch}")], - &format!( - "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", - ), - ) - .await; + .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 triple = this_host_triple(); - let arch = triple.split('-').next().unwrap(); - let mut cmd = cx.config.cmd( - "rustup", - ["toolchain", "install", &format!("nightly-{arch}")], - ); - cx.config.env(&mut cmd); - let out = cmd.output().unwrap(); - assert!(out.status.success()); - let stderr = String::from_utf8(out.stderr).unwrap(); - assert!(stderr.contains(&format!( - r"info: syncing channel updates for 'nightly-{triple}'" - ))); - assert!(!stderr.contains(&format!( - r"warn: toolchain 'nightly-{arch}' may not be able to run on this system." - ))); + let arch = this_host_triple().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_TRIPLE]' +... +"#]]) + .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 mut cx = CliTestContext::new(Scenario::SimpleV2).await; + let cx = CliTestContext::new(Scenario::SimpleV2).await; cx.config - .expect_err( - &["rustc", "--version"], - "rustup could not choose a version of rustc to run", - ) - .await; + .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_ok(&["rustup", "toolchain", "install"]) - .await; + .expect(["rustup", "toolchain", "install"]) + .await + .is_ok(); cx.config - .expect_stdout_ok(&["rustc", "--version"], "hash-nightly-2") - .await; + .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 @@ -2938,8 +3634,15 @@ async fn only_toml_in_rust_toolchain_toml() { raw::write_file(&toolchain_file, "nightly").unwrap(); cx.config - .expect_err(&["rustc", "--version"], "error parsing override file") - .await; + .expect(["rustc", "--version"]) + .await + .extend_redactions([("[CWD]", &cwd.display().to_string())]) + .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 @@ -2953,15 +3656,15 @@ async fn warn_on_duplicate_rust_toolchain_file() { raw::write_file(&toolchain_file_2, "[toolchain]").unwrap(); cx.config - .expect_stderr_ok( - &["rustup", "toolchain", "install"], - &format!( - "warn: both `{0}` and `{1}` exist. Using `{0}`", - toolchain_file_1.canonicalize().unwrap().display(), - toolchain_file_2.canonicalize().unwrap().display(), - ), - ) - .await; + .expect(&["rustup", "toolchain", "install"]) + .await + .extend_redactions([("[CWD]", &cwd.canonicalize().unwrap().display().to_string())]) + .with_stderr(snapbox::str![[r#" +... +warn: both `[CWD]/rust-toolchain` and `[CWD]/rust-toolchain.toml` exist. Using `[CWD]/rust-toolchain` +... +"#]]) + .is_ok(); } #[tokio::test] @@ -2973,32 +3676,31 @@ async fn custom_toolchain_with_components_toolchains_profile_does_not_err() { // install a toolchain so we can make a custom toolchain that links to it cx.config - .expect_stderr_ok( - &[ - "rustup", - "toolchain", - "install", - "nightly", - "--profile=minimal", - "--component=cargo", - ], - for_host!( - "\ -info: syncing channel updates for 'nightly-{0}' + .expect(&[ + "rustup", + "toolchain", + "install", + "nightly", + "--profile=minimal", + "--component=cargo", + ]) + .await + .with_stderr(snapbox::str![[r#" +info: syncing channel updates for 'nightly-[HOST_TRIPLE]' info: latest update on 2015-01-02, rust version 1.3.0 (hash-nightly-2) info: downloading component 'cargo' info: downloading component 'rustc' info: installing component 'cargo' info: installing component 'rustc' -info: default toolchain set to 'nightly-{0}'" - ), - ) - .await; +info: default toolchain set to 'nightly-[HOST_TRIPLE]' + +"#]]) + .is_ok(); // link the toolchain let toolchains = cx.config.rustupdir.join("toolchains"); raw::symlink_dir( - &toolchains.join(for_host!("nightly-{0}")), + &toolchains.join(format!("nightly-{}", this_host_triple())), &toolchains.join("my-custom"), ) .expect("failed to symlink"); @@ -3016,50 +3718,68 @@ profile = "minimal" .unwrap(); cx.config - .expect_stdout_ok( - &["rustup", "show", "active-toolchain"], - &format!("my-custom (overridden by '{0}')", toolchain_file.display(),), - ) - .await; + .expect(&["rustup", "show", "active-toolchain"]) + .await + .extend_redactions([("[CWD]", &cwd.display().to_string())]) + .with_stdout(snapbox::str![[r#" +my-custom (overridden by '[CWD]/rust-toolchain.toml') + +"#]]) + .is_ok(); cx.config - .expect_stdout_ok(&["rustc", "--version"], "1.3.0 (hash-nightly-2)") - .await; + .expect(&["rustc", "--version"]) + .await + .with_stdout(snapbox::str![[r#" +1.3.0 (hash-nightly-2) + +"#]]) + .is_ok(); cx.config - .expect_stdout_ok(&["cargo", "--version"], "1.3.0 (hash-nightly-2)") - .await; + .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 mut cx = CliTestContext::new(Scenario::SimpleV2).await; - cx.config.expect_ok(&["rustup", "default", "stable"]).await; + 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_triple())); cx.config - .expect_ok(&[ + .expect([ "rustup", "toolchain", "link", "stuff", &stable_path.to_string_lossy(), ]) - .await; + .await + .is_ok(); cx.config - .expect_ok_ex( - &["rustup", "+stuff", "show"], - &format!( - r"Default host: {0} -rustup home: {1} + .expect(["rustup", "+stuff", "show"]) + .await + .extend_redactions([("[RUSTUP_DIR]", cx.config.rustupdir.to_string())]) + .with_stdout(snapbox::str![[r#" +Default host: [HOST_TRIPLE] +rustup home: [RUSTUP_DIR] installed toolchains -------------------- -stable-{0} (default) +stable-[HOST_TRIPLE] (default) stuff (active) active toolchain @@ -3067,47 +3787,49 @@ active toolchain name: stuff active because: overridden by +toolchain on the command line installed targets: - {0} -", - this_host_triple(), - cx.config.rustupdir, - ), - r"", - ) - .await; + [HOST_TRIPLE] + +"#]]) + .with_stderr(snapbox::str![[""]]) + .is_ok(); } #[tokio::test] async fn show_custom_toolchain_without_components_file() { - let mut cx = CliTestContext::new(Scenario::SimpleV2).await; - cx.config.expect_ok(&["rustup", "default", "stable"]).await; + 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_triple())); cx.config - .expect_ok(&[ + .expect([ "rustup", "toolchain", "link", "stuff", &stable_path.to_string_lossy(), ]) - .await; + .await + .is_ok(); let components_file = stable_path.join("lib").join("rustlib").join("components"); fs::remove_file(&components_file).unwrap(); cx.config - .expect_ok_ex( - &["rustup", "+stuff", "show"], - &format!( - r"Default host: {0} -rustup home: {1} + .expect(["rustup", "+stuff", "show"]) + .await + .extend_redactions([("[RUSTUP_DIR]", cx.config.rustupdir.to_string())]) + .with_stdout(snapbox::str![[r#" +Default host: [HOST_TRIPLE] +rustup home: [RUSTUP_DIR] installed toolchains -------------------- -stable-{0} (default) +stable-[HOST_TRIPLE] (default) stuff (active) active toolchain @@ -3115,11 +3837,8 @@ active toolchain name: stuff active because: overridden by +toolchain on the command line installed targets: -", - this_host_triple(), - cx.config.rustupdir, - ), - r"", - ) - .await; + +"#]]) + .with_stderr(snapbox::str![[""]]) + .is_ok(); }