Skip to content

Commit f66952c

Browse files
committed
test(clitools): revive run_inprocess()
1 parent 02b148f commit f66952c

File tree

2 files changed

+106
-1
lines changed

2 files changed

+106
-1
lines changed

src/currentprocess.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,16 @@ impl TestProcess {
208208
})
209209
}
210210

211+
/// Extracts the stdout from the process
212+
pub fn stdout(&self) -> Vec<u8> {
213+
let tp = match &self.process {
214+
Process::TestProcess(tp) => tp,
215+
_ => unreachable!(),
216+
};
217+
218+
tp.stdout.lock().unwrap_or_else(|e| e.into_inner()).clone()
219+
}
220+
211221
/// Extracts the stderr from the process
212222
pub fn stderr(&self) -> Vec<u8> {
213223
let tp = match &self.process {

src/test/mock/clitools.rs

Lines changed: 96 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,11 @@ use std::{
1616

1717
use enum_map::{enum_map, Enum, EnumMap};
1818
use once_cell::sync::Lazy;
19+
use tokio::runtime::Builder;
1920
use url::Url;
2021

22+
use crate::cli::rustup_mode;
23+
use crate::currentprocess;
2124
use crate::test as rustup_test;
2225
use crate::test::const_dist_dir;
2326
use crate::test::this_host_triple;
@@ -676,8 +679,13 @@ impl Config {
676679
I: IntoIterator<Item = A> + Clone + Debug,
677680
A: AsRef<OsStr>,
678681
{
682+
let inprocess = allow_inprocess(name, args.clone());
679683
let start = Instant::now();
680-
let out = self.run_subprocess(name, args.clone(), env);
684+
let out = if inprocess {
685+
self.run_inprocess(name, args.clone(), env)
686+
} else {
687+
self.run_subprocess(name, args.clone(), env)
688+
};
681689
let duration = Instant::now() - start;
682690
let output = SanitizedOutput {
683691
ok: matches!(out.status, Some(0)),
@@ -686,6 +694,7 @@ impl Config {
686694
};
687695

688696
println!("ran: {} {:?}", name, args);
697+
println!("inprocess: {inprocess}");
689698
println!("status: {:?}", out.status);
690699
println!("duration: {:.3}s", duration.as_secs_f32());
691700
println!("stdout:\n====\n{}\n====\n", output.stdout);
@@ -694,6 +703,55 @@ impl Config {
694703
output
695704
}
696705

706+
#[cfg_attr(feature = "otel", tracing::instrument(skip_all))]
707+
pub(crate) fn run_inprocess<I, A>(&self, name: &str, args: I, env: &[(&str, &str)]) -> Output
708+
where
709+
I: IntoIterator<Item = A>,
710+
A: AsRef<OsStr>,
711+
{
712+
// should we use vars_os, or skip over non-stringable vars? This is test
713+
// code after all...
714+
let mut vars: HashMap<String, String> = HashMap::default();
715+
self::env(self, &mut vars);
716+
vars.extend(env.iter().map(|(k, v)| (k.to_string(), v.to_string())));
717+
let mut arg_strings: Vec<Box<str>> = Vec::new();
718+
arg_strings.push(name.to_owned().into_boxed_str());
719+
for arg in args {
720+
arg_strings.push(
721+
arg.as_ref()
722+
.to_os_string()
723+
.into_string()
724+
.unwrap()
725+
.into_boxed_str(),
726+
);
727+
}
728+
let mut builder = Builder::new_multi_thread();
729+
builder
730+
.enable_all()
731+
.worker_threads(2)
732+
.max_blocking_threads(2);
733+
let rt = builder.build().unwrap();
734+
rt.block_on(async {
735+
let tp =
736+
currentprocess::TestProcess::new(&*self.workdir.borrow(), &arg_strings, vars, "");
737+
let process_res =
738+
rustup_mode::main(tp.process.current_dir().unwrap(), &tp.process).await;
739+
// convert Err's into an ec
740+
let ec = match process_res {
741+
Ok(process_res) => process_res,
742+
Err(e) => {
743+
crate::cli::common::report_error(&e, &tp.process);
744+
utils::ExitCode(1)
745+
}
746+
};
747+
Output {
748+
status: Some(ec.0),
749+
stderr: tp.stderr(),
750+
stdout: tp.stdout(),
751+
}
752+
})
753+
}
754+
697755
#[track_caller]
698756
pub fn run_subprocess<I, A>(&self, name: &str, args: I, env: &[(&str, &str)]) -> Output
699757
where
@@ -797,6 +855,43 @@ pub fn env<E: rustup_test::Env>(config: &Config, cmd: &mut E) {
797855
config.env(cmd)
798856
}
799857

858+
fn allow_inprocess<I, A>(name: &str, args: I) -> bool
859+
where
860+
I: IntoIterator<Item = A>,
861+
A: AsRef<OsStr>,
862+
{
863+
// Only the rustup alias is currently ready for in-process testing:
864+
// - -init performs self-update which monkey with global external state.
865+
// - proxies themselves behave appropriately the proxied output needs to be
866+
// collected for assertions to be made on it as our tests traverse layers.
867+
// - self update executions cannot run in-process because on windows the
868+
// process replacement dance would replace the test process.
869+
// - any command with --version in it is testing to see something was
870+
// installed properly, so we have to shell out to it to be sure
871+
if name != "rustup" {
872+
return false;
873+
}
874+
let mut is_update = false;
875+
let mut no_self_update = false;
876+
let mut self_cmd = false;
877+
let mut run = false;
878+
let mut version = false;
879+
for arg in args {
880+
if arg.as_ref() == "update" {
881+
is_update = true;
882+
} else if arg.as_ref() == "--no-self-update" {
883+
no_self_update = true;
884+
} else if arg.as_ref() == "self" {
885+
self_cmd = true;
886+
} else if arg.as_ref() == "run" {
887+
run = true;
888+
} else if arg.as_ref() == "--version" {
889+
version = true;
890+
}
891+
}
892+
!(run || self_cmd || version || (is_update && !no_self_update))
893+
}
894+
800895
#[derive(Copy, Clone, Eq, PartialEq)]
801896
enum RlsStatus {
802897
Available,

0 commit comments

Comments
 (0)