#![cfg(feature = "cli-service")]
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
use hyperi_rustlib::cli::{CliError, CommonArgs, DfeApp, ServiceRuntime, VersionInfo, run_app};
struct ProbeApp {
common: CommonArgs,
cascade_was_populated: Arc<AtomicBool>,
log_level_seen: Arc<std::sync::Mutex<Option<String>>>,
}
impl DfeApp for ProbeApp {
type Config = ();
#[allow(clippy::unnecessary_literal_bound)]
fn name(&self) -> &str {
"cascade-probe"
}
#[allow(clippy::unnecessary_literal_bound)]
fn env_prefix(&self) -> &str {
"CASCADE_PROBE"
}
fn version_info(&self) -> VersionInfo {
VersionInfo::new("cascade-probe", "0.0.0-test")
}
fn common_args(&self) -> &CommonArgs {
&self.common
}
fn load_config(&self, _path: Option<&str>) -> Result<Self::Config, CliError> {
Ok(())
}
async fn run_service(
&self,
_config: Self::Config,
runtime: ServiceRuntime,
) -> Result<(), CliError> {
let cfg = hyperi_rustlib::config::try_get();
self.cascade_was_populated
.store(cfg.is_some(), Ordering::SeqCst);
if let Some(cfg) = cfg {
*self.log_level_seen.lock().unwrap() = cfg.get_string("log_level");
}
runtime.shutdown.cancel();
Ok(())
}
}
#[tokio::test]
async fn run_app_populates_cascade_from_config_file() {
let dir = std::env::temp_dir().join(format!("rustlib-runapp-cfg-{}", std::process::id()));
std::fs::create_dir_all(&dir).expect("create temp dir");
let file = dir.join("config.yaml");
std::fs::write(&file, "log_level: warn\n").expect("write config");
let cascade_was_populated = Arc::new(AtomicBool::new(false));
let log_level_seen = Arc::new(std::sync::Mutex::new(None));
let app = ProbeApp {
common: CommonArgs {
config: Some(file.to_string_lossy().into_owned()),
log_level: "info".to_string(),
log_format: "json".to_string(),
metrics_addr: "127.0.0.1:0".to_string(),
verbose: false,
quiet: true,
},
cascade_was_populated: Arc::clone(&cascade_was_populated),
log_level_seen: Arc::clone(&log_level_seen),
};
run_app(app).await.expect("run_app should succeed");
assert!(
cascade_was_populated.load(Ordering::SeqCst),
"run_app must populate the global config cascade before run_service"
);
assert_eq!(
*log_level_seen.lock().unwrap(),
Some("warn".to_string()),
"the cascade run_app built must carry the --config file's log_level (warn), \
proving the explicit file was actually ingested"
);
std::fs::remove_dir_all(&dir).ok();
}