mod common;
use serde::Deserialize;
use std::io::Write;
use std::path::PathBuf;
use confers::ConfigBuilder;
#[derive(Debug, Default, PartialEq, Deserialize)]
struct DbConfig {
host: String,
port: u16,
}
#[derive(Debug, Default, PartialEq, Deserialize)]
struct AppConfig {
database: DbConfig,
}
fn create_local_temp_config(content: &str, extension: &str) -> (tempfile::NamedTempFile, PathBuf) {
let current_dir = std::env::current_dir().unwrap();
let ext = extension.trim_start_matches('.');
let mut file = tempfile::Builder::new()
.suffix(&format!(".{ext}"))
.tempfile_in(¤t_dir)
.unwrap();
file.write_all(content.as_bytes()).unwrap();
file.flush().unwrap();
let absolute_path = file.path().to_path_buf();
let relative_path = absolute_path
.strip_prefix(¤t_dir)
.unwrap_or(&absolute_path)
.to_path_buf();
(file, relative_path)
}
fn assert_app_config(config: &AppConfig) {
assert_eq!(
config.database.host, "localhost",
"nested database.host should deserialize to 'localhost'"
);
assert_eq!(
config.database.port, 5432,
"nested database.port should deserialize to 5432"
);
}
#[cfg(feature = "toml")]
#[test]
fn test_nested_toml_deserializes_into_struct() {
let content = r#"
[database]
host = "localhost"
port = 5432
"#;
let (_file, path) = create_local_temp_config(content, ".toml");
let config: AppConfig = ConfigBuilder::new()
.file(&path)
.build()
.expect("TOML with nested [database] table should deserialize into AppConfig");
assert_app_config(&config);
}
#[cfg(feature = "json")]
#[test]
fn test_nested_json_deserializes_into_struct() {
let content = r#"{
"database": {
"host": "localhost",
"port": 5432
}
}"#;
let (_file, path) = create_local_temp_config(content, ".json");
let config: AppConfig = ConfigBuilder::new()
.file(&path)
.build()
.expect("JSON with nested database object should deserialize into AppConfig");
assert_app_config(&config);
}
#[cfg(feature = "yaml")]
#[test]
fn test_nested_yaml_deserializes_into_struct() {
let content = r#"
database:
host: localhost
port: 5432
"#;
let (_file, path) = create_local_temp_config(content, ".yaml");
let config: AppConfig = ConfigBuilder::new()
.file(&path)
.build()
.expect("YAML with nested database mapping should deserialize into AppConfig");
assert_app_config(&config);
}