Generate a script to rerun the failed sub-command in cargo-test-bpf (#18582)

* Generate a script to rerun the failed sub-command in cargo-test-bpf

* Generate a script to rerun the failed sub-command in cargo-build-bpf

* Add cargo-build-bpf test for generate-child-script-on-failure option
This commit is contained in:
Dmitri Makarov
2021-07-14 18:02:42 -07:00
committed by GitHub
parent ad3f18f031
commit 6f72f8b1fc
6 changed files with 162 additions and 16 deletions

View File

@@ -4,6 +4,8 @@ use clap::{
use std::{
env,
ffi::OsStr,
fs::File,
io::{prelude::*, BufWriter},
path::{Path, PathBuf},
process::exit,
process::Command,
@@ -16,6 +18,7 @@ struct Config {
cargo_build_bpf: PathBuf,
extra_cargo_test_args: Vec<String>,
features: Vec<String>,
generate_child_script_on_failure: bool,
test_name: Option<String>,
no_default_features: bool,
no_run: bool,
@@ -33,6 +36,7 @@ impl Default for Config {
cargo_build_bpf: PathBuf::from("cargo-build-bpf"),
extra_cargo_test_args: vec![],
features: vec![],
generate_child_script_on_failure: false,
test_name: None,
no_default_features: false,
no_run: false,
@@ -43,13 +47,13 @@ impl Default for Config {
}
}
fn spawn<I, S>(program: &Path, args: I)
fn spawn<I, S>(program: &Path, args: I, generate_child_script_on_failure: bool)
where
I: IntoIterator<Item = S>,
S: AsRef<OsStr>,
{
let args = args.into_iter().collect::<Vec<_>>();
print!("Running: {}", program.display());
print!("cargo-test-bpf child: {}", program.display());
for arg in args.iter() {
print!(" {}", arg.as_ref().to_str().unwrap_or("?"));
}
@@ -65,6 +69,29 @@ where
let exit_status = child.wait().expect("failed to wait on child");
if !exit_status.success() {
if !generate_child_script_on_failure {
exit(1);
}
eprintln!("cargo-test-bpf exited on command execution failure");
let script_name = format!(
"cargo-test-bpf-child-script-{}.sh",
program.file_name().unwrap().to_str().unwrap(),
);
let file = File::create(&script_name).unwrap();
let mut out = BufWriter::new(file);
for (key, value) in env::vars() {
writeln!(out, "{}=\"{}\" \\", key, value).unwrap();
}
write!(out, "{}", program.display()).unwrap();
for arg in args.iter() {
write!(out, " {}", arg.as_ref().to_str().unwrap_or("?")).unwrap();
}
writeln!(out).unwrap();
out.flush().unwrap();
eprintln!(
"To rerun the failed command for debugging use {}",
script_name,
);
exit(1);
}
}
@@ -99,7 +126,11 @@ fn test_bpf_package(config: &Config, target_directory: &Path, package: &cargo_me
build_bpf_args.push("--bpf-out-dir");
build_bpf_args.push(&bpf_out_dir);
spawn(&config.cargo_build_bpf, &build_bpf_args);
spawn(
&config.cargo_build_bpf,
&build_bpf_args,
config.generate_child_script_on_failure,
);
// Pass --bpf-out-dir along to the solana-program-test crate
env::set_var("BPF_OUT_DIR", bpf_out_dir);
@@ -124,7 +155,11 @@ fn test_bpf_package(config: &Config, target_directory: &Path, package: &cargo_me
for extra_cargo_test_arg in &config.extra_cargo_test_args {
cargo_args.push(extra_cargo_test_arg);
}
spawn(&config.cargo, &cargo_args);
spawn(
&config.cargo,
&cargo_args,
config.generate_child_script_on_failure,
);
}
fn test_bpf(config: Config, manifest_path: Option<PathBuf>) {
@@ -239,6 +274,12 @@ fn main() {
.takes_value(false)
.help("Run without accessing the network"),
)
.arg(
Arg::with_name("generate_child_script_on_failure")
.long("generate-child-script-on-failure")
.takes_value(false)
.help("Generate rerun-script.sh to rerun test command on failure"),
)
.arg(
Arg::with_name("verbose")
.short("v")
@@ -271,6 +312,7 @@ fn main() {
features: values_t!(matches, "features", String)
.ok()
.unwrap_or_else(Vec::new),
generate_child_script_on_failure: matches.is_present("generate_child_script_on_failure"),
test_name: value_t!(matches, "test", String).ok(),
no_default_features: matches.is_present("no_default_features"),
no_run: matches.is_present("no_run"),