1use thiserror::Error;
4use zombienet_sdk::OrchestratorError;
5
6#[derive(Error, Debug)]
8pub enum Error {
9 #[error("User aborted due to existing target directory.")]
11 Aborted,
12 #[error("Anyhow error: {0}")]
14 AnyhowError(#[from] anyhow::Error),
15 #[error("Failed to build the chain spec: {0}")]
17 BuildSpecError(String),
18 #[error("Failed to run benchmarking: {0}")]
20 BenchmarkingError(String),
21 #[error("Failed to decode call data: {0}")]
23 CallDataDecodingError(String),
24 #[error("Failed to encode call data: {0}")]
26 CallDataEncodingError(String),
27 #[error("{0}")]
29 CommonError(#[from] pop_common::Error),
30 #[error("Failed to establish a connection to: {0}")]
32 ConnectionFailure(String),
33 #[error("Configuration error: {0}")]
35 Config(String),
36 #[error("Failed to access the current directory")]
38 CurrentDirAccess,
39 #[error("Failed to parse the endowment value")]
41 EndowmentError,
42 #[error("Event {0} not found.")]
44 EventNotFound(String),
45 #[error("Extrinsic submission error: {0}")]
47 ExtrinsicSubmissionError(String),
48 #[error("The callable item is not supported")]
50 CallableNotSupported,
51 #[error("Function not found: {0}")]
53 FunctionNotFound(String),
54 #[error("Genesis builder error: {0}")]
56 GenesisBuilderError(String),
57 #[error("Failed to retrieve image tag.")]
59 ImageTagRetrievalFailed,
60 #[error("IO error: {0}")]
62 IO(#[from] std::io::Error),
63 #[error("JSON error: {0}")]
65 JsonError(#[from] serde_json::Error),
66 #[error("Error parsing metadata for parameter: {0}")]
68 MetadataParsingError(String),
69 #[error("Missing binary: {0}")]
71 MissingBinary(String),
72 #[error("Missing chain spec file at: {0}")]
74 MissingChainSpec(String),
75 #[error("Command {command} doesn't exist in binary {binary}")]
77 MissingCommand {
78 command: String,
80 binary: String,
82 },
83 #[error("Configuration error: {0:?}")]
85 NetworkConfigurationError(Vec<anyhow::Error>),
86 #[error("Orchestrator error: {0}")]
88 OrchestratorError(#[from] OrchestratorError),
89 #[error("Failed to create pallet directory")]
91 PalletDirCreation,
92 #[error("Failed to find the pallet: {0}")]
94 PalletNotFound(String),
95 #[error("Failed to process the arguments provided by the user.")]
97 ParamProcessingError,
98 #[error("Failed to parse the arguments provided by the user: {0}")]
100 ParamParsingError(String),
101 #[error("Invalid path")]
103 PathError,
104 #[error("Failed to execute rustfmt")]
106 RustfmtError(std::io::Error),
107 #[error("Failed to find the runtime {0}")]
109 RuntimeNotFound(String),
110 #[error("Template error: {0}")]
112 SourcingError(#[from] pop_common::sourcing::Error),
113 #[error("Subxt error: {0}")]
115 SubXtError(#[from] Box<subxt::Error>),
116 #[error("Toml error: {0}")]
118 TomlError(#[from] toml_edit::de::Error),
119 #[error("Failed to test with try-runtime: {0}")]
121 TryRuntimeError(String),
122 #[error("Unsupported command: {0}")]
124 UnsupportedCommand(String),
125 #[error("Failed to locate the workspace")]
127 WorkspaceLocate,
128}
129
130pub(crate) fn handle_command_error<F>(
133 output: &std::process::Output,
134 custom_error: F,
135) -> Result<(), Error>
136where
137 F: FnOnce(String) -> Error,
138{
139 if !output.status.success() {
140 let stderr_msg = String::from_utf8_lossy(&output.stderr);
141 return Err(custom_error(stderr_msg.to_string()));
142 }
143 Ok(())
144}
145
146#[cfg(test)]
147mod tests {
148 use super::*;
149 use anyhow::Result;
150 use std::{
151 os::unix::process::ExitStatusExt,
152 process::{ExitStatus, Output},
153 };
154
155 #[test]
156 fn handle_command_error_failure() -> Result<()> {
157 let output = Output {
158 status: ExitStatus::from_raw(1),
159 stdout: Vec::new(),
160 stderr: Vec::from("Error message".as_bytes()),
161 };
162 assert!(matches!(
163 handle_command_error(&output, Error::BuildSpecError),
164 Err(Error::BuildSpecError(message))
165 if message == "Error message"
166 ));
167 Ok(())
168 }
169}