Add cargo-test-bpf
This commit is contained in:
parent
78c2d9156b
commit
6c36a2085f
|
@ -56,6 +56,7 @@ members = [
|
||||||
"runtime/store-tool",
|
"runtime/store-tool",
|
||||||
"sdk",
|
"sdk",
|
||||||
"sdk/cargo-build-bpf",
|
"sdk/cargo-build-bpf",
|
||||||
|
"sdk/cargo-test-bpf",
|
||||||
"scripts",
|
"scripts",
|
||||||
"stake-accounts",
|
"stake-accounts",
|
||||||
"stake-monitor",
|
"stake-monitor",
|
||||||
|
|
|
@ -1,5 +1,13 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
here=$(dirname "$0")
|
here=$(dirname "$0")
|
||||||
|
|
||||||
|
maybe_bpf_sdk="--bpf-sdk $here/sdk/bpf"
|
||||||
|
for a in "$@"; do
|
||||||
|
if [[ $a = --bpf-sdk ]]; then
|
||||||
|
maybe_bpf_sdk=
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
set -x
|
set -x
|
||||||
exec $here/cargo run --manifest-path $here/sdk/cargo-build-bpf/Cargo.toml -- --bpf-sdk $here/sdk/bpf "$@"
|
exec "$here"/cargo run --manifest-path "$here"/sdk/cargo-build-bpf/Cargo.toml -- $maybe_bpf_sdk "$@"
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
here=$(dirname "$0")
|
||||||
|
|
||||||
|
maybe_bpf_sdk="--bpf-sdk $here/sdk/bpf"
|
||||||
|
for a in "$@"; do
|
||||||
|
if [[ $a = --bpf-sdk ]]; then
|
||||||
|
maybe_bpf_sdk=
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
export CARGO_BUILD_BPF="$here"/cargo-build-bpf
|
||||||
|
set -x
|
||||||
|
exec "$here"/cargo run --manifest-path "$here"/sdk/cargo-test-bpf/Cargo.toml -- $maybe_bpf_sdk "$@"
|
|
@ -78,6 +78,7 @@ else
|
||||||
|
|
||||||
BINS=(
|
BINS=(
|
||||||
cargo-build-bpf
|
cargo-build-bpf
|
||||||
|
cargo-test-bpf
|
||||||
solana
|
solana
|
||||||
solana-bench-exchange
|
solana-bench-exchange
|
||||||
solana-bench-tps
|
solana-bench-tps
|
||||||
|
|
|
@ -11,12 +11,13 @@ use std::{
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Config {
|
struct Config {
|
||||||
bpf_sdk: PathBuf,
|
|
||||||
bpf_out_dir: Option<PathBuf>,
|
bpf_out_dir: Option<PathBuf>,
|
||||||
|
bpf_sdk: PathBuf,
|
||||||
dump: bool,
|
dump: bool,
|
||||||
features: Vec<String>,
|
features: Vec<String>,
|
||||||
manifest_path: Option<PathBuf>,
|
manifest_path: Option<PathBuf>,
|
||||||
no_default_features: bool,
|
no_default_features: bool,
|
||||||
|
verbose: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Config {
|
impl Default for Config {
|
||||||
|
@ -29,10 +30,11 @@ impl Default for Config {
|
||||||
.to_path_buf()
|
.to_path_buf()
|
||||||
.join("sdk/bpf"),
|
.join("sdk/bpf"),
|
||||||
bpf_out_dir: None,
|
bpf_out_dir: None,
|
||||||
|
dump: false,
|
||||||
features: vec![],
|
features: vec![],
|
||||||
manifest_path: None,
|
manifest_path: None,
|
||||||
no_default_features: false,
|
no_default_features: false,
|
||||||
dump: true,
|
verbose: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -152,22 +154,25 @@ fn build_bpf(config: Config) {
|
||||||
}
|
}
|
||||||
|
|
||||||
let xargo_build = config.bpf_sdk.join("rust/xargo-build.sh");
|
let xargo_build = config.bpf_sdk.join("rust/xargo-build.sh");
|
||||||
let mut spawn_args = vec![];
|
let mut xargo_build_args = vec![];
|
||||||
|
|
||||||
if config.no_default_features {
|
if config.no_default_features {
|
||||||
spawn_args.push("--no-default-features");
|
xargo_build_args.push("--no-default-features");
|
||||||
}
|
}
|
||||||
for feature in &config.features {
|
for feature in &config.features {
|
||||||
spawn_args.push("--features");
|
xargo_build_args.push("--features");
|
||||||
spawn_args.push(feature);
|
xargo_build_args.push(feature);
|
||||||
}
|
}
|
||||||
if legacy_program_feature_present {
|
if legacy_program_feature_present {
|
||||||
if !config.no_default_features {
|
if !config.no_default_features {
|
||||||
spawn_args.push("--no-default-features");
|
xargo_build_args.push("--no-default-features");
|
||||||
}
|
}
|
||||||
spawn_args.push("--features=program");
|
xargo_build_args.push("--features=program");
|
||||||
}
|
}
|
||||||
spawn(&config.bpf_sdk.join(xargo_build), &spawn_args);
|
if config.verbose {
|
||||||
|
xargo_build_args.push("--verbose");
|
||||||
|
}
|
||||||
|
spawn(&config.bpf_sdk.join(xargo_build), &xargo_build_args);
|
||||||
|
|
||||||
if let Some(program_name) = program_name {
|
if let Some(program_name) = program_name {
|
||||||
let program_unstripped_so = target_build_directory.join(&format!("{}.so", program_name));
|
let program_unstripped_so = target_build_directory.join(&format!("{}.so", program_name));
|
||||||
|
@ -224,6 +229,13 @@ fn main() {
|
||||||
.takes_value(false)
|
.takes_value(false)
|
||||||
.help("Dump ELF information to a text file on success"),
|
.help("Dump ELF information to a text file on success"),
|
||||||
)
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("verbose")
|
||||||
|
.short("v")
|
||||||
|
.long("verbose")
|
||||||
|
.takes_value(false)
|
||||||
|
.help("Use verbose output"),
|
||||||
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("features")
|
Arg::with_name("features")
|
||||||
.long("features")
|
.long("features")
|
||||||
|
@ -281,6 +293,7 @@ fn main() {
|
||||||
.unwrap_or_else(Vec::new),
|
.unwrap_or_else(Vec::new),
|
||||||
manifest_path: value_t!(matches, "manifest_path", PathBuf).ok(),
|
manifest_path: value_t!(matches, "manifest_path", PathBuf).ok(),
|
||||||
no_default_features: matches.is_present("no_default_features"),
|
no_default_features: matches.is_present("no_default_features"),
|
||||||
|
verbose: matches.is_present("verbose"),
|
||||||
};
|
};
|
||||||
build_bpf(config);
|
build_bpf(config);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
[package]
|
||||||
|
name = "solana-cargo-test-bpf"
|
||||||
|
version = "1.5.0"
|
||||||
|
description = "Execute all unit and integration tests after building with the Solana BPF SDK"
|
||||||
|
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||||
|
repository = "https://github.com/solana-labs/solana"
|
||||||
|
homepage = "https://solana.com/"
|
||||||
|
license = "Apache-2.0"
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
clap = "2.33.3"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "cargo-test-bpf"
|
||||||
|
path = "src/main.rs"
|
|
@ -0,0 +1,192 @@
|
||||||
|
use clap::{
|
||||||
|
crate_description, crate_name, crate_version, value_t, values_t, App, AppSettings, Arg,
|
||||||
|
};
|
||||||
|
use std::{
|
||||||
|
env,
|
||||||
|
ffi::OsStr,
|
||||||
|
path::{Path, PathBuf},
|
||||||
|
process::exit,
|
||||||
|
process::Command,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Config {
|
||||||
|
bpf_sdk: Option<String>,
|
||||||
|
bpf_out_dir: Option<String>,
|
||||||
|
cargo: PathBuf,
|
||||||
|
cargo_build_bpf: PathBuf,
|
||||||
|
extra_cargo_test_args: Vec<String>,
|
||||||
|
features: Vec<String>,
|
||||||
|
manifest_path: Option<String>,
|
||||||
|
no_default_features: bool,
|
||||||
|
verbose: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Config {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
bpf_sdk: None,
|
||||||
|
bpf_out_dir: None,
|
||||||
|
cargo: PathBuf::from("cargo"),
|
||||||
|
cargo_build_bpf: PathBuf::from("cargo-build-bpf"),
|
||||||
|
extra_cargo_test_args: vec![],
|
||||||
|
features: vec![],
|
||||||
|
manifest_path: None,
|
||||||
|
no_default_features: false,
|
||||||
|
verbose: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn spawn<I, S>(program: &Path, args: I)
|
||||||
|
where
|
||||||
|
I: IntoIterator<Item = S>,
|
||||||
|
S: AsRef<OsStr>,
|
||||||
|
{
|
||||||
|
let args = args.into_iter().collect::<Vec<_>>();
|
||||||
|
print!("Running: {}", program.display());
|
||||||
|
for arg in args.iter() {
|
||||||
|
print!(" {}", arg.as_ref().to_str().unwrap_or("?"));
|
||||||
|
}
|
||||||
|
println!();
|
||||||
|
|
||||||
|
let mut child = Command::new(program)
|
||||||
|
.args(&args)
|
||||||
|
.spawn()
|
||||||
|
.unwrap_or_else(|err| {
|
||||||
|
eprintln!("Failed to execute {}: {}", program.display(), err);
|
||||||
|
exit(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
let exit_status = child.wait().expect("failed to wait on child");
|
||||||
|
if !exit_status.success() {
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_bpf(config: Config) {
|
||||||
|
let mut cargo_args = vec![];
|
||||||
|
if config.no_default_features {
|
||||||
|
cargo_args.push("--no-default-features");
|
||||||
|
}
|
||||||
|
for feature in &config.features {
|
||||||
|
cargo_args.push("--features");
|
||||||
|
cargo_args.push(feature);
|
||||||
|
}
|
||||||
|
if let Some(manifest_path) = config.manifest_path.as_ref() {
|
||||||
|
cargo_args.push("--manifest-path");
|
||||||
|
cargo_args.push(&manifest_path);
|
||||||
|
}
|
||||||
|
if config.verbose {
|
||||||
|
cargo_args.push("--verbose");
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut build_bpf_args = cargo_args.clone();
|
||||||
|
if let Some(bpf_sdk) = config.bpf_sdk.as_ref() {
|
||||||
|
build_bpf_args.push("--bpf-sdk");
|
||||||
|
build_bpf_args.push(bpf_sdk);
|
||||||
|
}
|
||||||
|
if let Some(bpf_out_dir) = config.bpf_out_dir.as_ref() {
|
||||||
|
build_bpf_args.push("--bpf-out-dir");
|
||||||
|
build_bpf_args.push(bpf_out_dir);
|
||||||
|
}
|
||||||
|
spawn(&config.cargo_build_bpf, &build_bpf_args);
|
||||||
|
|
||||||
|
env::set_var("bpf", "1"); // Hint to solana-program-test that it should load BPF programs
|
||||||
|
cargo_args.insert(0, "test");
|
||||||
|
for extra_cargo_test_arg in &config.extra_cargo_test_args {
|
||||||
|
cargo_args.push(&extra_cargo_test_arg);
|
||||||
|
}
|
||||||
|
spawn(&config.cargo, &cargo_args);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let mut args = env::args().collect::<Vec<_>>();
|
||||||
|
// When run as a cargo subcommand, the first program argument is the subcommand name.
|
||||||
|
// Remove it
|
||||||
|
if let Some(arg1) = args.get(1) {
|
||||||
|
if arg1 == "test-bpf" {
|
||||||
|
args.remove(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let matches = App::new(crate_name!())
|
||||||
|
.about(crate_description!())
|
||||||
|
.version(crate_version!())
|
||||||
|
.setting(AppSettings::TrailingVarArg)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("bpf_sdk")
|
||||||
|
.long("bpf-sdk")
|
||||||
|
.value_name("PATH")
|
||||||
|
.takes_value(true)
|
||||||
|
.help("Path to the Solana BPF SDK"),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("features")
|
||||||
|
.long("features")
|
||||||
|
.value_name("FEATURES")
|
||||||
|
.takes_value(true)
|
||||||
|
.multiple(true)
|
||||||
|
.help("Space-separated list of features to activate"),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("no_default_features")
|
||||||
|
.long("no-default-features")
|
||||||
|
.takes_value(false)
|
||||||
|
.help("Do not activate the `default` feature"),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("manifest_path")
|
||||||
|
.long("manifest-path")
|
||||||
|
.value_name("PATH")
|
||||||
|
.takes_value(true)
|
||||||
|
.help("Path to Cargo.toml"),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("bpf_out_dir")
|
||||||
|
.long("bpf-out-dir")
|
||||||
|
.value_name("DIRECTORY")
|
||||||
|
.takes_value(true)
|
||||||
|
.help("Place final BPF build artifacts in this directory"),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("verbose")
|
||||||
|
.short("v")
|
||||||
|
.long("verbose")
|
||||||
|
.takes_value(false)
|
||||||
|
.help("Use verbose output"),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("extra_cargo_test_args")
|
||||||
|
.value_name("extra args for cargo test")
|
||||||
|
.index(1)
|
||||||
|
.multiple(true)
|
||||||
|
.help("All extra arguments are passed through to cargo test"),
|
||||||
|
)
|
||||||
|
.get_matches_from(args);
|
||||||
|
|
||||||
|
let mut config = Config {
|
||||||
|
bpf_sdk: value_t!(matches, "bpf_sdk", String).ok(),
|
||||||
|
bpf_out_dir: value_t!(matches, "bpf_out_dir", String).ok(),
|
||||||
|
extra_cargo_test_args: values_t!(matches, "extra_cargo_test_args", String)
|
||||||
|
.ok()
|
||||||
|
.unwrap_or_else(Vec::new),
|
||||||
|
features: values_t!(matches, "features", String)
|
||||||
|
.ok()
|
||||||
|
.unwrap_or_else(Vec::new),
|
||||||
|
manifest_path: value_t!(matches, "manifest_path", String).ok(),
|
||||||
|
no_default_features: matches.is_present("no_default_features"),
|
||||||
|
verbose: matches.is_present("verbose"),
|
||||||
|
..Config::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Ok(cargo_build_bpf) = env::var("CARGO_BUILD_BPF") {
|
||||||
|
config.cargo_build_bpf = PathBuf::from(cargo_build_bpf);
|
||||||
|
}
|
||||||
|
if let Ok(cargo_build_bpf) = env::var("CARGO") {
|
||||||
|
config.cargo = PathBuf::from(cargo_build_bpf);
|
||||||
|
}
|
||||||
|
|
||||||
|
test_bpf(config);
|
||||||
|
|
||||||
|
// TODO: args after -- go to ct
|
||||||
|
}
|
Loading…
Reference in New Issue