use std::collections::BTreeMap;
use crate::config::MergeStrategy;
use crate::domain::{
Format, ParsedContent, RawContent, Result, Source, SourceKind, SourceMetadata,
};
use super::Loader;
struct TestSource {
content: String,
format: Format,
optional: bool,
}
impl TestSource {
fn new(content: &str, format: Format) -> Self {
Self {
content: content.to_string(),
format,
optional: false,
}
}
fn with_optional(mut self, optional: bool) -> Self {
self.optional = optional;
self
}
}
impl Source for TestSource {
fn kind(&self) -> SourceKind {
SourceKind::Memory
}
fn metadata(&self) -> SourceMetadata {
SourceMetadata::new("test")
}
fn load_raw(&self) -> Result<RawContent> {
Ok(RawContent::from_string(&self.content))
}
fn detect_format(&self) -> Option<Format> {
Some(self.format)
}
fn is_optional(&self) -> bool {
self.optional
}
}
#[test]
fn test_loader_new() {
let loader = Loader::new();
assert_eq!(loader.options().merge_strategy, MergeStrategy::Deep);
}
#[test]
fn test_loader_builder() {
let loader = Loader::builder()
.merge_strategy(MergeStrategy::Replace)
.fail_fast(false)
.build();
assert_eq!(loader.options().merge_strategy, MergeStrategy::Replace);
assert!(!loader.options().is_fail_fast());
}
#[test]
fn test_loader_load_raw() {
let source = TestSource::new(r#"key = "value""#, Format::Toml);
let loader = Loader::new();
let raw = loader.load_raw(&source).unwrap();
assert!(!raw.is_empty());
}
#[test]
fn test_loader_load() {
let source = TestSource::new(r#"key = "value""#, Format::Toml);
let loader = Loader::new();
let content = loader.load(&source).unwrap();
assert!(content.is_object());
}
#[test]
fn test_loader_load_layer() {
let source = TestSource::new(r#"{"key": "value"}"#, Format::Json);
let loader = Loader::new();
let layer = loader.load_layer(&source).unwrap();
assert_eq!(layer.metadata.display_id(), "test");
assert_eq!(layer.registration_index, 0);
assert_eq!(layer.content.get("key").unwrap().as_str(), Some("value"));
}
#[test]
fn test_loader_load_layers() {
let source1 = TestSource::new(r#"{"a": 1}"#, Format::Json);
let source2 = TestSource::new(r#"{"b": 2}"#, Format::Json);
let loader = Loader::new();
let layers = loader.load_layers(&[source1, source2]).unwrap();
assert_eq!(layers.len(), 2);
assert_eq!(layers[0].registration_index, 0);
assert_eq!(layers[1].registration_index, 1);
assert_eq!(layers[0].content.get("a").unwrap().as_integer(), Some(1));
assert_eq!(layers[1].content.get("b").unwrap().as_integer(), Some(2));
}
#[test]
fn test_loader_parse() {
let raw = RawContent::from_string(r#"{"key": "value"}"#);
let loader = Loader::new();
let content = loader.parse(&raw, Format::Json).unwrap();
assert!(content.is_object());
}
#[test]
fn test_loader_merge_empty() {
let loader = Loader::new();
let result = loader.merge(vec![]).unwrap();
assert!(result.is_null());
}
#[test]
fn test_loader_merge_single() {
let loader = Loader::new();
let mut obj = BTreeMap::new();
obj.insert(
"key".to_string(),
ParsedContent::String("value".to_string()),
);
let content = ParsedContent::Object(obj);
let result = loader.merge(vec![content.clone()]).unwrap();
assert_eq!(result, content);
}
#[test]
fn test_loader_merge_multiple() {
let loader = Loader::builder()
.merge_strategy(MergeStrategy::Deep)
.build();
let mut obj1 = BTreeMap::new();
obj1.insert("a".to_string(), ParsedContent::Integer(1));
let mut obj2 = BTreeMap::new();
obj2.insert("b".to_string(), ParsedContent::Integer(2));
let result = loader
.merge(vec![
ParsedContent::Object(obj1),
ParsedContent::Object(obj2),
])
.unwrap();
assert!(result.get("a").is_some());
assert!(result.get("b").is_some());
}
#[test]
fn test_loader_merge_shallow() {
let loader = Loader::builder()
.merge_strategy(MergeStrategy::Shallow)
.build();
let nested_low = ParsedContent::from_json(serde_json::json!({
"section": {
"host": "localhost",
"port": 8080
}
}));
let nested_high = ParsedContent::from_json(serde_json::json!({
"section": {
"port": 3000
}
}));
let result = loader.merge(vec![nested_low, nested_high]).unwrap();
let section = result.get("section").unwrap();
assert_eq!(section.get("port").unwrap().as_integer(), Some(3000));
assert!(section.get("host").is_none());
}
#[test]
fn test_loader_merge_strict_conflict() {
let loader = Loader::builder()
.merge_strategy(MergeStrategy::Strict)
.build();
let result = loader.merge(vec![
ParsedContent::from_json(serde_json::json!({ "port": 8080 })),
ParsedContent::from_json(serde_json::json!({ "port": 3000 })),
]);
assert!(result.is_err());
}
#[test]
fn test_loader_to_type() {
use serde::Deserialize;
#[derive(Debug, Deserialize, PartialEq)]
struct Config {
name: String,
}
let loader = Loader::new();
let mut obj = BTreeMap::new();
obj.insert(
"name".to_string(),
ParsedContent::String("test".to_string()),
);
let content = ParsedContent::Object(obj);
let config: Config = loader.to_type(content).unwrap();
assert_eq!(config.name, "test");
}
#[test]
fn test_loader_load_multiple() {
let source1 = TestSource::new(r#"{"a": 1}"#, Format::Json);
let source2 = TestSource::new(r#"{"b": 2}"#, Format::Json);
let loader = Loader::builder()
.merge_strategy(MergeStrategy::Deep)
.build();
let result = loader.load_multiple(&[source1, source2]).unwrap();
assert!(result.get("a").is_some());
assert!(result.get("b").is_some());
}
#[test]
fn test_loader_load_multiple_with_optional() {
let source1 = TestSource::new(r#"{"a": 1}"#, Format::Json);
let source2 = TestSource::new(r"invalid", Format::Toml).with_optional(true);
let loader = Loader::builder().fail_fast(false).build();
let result = loader.load_multiple(&[source1, source2]).unwrap();
assert!(result.get("a").is_some());
}
#[test]
fn test_loader_default_format() {
let source = TestSource::new(r#"{"key": "value"}"#, Format::Unknown);
let loader = Loader::builder().default_format(Format::Json).build();
let content = loader.load(&source).unwrap();
assert!(content.is_object());
}