passivized_test_support/
cli.rs

1use core::future::Future;
2use std::fmt::Debug;
3use std::process::ExitCode;
4
5use log::{info, LevelFilter, warn};
6
7/// An implementation of the main() function of an example app.
8///
9/// Sets up logging and provides a reasonable process exit code.
10///
11/// # Example
12///
13/// ```rust
14/// use std::process::ExitCode;
15///
16/// #[tokio::main]
17/// async fn main() -> ExitCode {
18///     passivized_test_support::cli::run(run).await
19/// }
20///
21/// async fn run() -> Result<(), String> {
22///     // Implementation of example goes here.
23///
24///     Ok(())
25/// }
26/// ```
27pub async fn run<E, F, Fut>(implementation: F) -> ExitCode
28where
29    E: Debug,
30    F: FnOnce() -> Fut,
31    Fut: Future<Output = Result<(), E>>
32{
33    super::logging::enable();
34
35    run_impl(implementation).await
36}
37
38/// Same as run(), but with a custom log level
39pub async fn run_with_level<E, F, Fut>(implementation: F, log_level: LevelFilter) -> ExitCode
40where
41    E: Debug,
42    F: FnOnce() -> Fut,
43    Fut: Future<Output = Result<(), E>>
44{
45    super::logging::enable_with_level(log_level);
46
47    run_impl(implementation).await
48}
49
50/// Same as run(), but does NOT configure a logger.
51pub async fn run_impl<E, F, Fut>(implementation: F) -> ExitCode
52where
53    E: Debug,
54    F: FnOnce() -> Fut,
55    Fut: Future<Output = Result<(), E>>
56{
57    info!("Hello, world.");
58
59    match implementation().await {
60        Err(e) => {
61            warn!("Failed: {:?}", e);
62            ExitCode::FAILURE
63        }
64        Ok(_) => {
65            info!("Done.");
66            ExitCode::SUCCESS
67        }
68    }
69}