use clap::Parser;
use rust_template_foundation::logging::{LogFormat, LogLevel};
use rust_template_foundation::MergeConfig;
use thiserror::Error;
#[derive(Debug, Error, PartialEq)]
enum MyError {
#[error("port {0} is reserved")]
ReservedPort(u16),
#[error("missing widget catalogue")]
MissingCatalogue,
}
#[derive(Debug, Clone, MergeConfig)]
#[merge_config(app_name = "extra-error-test", extra_error = "crate::MyError")]
pub struct Config {
#[merge_config(common)]
pub log_level: LogLevel,
#[merge_config(common)]
pub log_format: LogFormat,
#[merge_config(default = "8080")]
pub port: u16,
#[merge_config(skip)]
pub catalogue: String,
}
impl Config {
fn resolve_catalogue(
_cli: &CliRaw,
_file: &ConfigFileRaw,
) -> Result<String, MyError> {
Err(MyError::MissingCatalogue)
}
}
#[test]
fn user_error_propagates_as_extra_variant() {
let cli = CliRaw::try_parse_from(["extra-error-test"]).unwrap();
let err = Config::from_cli_and_file(cli).unwrap_err();
match err {
ConfigError::Extra(MyError::MissingCatalogue) => {}
other => panic!("expected Extra(MissingCatalogue), got {:?}", other),
}
}
#[test]
fn extra_variant_display_is_transparent() {
let inner = MyError::ReservedPort(22);
let inner_display = inner.to_string();
let wrapped = ConfigError::Extra(inner);
assert_eq!(wrapped.to_string(), inner_display);
}
#[test]
fn from_user_error_into_config_error() {
let err: ConfigError = MyError::ReservedPort(80).into();
assert!(matches!(err, ConfigError::Extra(MyError::ReservedPort(80))));
}