use crate::{Error, errors::handle_command_error};
use duct::cmd;
pub use frame_try_runtime::{TryStateSelect, UpgradeCheckSelect};
use std::{fmt::Display, path::PathBuf, str::from_utf8};
pub mod binary;
pub mod parse;
pub mod shared_parameters;
pub mod state;
pub enum TryRuntimeCliCommand {
OnRuntimeUpgrade,
ExecuteBlock,
CreateSnapshot,
FastForward,
}
impl Display for TryRuntimeCliCommand {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let s = match self {
TryRuntimeCliCommand::OnRuntimeUpgrade => "on-runtime-upgrade",
TryRuntimeCliCommand::ExecuteBlock => "execute-block",
TryRuntimeCliCommand::CreateSnapshot => "create-snapshot",
TryRuntimeCliCommand::FastForward => "fast-forward",
};
write!(f, "{}", s)
}
}
pub fn upgrade_checks_details(upgrade_check_select: &UpgradeCheckSelect) -> (String, String) {
match upgrade_check_select {
UpgradeCheckSelect::None => ("none".to_string(), "Run no checks".to_string()),
UpgradeCheckSelect::All => (
"all".to_string(),
"Run the `try_state`, `pre_upgrade` and `post_upgrade` checks".to_string(),
),
UpgradeCheckSelect::TryState =>
("try-state".to_string(), "Run the `try_state` checks".to_string()),
UpgradeCheckSelect::PreAndPost => (
"pre-and-post".to_string(),
"Run the `pre_upgrade` and `post_upgrade` checks".to_string(),
),
}
}
pub fn try_state_label(try_state_select: &TryStateSelect) -> String {
match try_state_select {
TryStateSelect::None => "None".to_string(),
TryStateSelect::All => "All".to_string(),
TryStateSelect::RoundRobin(..) => "Round Robin".to_string(),
TryStateSelect::Only(..) => "Only Pallets".to_string(),
}
}
pub fn try_state_details(try_state_select: &TryStateSelect) -> (String, String) {
(
try_state_label(try_state_select),
match try_state_select {
TryStateSelect::None => "Run no tests".to_string(),
TryStateSelect::All => "Run all the state tests".to_string(),
TryStateSelect::RoundRobin(..) =>
"Run a fixed number of state tests in a round robin manner.".to_string(),
TryStateSelect::Only(..) =>
"Run only pallets who's name matches the given list.".to_string(),
},
)
}
pub fn parse_try_state_string(try_state: &TryStateSelect) -> Result<String, Error> {
Ok(match try_state {
TryStateSelect::All => "all".to_string(),
TryStateSelect::None => "none".to_string(),
TryStateSelect::RoundRobin(rounds) => format!("rr-{}", rounds),
TryStateSelect::Only(pallets) => {
let mut result = vec![];
for pallet in pallets.iter() {
result.push(from_utf8(pallet).map_err(|_| {
Error::ParamParsingError("Invalid pallet string in `try_state`".to_string())
})?);
}
result.join(",")
},
})
}
pub fn run_try_runtime(
binary_path: &PathBuf,
command: TryRuntimeCliCommand,
shared_params: Vec<String>,
args: Vec<String>,
excluded_args: &[&str],
) -> Result<(), Error> {
let mut cmd_args = shared_params
.into_iter()
.filter(|arg| !excluded_args.iter().any(|a| arg.starts_with(a)))
.collect::<Vec<String>>();
cmd_args.extend(vec![command.to_string()]);
cmd_args.extend(
args.into_iter()
.filter(|arg| !excluded_args.iter().any(|a| arg.starts_with(a)))
.collect::<Vec<String>>(),
);
let output = cmd(binary_path, cmd_args)
.env("RUST_LOG", "info")
.stderr_capture()
.unchecked()
.run()?;
handle_command_error(&output, Error::TryRuntimeError)?;
if output.status.success() {
eprintln!("{}", String::from_utf8_lossy(&output.stderr));
}
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn parse_try_state_string_works() {
assert_eq!(parse_try_state_string(&TryStateSelect::All).unwrap(), "all");
assert_eq!(parse_try_state_string(&TryStateSelect::None).unwrap(), "none");
assert_eq!(parse_try_state_string(&TryStateSelect::RoundRobin(5)).unwrap(), "rr-5");
assert_eq!(
parse_try_state_string(&TryStateSelect::Only(vec![
b"System".to_vec(),
b"Proxy".to_vec()
]))
.unwrap(),
"System,Proxy"
);
}
#[test]
fn try_state_label_works() {
for (select, label) in [
(TryStateSelect::All, "All"),
(TryStateSelect::None, "None"),
(TryStateSelect::RoundRobin(5), "Round Robin"),
(TryStateSelect::Only(vec![]), "Only Pallets"),
] {
assert_eq!(try_state_label(&select), label);
}
}
#[test]
fn try_state_details_works() {
for (select, description) in [
(TryStateSelect::None, "Run no tests"),
(TryStateSelect::All, "Run all the state tests"),
(
TryStateSelect::RoundRobin(0),
"Run a fixed number of state tests in a round robin manner.",
),
(TryStateSelect::Only(vec![]), "Run only pallets who's name matches the given list."),
] {
assert_eq!(
try_state_details(&select),
(try_state_label(&select), description.to_string())
);
}
}
}