Skip to content

Commit 2b13b2b

Browse files
committed
Asyncify CLI tests
1 parent f3b45f2 commit 2b13b2b

10 files changed

+4707
-3680
lines changed

src/test/mock/clitools.rs

Lines changed: 77 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ use std::{
1919
use enum_map::{enum_map, Enum, EnumMap};
2020
use once_cell::sync::Lazy;
2121
use tempfile::TempDir;
22-
use tokio::runtime::Builder;
2322
use url::Url;
2423

2524
use crate::cli::rustup_mode;
@@ -189,7 +188,7 @@ impl ConstState {
189188
}
190189

191190
/// State a test can interact and mutate
192-
pub fn setup_test_state(test_dist_dir: tempfile::TempDir) -> (tempfile::TempDir, Config) {
191+
pub async fn setup_test_state(test_dist_dir: tempfile::TempDir) -> (tempfile::TempDir, Config) {
193192
// Unset env variables that will break our testing
194193
env::remove_var("RUSTUP_UPDATE_ROOT");
195194
env::remove_var("RUSTUP_TOOLCHAIN");
@@ -294,10 +293,14 @@ pub fn setup_test_state(test_dist_dir: tempfile::TempDir) -> (tempfile::TempDir,
294293
// Make sure the host triple matches the build triple. Otherwise testing a 32-bit build of
295294
// rustup on a 64-bit machine will fail, because the tests do not have the host detection
296295
// functionality built in.
297-
config.run("rustup", ["set", "default-host", &this_host_triple()], &[]);
296+
config
297+
.run("rustup", ["set", "default-host", &this_host_triple()], &[])
298+
.await;
298299

299300
// Set the auto update mode to disable, as most tests do not want to update rustup itself during the test.
300-
config.run("rustup", ["set", "auto-self-update", "disable"], &[]);
301+
config
302+
.run("rustup", ["set", "auto-self-update", "disable"], &[])
303+
.await;
301304

302305
// Create some custom toolchains
303306
create_custom_toolchains(&config.customdir);
@@ -312,8 +315,8 @@ pub struct SelfUpdateTestContext {
312315
}
313316

314317
impl SelfUpdateTestContext {
315-
pub fn new(version: &str) -> Self {
316-
let mut cx = CliTestContext::from(Scenario::SimpleV2);
318+
pub async fn new(version: &str) -> Self {
319+
let mut cx = CliTestContext::new(Scenario::SimpleV2).await;
317320

318321
// Create a mock self-update server
319322
let self_dist_tmp = tempfile::Builder::new()
@@ -361,6 +364,24 @@ pub struct CliTestContext {
361364
}
362365

363366
impl CliTestContext {
367+
pub async fn new(scenario: Scenario) -> Self {
368+
// Things we might cache or what not
369+
370+
// Mutable dist server - working toward elimination
371+
let test_dist_dir = crate::test::test_dist_dir().unwrap();
372+
create_mock_dist_server(test_dist_dir.path(), scenario);
373+
374+
// Things that are just about the test itself
375+
let (_test_dir, mut config) = setup_test_state(test_dist_dir).await;
376+
// Pulled out of setup_test_state for clarity: the long term intent is to
377+
// not have this at all.
378+
if scenario != Scenario::None {
379+
config.distdir = Some(config.test_dist_dir.path().to_path_buf());
380+
}
381+
382+
Self { config, _test_dir }
383+
}
384+
364385
/// Move the dist server to the specified scenario and restore it
365386
/// afterwards.
366387
pub fn with_dist_dir(&mut self, scenario: Scenario) -> DistDirGuard<'_> {
@@ -411,26 +432,6 @@ pub struct UpdateServerGuard {
411432
_self_dist: TempDir,
412433
}
413434

414-
impl From<Scenario> for CliTestContext {
415-
fn from(scenario: Scenario) -> Self {
416-
// Things we might cache or what not
417-
418-
// Mutable dist server - working toward elimination
419-
let test_dist_dir = crate::test::test_dist_dir().unwrap();
420-
create_mock_dist_server(test_dist_dir.path(), scenario);
421-
422-
// Things that are just about the test itself
423-
let (_test_dir, mut config) = setup_test_state(test_dist_dir);
424-
// Pulled out of setup_test_state for clarity: the long term intent is to
425-
// not have this at all.
426-
if scenario != Scenario::None {
427-
config.distdir = Some(config.test_dist_dir.path().to_path_buf());
428-
}
429-
430-
Self { config, _test_dir }
431-
}
432-
}
433-
434435
#[must_use]
435436
pub struct WorkDirGuard<'a> {
436437
inner: &'a mut CliTestContext,
@@ -592,9 +593,8 @@ impl Config {
592593
}
593594

594595
/// Expect an ok status
595-
#[track_caller]
596-
pub fn expect_ok(&mut self, args: &[&str]) {
597-
let out = self.run(args[0], &args[1..], &[]);
596+
pub async fn expect_ok(&mut self, args: &[&str]) {
597+
let out = self.run(args[0], &args[1..], &[]).await;
598598
if !out.ok {
599599
print_command(args, &out);
600600
println!("expected.ok: true");
@@ -603,9 +603,8 @@ impl Config {
603603
}
604604

605605
/// Expect an err status and a string in stderr
606-
#[track_caller]
607-
pub fn expect_err(&self, args: &[&str], expected: &str) {
608-
let out = self.run(args[0], &args[1..], &[]);
606+
pub async fn expect_err(&self, args: &[&str], expected: &str) {
607+
let out = self.run(args[0], &args[1..], &[]).await;
609608
if out.ok || !out.stderr.contains(expected) {
610609
print_command(args, &out);
611610
println!("expected.ok: false");
@@ -615,9 +614,8 @@ impl Config {
615614
}
616615

617616
/// Expect an ok status and a string in stdout
618-
#[track_caller]
619-
pub fn expect_stdout_ok(&self, args: &[&str], expected: &str) {
620-
let out = self.run(args[0], &args[1..], &[]);
617+
pub async fn expect_stdout_ok(&self, args: &[&str], expected: &str) {
618+
let out = self.run(args[0], &args[1..], &[]).await;
621619
if !out.ok || !out.stdout.contains(expected) {
622620
print_command(args, &out);
623621
println!("expected.ok: true");
@@ -626,9 +624,8 @@ impl Config {
626624
}
627625
}
628626

629-
#[track_caller]
630-
pub fn expect_not_stdout_ok(&self, args: &[&str], expected: &str) {
631-
let out = self.run(args[0], &args[1..], &[]);
627+
pub async fn expect_not_stdout_ok(&self, args: &[&str], expected: &str) {
628+
let out = self.run(args[0], &args[1..], &[]).await;
632629
if !out.ok || out.stdout.contains(expected) {
633630
print_command(args, &out);
634631
println!("expected.ok: true");
@@ -637,9 +634,8 @@ impl Config {
637634
}
638635
}
639636

640-
#[track_caller]
641-
pub fn expect_not_stderr_ok(&self, args: &[&str], expected: &str) {
642-
let out = self.run(args[0], &args[1..], &[]);
637+
pub async fn expect_not_stderr_ok(&self, args: &[&str], expected: &str) {
638+
let out = self.run(args[0], &args[1..], &[]).await;
643639
if !out.ok || out.stderr.contains(expected) {
644640
print_command(args, &out);
645641
println!("expected.ok: false");
@@ -648,9 +644,8 @@ impl Config {
648644
}
649645
}
650646

651-
#[track_caller]
652-
pub fn expect_not_stderr_err(&self, args: &[&str], expected: &str) {
653-
let out = self.run(args[0], &args[1..], &[]);
647+
pub async fn expect_not_stderr_err(&self, args: &[&str], expected: &str) {
648+
let out = self.run(args[0], &args[1..], &[]).await;
654649
if out.ok || out.stderr.contains(expected) {
655650
print_command(args, &out);
656651
println!("expected.ok: false");
@@ -660,9 +655,8 @@ impl Config {
660655
}
661656

662657
/// Expect an ok status and a string in stderr
663-
#[track_caller]
664-
pub fn expect_stderr_ok(&self, args: &[&str], expected: &str) {
665-
let out = self.run(args[0], &args[1..], &[]);
658+
pub async fn expect_stderr_ok(&self, args: &[&str], expected: &str) {
659+
let out = self.run(args[0], &args[1..], &[]).await;
666660
if !out.ok || !out.stderr.contains(expected) {
667661
print_command(args, &out);
668662
println!("expected.ok: true");
@@ -672,9 +666,8 @@ impl Config {
672666
}
673667

674668
/// Expect an exact strings on stdout/stderr with an ok status code
675-
#[track_caller]
676-
pub fn expect_ok_ex(&mut self, args: &[&str], stdout: &str, stderr: &str) {
677-
let out = self.run(args[0], &args[1..], &[]);
669+
pub async fn expect_ok_ex(&mut self, args: &[&str], stdout: &str, stderr: &str) {
670+
let out = self.run(args[0], &args[1..], &[]).await;
678671
if !out.ok || out.stdout != stdout || out.stderr != stderr {
679672
print_command(args, &out);
680673
println!("expected.ok: true");
@@ -687,9 +680,8 @@ impl Config {
687680
}
688681

689682
/// Expect an exact strings on stdout/stderr with an error status code
690-
#[track_caller]
691-
pub fn expect_err_ex(&self, args: &[&str], stdout: &str, stderr: &str) {
692-
let out = self.run(args[0], &args[1..], &[]);
683+
pub async fn expect_err_ex(&self, args: &[&str], stdout: &str, stderr: &str) {
684+
let out = self.run(args[0], &args[1..], &[]).await;
693685
if out.ok || out.stdout != stdout || out.stderr != stderr {
694686
print_command(args, &out);
695687
println!("expected.ok: false");
@@ -707,9 +699,8 @@ impl Config {
707699
}
708700
}
709701

710-
#[track_caller]
711-
pub fn expect_ok_contains(&self, args: &[&str], stdout: &str, stderr: &str) {
712-
let out = self.run(args[0], &args[1..], &[]);
702+
pub async fn expect_ok_contains(&self, args: &[&str], stdout: &str, stderr: &str) {
703+
let out = self.run(args[0], &args[1..], &[]).await;
713704
if !out.ok || !out.stdout.contains(stdout) || !out.stderr.contains(stderr) {
714705
print_command(args, &out);
715706
println!("expected.ok: true");
@@ -719,10 +710,9 @@ impl Config {
719710
}
720711
}
721712

722-
#[track_caller]
723-
pub fn expect_ok_eq(&self, args1: &[&str], args2: &[&str]) {
724-
let out1 = self.run(args1[0], &args1[1..], &[]);
725-
let out2 = self.run(args2[0], &args2[1..], &[]);
713+
pub async fn expect_ok_eq(&self, args1: &[&str], args2: &[&str]) {
714+
let out1 = self.run(args1[0], &args1[1..], &[]).await;
715+
let out2 = self.run(args2[0], &args2[1..], &[]).await;
726716
if !out1.ok || !out2.ok || out1.stdout != out2.stdout || out1.stderr != out2.stderr {
727717
print_command(args1, &out1);
728718
println!("expected.ok: true");
@@ -732,35 +722,33 @@ impl Config {
732722
}
733723
}
734724

735-
#[track_caller]
736-
pub fn expect_component_executable(&self, cmd: &str) {
737-
let out1 = self.run(cmd, ["--version"], &[]);
725+
pub async fn expect_component_executable(&self, cmd: &str) {
726+
let out1 = self.run(cmd, ["--version"], &[]).await;
738727
if !out1.ok {
739728
print_command(&[cmd, "--version"], &out1);
740729
println!("expected.ok: true");
741730
panic!()
742731
}
743732
}
744733

745-
#[track_caller]
746-
pub fn expect_component_not_executable(&self, cmd: &str) {
747-
let out1 = self.run(cmd, ["--version"], &[]);
734+
pub async fn expect_component_not_executable(&self, cmd: &str) {
735+
let out1 = self.run(cmd, ["--version"], &[]).await;
748736
if out1.ok {
749737
print_command(&[cmd, "--version"], &out1);
750738
println!("expected.ok: false");
751739
panic!()
752740
}
753741
}
754742

755-
pub fn run<I, A>(&self, name: &str, args: I, env: &[(&str, &str)]) -> SanitizedOutput
743+
pub async fn run<I, A>(&self, name: &str, args: I, env: &[(&str, &str)]) -> SanitizedOutput
756744
where
757745
I: IntoIterator<Item = A> + Clone + Debug,
758746
A: AsRef<OsStr>,
759747
{
760748
let inprocess = allow_inprocess(name, args.clone());
761749
let start = Instant::now();
762750
let out = if inprocess {
763-
self.run_inprocess(name, args.clone(), env)
751+
self.run_inprocess(name, args.clone(), env).await
764752
} else {
765753
self.run_subprocess(name, args.clone(), env)
766754
};
@@ -782,7 +770,12 @@ impl Config {
782770
}
783771

784772
#[cfg_attr(feature = "otel", tracing::instrument(skip_all))]
785-
pub(crate) fn run_inprocess<I, A>(&self, name: &str, args: I, env: &[(&str, &str)]) -> Output
773+
pub(crate) async fn run_inprocess<I, A>(
774+
&self,
775+
name: &str,
776+
args: I,
777+
env: &[(&str, &str)],
778+
) -> Output
786779
where
787780
I: IntoIterator<Item = A>,
788781
A: AsRef<OsStr>,
@@ -803,31 +796,22 @@ impl Config {
803796
.into_boxed_str(),
804797
);
805798
}
806-
let mut builder = Builder::new_multi_thread();
807-
builder
808-
.enable_all()
809-
.worker_threads(2)
810-
.max_blocking_threads(2);
811-
let rt = builder.build().unwrap();
812-
rt.block_on(async {
813-
let tp =
814-
currentprocess::TestProcess::new(&*self.workdir.borrow(), &arg_strings, vars, "");
815-
let process_res =
816-
rustup_mode::main(tp.process.current_dir().unwrap(), &tp.process).await;
817-
// convert Err's into an ec
818-
let ec = match process_res {
819-
Ok(process_res) => process_res,
820-
Err(e) => {
821-
crate::cli::common::report_error(&e, &tp.process);
822-
utils::ExitCode(1)
823-
}
824-
};
825-
Output {
826-
status: Some(ec.0),
827-
stderr: tp.stderr(),
828-
stdout: tp.stdout(),
799+
800+
let tp = currentprocess::TestProcess::new(&*self.workdir.borrow(), &arg_strings, vars, "");
801+
let process_res = rustup_mode::main(tp.process.current_dir().unwrap(), &tp.process).await;
802+
// convert Err's into an ec
803+
let ec = match process_res {
804+
Ok(process_res) => process_res,
805+
Err(e) => {
806+
crate::cli::common::report_error(&e, &tp.process);
807+
utils::ExitCode(1)
829808
}
830-
})
809+
};
810+
Output {
811+
status: Some(ec.0),
812+
stderr: tp.stderr(),
813+
stdout: tp.stdout(),
814+
}
831815
}
832816

833817
#[track_caller]

0 commit comments

Comments
 (0)