Skip to content

Commit e03bca1

Browse files
committed
feat: handle retryable errors in e2e test
1 parent c7a9802 commit e03bca1

File tree

1 file changed

+116
-3
lines changed
  • mithril-test-lab/mithril-end-to-end/src

1 file changed

+116
-3
lines changed

mithril-test-lab/mithril-end-to-end/src/main.rs

Lines changed: 116 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@ use clap::{CommandFactory, Parser, Subcommand};
33
use slog::{Drain, Level, Logger};
44
use slog_scope::{error, info, warn};
55
use std::{
6-
fs,
6+
fmt, fs,
77
path::{Path, PathBuf},
8+
process::{ExitCode, Termination},
89
sync::Arc,
910
time::Duration,
1011
};
@@ -18,6 +19,7 @@ use mithril_common::StdResult;
1819
use mithril_doc::GenerateDocCommands;
1920
use mithril_end_to_end::{
2021
Devnet, DevnetBootstrapArgs, MithrilInfrastructure, MithrilInfrastructureConfig, RunOnly, Spec,
22+
UnrecoverableDevnetError,
2123
};
2224

2325
/// Tests args
@@ -152,8 +154,16 @@ enum EndToEndCommands {
152154
GenerateDoc(GenerateDocCommands),
153155
}
154156

155-
#[tokio::main]
156-
async fn main() -> StdResult<()> {
157+
fn main() -> AppResult {
158+
tokio::runtime::Builder::new_multi_thread()
159+
.enable_all()
160+
.build()
161+
.unwrap()
162+
.block_on(async { main_exec().await })
163+
.into()
164+
}
165+
166+
async fn main_exec() -> StdResult<()> {
157167
let args = Args::parse();
158168
let _guard = slog_scope::set_global_logger(build_logger(&args));
159169

@@ -198,9 +208,66 @@ async fn main() -> StdResult<()> {
198208

199209
app_stopper.stop().await;
200210
join_set.shutdown().await;
211+
201212
res
202213
}
203214

215+
#[derive(Debug)]
216+
enum AppResult {
217+
Success(),
218+
UnretryableError(anyhow::Error),
219+
RetryableError(anyhow::Error),
220+
}
221+
222+
impl AppResult {
223+
fn exit_code(&self) -> ExitCode {
224+
match self {
225+
AppResult::Success() => ExitCode::SUCCESS,
226+
AppResult::UnretryableError(_) => ExitCode::FAILURE,
227+
AppResult::RetryableError(_) => ExitCode::from(2),
228+
}
229+
}
230+
}
231+
232+
impl fmt::Display for AppResult {
233+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
234+
match self {
235+
AppResult::Success() => write!(f, "Success"),
236+
AppResult::UnretryableError(error) => write!(f, "Error(Unretryable): {error:?}"),
237+
AppResult::RetryableError(error) => write!(f, "Error(Retryable): {error:?}"),
238+
}
239+
}
240+
}
241+
242+
impl Termination for AppResult {
243+
fn report(self) -> ExitCode {
244+
let exit_code = self.exit_code();
245+
println!(" ");
246+
println!("----------------------------------------------------------------------------------------------------");
247+
println!("Mithril End to End test outcome:");
248+
println!("----------------------------------------------------------------------------------------------------");
249+
println!("{self}");
250+
println!("{exit_code:?}");
251+
252+
exit_code
253+
}
254+
}
255+
256+
impl From<StdResult<()>> for AppResult {
257+
fn from(result: StdResult<()>) -> Self {
258+
match result {
259+
Ok(()) => AppResult::Success(),
260+
Err(error) => {
261+
if error.is::<UnrecoverableDevnetError>() {
262+
AppResult::RetryableError(error)
263+
} else {
264+
AppResult::UnretryableError(error)
265+
}
266+
}
267+
}
268+
}
269+
}
270+
204271
struct App {
205272
devnet: Arc<Mutex<Option<Devnet>>>,
206273
infrastructure: Arc<Mutex<Option<MithrilInfrastructure>>>,
@@ -366,3 +433,49 @@ fn with_gracefull_shutdown(join_set: &mut JoinSet<StdResult<()>>) {
366433
.inspect(|()| warn!("Received SIGQUIT"))
367434
});
368435
}
436+
437+
#[cfg(test)]
438+
mod tests {
439+
use super::*;
440+
441+
#[test]
442+
fn app_result_exit_code() {
443+
let expected_exit_code = ExitCode::SUCCESS;
444+
let exit_code = AppResult::Success().exit_code();
445+
assert_eq!(
446+
format!("{:?}", expected_exit_code),
447+
format!("{:?}", exit_code)
448+
);
449+
450+
let expected_exit_code = ExitCode::FAILURE;
451+
let exit_code = AppResult::UnretryableError(anyhow::anyhow!("an error")).exit_code();
452+
assert_eq!(
453+
format!("{:?}", expected_exit_code),
454+
format!("{:?}", exit_code)
455+
);
456+
457+
let expected_exit_code = ExitCode::from(2);
458+
let exit_code = AppResult::RetryableError(anyhow::anyhow!("an error")).exit_code();
459+
assert_eq!(
460+
format!("{:?}", expected_exit_code),
461+
format!("{:?}", exit_code)
462+
);
463+
}
464+
465+
#[test]
466+
fn app_result_conversion() {
467+
assert!(matches!(AppResult::from(Ok(())), AppResult::Success()));
468+
469+
assert!(matches!(
470+
AppResult::from(Err(anyhow!(UnrecoverableDevnetError(
471+
"an error".to_string()
472+
)))),
473+
AppResult::RetryableError(_)
474+
));
475+
476+
assert!(matches!(
477+
AppResult::from(Err(anyhow!("an error"))),
478+
AppResult::UnretryableError(_)
479+
));
480+
}
481+
}

0 commit comments

Comments
 (0)