Skip to content

Commit

Permalink
test(clitools): revive run_inprocess()
Browse files Browse the repository at this point in the history
  • Loading branch information
rami3l committed Jun 18, 2024
1 parent e7baa2d commit 618e072
Show file tree
Hide file tree
Showing 2 changed files with 106 additions and 1 deletion.
10 changes: 10 additions & 0 deletions src/currentprocess.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,16 @@ impl TestProcess {
})
}

/// Extracts the stdout from the process
pub fn stdout(&self) -> Vec<u8> {
let tp = match &self.process {
Process::TestProcess(tp) => tp,
_ => unreachable!(),
};

tp.stdout.lock().unwrap_or_else(|e| e.into_inner()).clone()
}

/// Extracts the stderr from the process
pub fn stderr(&self) -> Vec<u8> {
let tp = match &self.process {
Expand Down
97 changes: 96 additions & 1 deletion src/test/mock/clitools.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,11 @@ use std::{

use enum_map::{enum_map, Enum, EnumMap};
use once_cell::sync::Lazy;
use tokio::runtime::Builder;
use url::Url;

use crate::cli::rustup_mode;
use crate::currentprocess;
use crate::test as rustup_test;
use crate::test::const_dist_dir;
use crate::test::this_host_triple;
Expand Down Expand Up @@ -676,8 +679,13 @@ impl Config {
I: IntoIterator<Item = A> + Clone + Debug,
A: AsRef<OsStr>,
{
let inprocess = allow_inprocess(name, args.clone());
let start = Instant::now();
let out = self.run_subprocess(name, args.clone(), env);
let out = if inprocess {
self.run_inprocess(name, args.clone(), env)
} else {
self.run_subprocess(name, args.clone(), env)
};
let duration = Instant::now() - start;
let output = SanitizedOutput {
ok: matches!(out.status, Some(0)),
Expand All @@ -686,6 +694,7 @@ impl Config {
};

println!("ran: {} {:?}", name, args);
println!("inprocess: {inprocess}");
println!("status: {:?}", out.status);
println!("duration: {:.3}s", duration.as_secs_f32());
println!("stdout:\n====\n{}\n====\n", output.stdout);
Expand All @@ -694,6 +703,55 @@ impl Config {
output
}

#[cfg_attr(feature = "otel", tracing::instrument(skip_all))]
pub(crate) fn run_inprocess<I, A>(&self, name: &str, args: I, env: &[(&str, &str)]) -> Output
where
I: IntoIterator<Item = A>,
A: AsRef<OsStr>,
{
// should we use vars_os, or skip over non-stringable vars? This is test
// code after all...
let mut vars: HashMap<String, String> = HashMap::default();
self::env(self, &mut vars);
vars.extend(env.iter().map(|(k, v)| (k.to_string(), v.to_string())));
let mut arg_strings: Vec<Box<str>> = Vec::new();
arg_strings.push(name.to_owned().into_boxed_str());
for arg in args {
arg_strings.push(
arg.as_ref()
.to_os_string()
.into_string()
.unwrap()
.into_boxed_str(),
);
}
let mut builder = Builder::new_multi_thread();
builder
.enable_all()
.worker_threads(2)
.max_blocking_threads(2);
let rt = builder.build().unwrap();
rt.block_on(async {
let tp =
currentprocess::TestProcess::new(&*self.workdir.borrow(), &arg_strings, vars, "");
let process_res =
rustup_mode::main(tp.process.current_dir().unwrap(), &tp.process).await;
// convert Err's into an ec
let ec = match process_res {
Ok(process_res) => process_res,
Err(e) => {
crate::cli::common::report_error(&e, &tp.process);
utils::ExitCode(1)
}
};
Output {
status: Some(ec.0),
stderr: tp.stderr(),
stdout: tp.stdout(),
}
})
}

#[track_caller]
pub fn run_subprocess<I, A>(&self, name: &str, args: I, env: &[(&str, &str)]) -> Output
where
Expand Down Expand Up @@ -797,6 +855,43 @@ pub fn env<E: rustup_test::Env>(config: &Config, cmd: &mut E) {
config.env(cmd)
}

fn allow_inprocess<I, A>(name: &str, args: I) -> bool
where
I: IntoIterator<Item = A>,
A: AsRef<OsStr>,
{
// Only the rustup alias is currently ready for in-process testing:
// - -init performs self-update which monkey with global external state.
// - proxies themselves behave appropriately the proxied output needs to be
// collected for assertions to be made on it as our tests traverse layers.
// - self update executions cannot run in-process because on windows the
// process replacement dance would replace the test process.
// - any command with --version in it is testing to see something was
// installed properly, so we have to shell out to it to be sure
if name != "rustup" {
return false;
}
let mut is_update = false;
let mut no_self_update = false;
let mut self_cmd = false;
let mut run = false;
let mut version = false;
for arg in args {
if arg.as_ref() == "update" {
is_update = true;
} else if arg.as_ref() == "--no-self-update" {
no_self_update = true;
} else if arg.as_ref() == "self" {
self_cmd = true;
} else if arg.as_ref() == "run" {
run = true;
} else if arg.as_ref() == "--version" {
version = true;
}
}
!(run || self_cmd || version || (is_update && !no_self_update))
}

#[derive(Copy, Clone, Eq, PartialEq)]
enum RlsStatus {
Available,
Expand Down

0 comments on commit 618e072

Please sign in to comment.