use thiserror::Error;
use zombienet_sdk::OrchestratorError;
#[derive(Error, Debug)]
pub enum Error {
#[error("User aborted due to existing target directory.")]
Aborted,
#[error("Anyhow error: {0}")]
AnyhowError(#[from] anyhow::Error),
#[error("Failed to build the chain spec: {0}")]
BuildSpecError(String),
#[error("Failed to run benchmarking: {0}")]
BenchmarkingError(String),
#[error("Failed to decode call data: {0}")]
CallDataDecodingError(String),
#[error("Failed to encode call data: {0}")]
CallDataEncodingError(String),
#[error("{0}")]
CommonError(#[from] pop_common::Error),
#[error("Failed to establish a connection to: {0}")]
ConnectionFailure(String),
#[error("Configuration error: {0}")]
Config(String),
#[error("Failed to access the current directory")]
CurrentDirAccess,
#[error("Failed to parse the endowment value")]
EndowmentError,
#[error("Event {0} not found.")]
EventNotFound(String),
#[error("Extrinsic submission error: {0}")]
ExtrinsicSubmissionError(String),
#[error("The callable item is not supported")]
CallableNotSupported,
#[error("Function not found: {0}")]
FunctionNotFound(String),
#[error("Genesis builder error: {0}")]
GenesisBuilderError(String),
#[error("Failed to retrieve image tag.")]
ImageTagRetrievalFailed,
#[error("IO error: {0}")]
IO(#[from] std::io::Error),
#[error("JSON error: {0}")]
JsonError(#[from] serde_json::Error),
#[error("Error parsing metadata for parameter: {0}")]
MetadataParsingError(String),
#[error("Missing binary: {0}")]
MissingBinary(String),
#[error("Missing chain spec file at: {0}")]
MissingChainSpec(String),
#[error("Command {command} doesn't exist in binary {binary}")]
MissingCommand {
command: String,
binary: String,
},
#[error("Configuration error: {0:?}")]
NetworkConfigurationError(Vec<anyhow::Error>),
#[error("Orchestrator error: {0}")]
OrchestratorError(#[from] OrchestratorError),
#[error("Failed to create pallet directory")]
PalletDirCreation,
#[error("Failed to find the pallet: {0}")]
PalletNotFound(String),
#[error("Failed to process the arguments provided by the user.")]
ParamProcessingError,
#[error("Failed to parse the arguments provided by the user: {0}")]
ParamParsingError(String),
#[error("Invalid path")]
PathError,
#[error("Failed to execute rustfmt")]
RustfmtError(std::io::Error),
#[error("Failed to find the runtime {0}")]
RuntimeNotFound(String),
#[error("Template error: {0}")]
SourcingError(#[from] pop_common::sourcing::Error),
#[error("Subxt error: {0}")]
SubXtError(#[from] Box<subxt::Error>),
#[error("Toml error: {0}")]
TomlError(#[from] toml_edit::de::Error),
#[error("Failed to test with try-runtime: {0}")]
TryRuntimeError(String),
#[error("Unsupported command: {0}")]
UnsupportedCommand(String),
#[error("Failed to locate the workspace")]
WorkspaceLocate,
}
pub(crate) fn handle_command_error<F>(
output: &std::process::Output,
custom_error: F,
) -> Result<(), Error>
where
F: FnOnce(String) -> Error,
{
if !output.status.success() {
let stderr_msg = String::from_utf8_lossy(&output.stderr);
return Err(custom_error(stderr_msg.to_string()));
}
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
use anyhow::Result;
use std::{
os::unix::process::ExitStatusExt,
process::{ExitStatus, Output},
};
#[test]
fn handle_command_error_failure() -> Result<()> {
let output = Output {
status: ExitStatus::from_raw(1),
stdout: Vec::new(),
stderr: Vec::from("Error message".as_bytes()),
};
assert!(matches!(
handle_command_error(&output, Error::BuildSpecError),
Err(Error::BuildSpecError(message))
if message == "Error message"
));
Ok(())
}
}