#![allow(dead_code)] use schematic::*; use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet}; #[derive(Config)] pub struct MergeNormal { string: String, vector: Vec, map: HashMap, } fn merge_string(prev: String, next: String, _: &C) -> MergeResult { Ok(Some(format!("{}-{}", prev, next))) } #[derive(Config)] pub struct MergeFunc { #[setting(merge = merge_string)] string: String, #[setting(merge = merge::prepend_vec)] vector: Vec, #[setting(merge = merge::discard)] map: HashMap, } #[test] fn normal_merge_takes_some_next() { let mut base = PartialMergeNormal { string: Some("foo".into()), vector: Some(vec![1, 2, 3]), map: Some(HashMap::from_iter([("a".into(), 1)])), }; base.merge( &(), PartialMergeNormal { string: Some("bar".into()), vector: Some(vec![4, 5, 6]), map: None, }, ) .unwrap(); assert_eq!(base.string.unwrap(), "bar"); assert_eq!(base.vector.unwrap(), vec![4, 5, 6]); assert_eq!(base.map.unwrap(), HashMap::from_iter([("a".into(), 1)])); } #[test] fn custom_merge_with_funcs() { let mut base = PartialMergeFunc { string: Some("foo".into()), vector: Some(vec![1, 2, 3]), map: Some(HashMap::from_iter([("a".into(), 1)])), }; base.merge( &(), PartialMergeFunc { string: Some("bar".into()), vector: Some(vec![4, 5, 6]), map: Some(HashMap::from_iter([("b".into(), 2)])), }, ) .unwrap(); assert_eq!(base.string.unwrap(), "foo-bar"); assert_eq!(base.vector.unwrap(), vec![4, 5, 6, 1, 2, 3]); assert_eq!(base.map, None); } #[derive(Debug, Config)] pub struct MergeNested { #[setting(default = "xyz")] string: String, #[setting(default = 10)] other: usize, } #[derive(Debug, Config)] pub struct MergeBase { #[setting(default = "abc")] string: String, #[setting(default = vec![1,2,3], merge = merge::append_vec)] vector: Vec, #[setting(nested)] nested: MergeNested, #[setting(nested)] opt_nested: Option, } #[test] fn uses_defaults_when_no_layers() { let result = ConfigLoader::::new().load().unwrap(); assert_eq!(result.config.string, "abc"); assert_eq!(result.config.vector, vec![1, 2, 3]); assert_eq!(result.config.nested.string, "xyz"); assert_eq!(result.config.nested.other, 10); assert!(result.config.opt_nested.is_none()); } #[test] fn can_merge_with_defaults() { let result = ConfigLoader::::new() .code("string: def", Format::Yaml) .unwrap() .code("vector: [4]", Format::Yaml) .unwrap() .code( r"vector: [5] nested: string: zyx ", Format::Yaml, ) .unwrap() .code( r"nested: other: 15 ", Format::Yaml, ) .unwrap() .load() .unwrap(); assert_eq!(result.config.string, "def"); assert_eq!(result.config.vector, vec![1, 2, 3, 4, 5]); assert_eq!(result.config.nested.string, "zyx"); assert_eq!(result.config.nested.other, 15); assert!(result.config.opt_nested.is_none()); } #[test] fn loads_defaults_for_optional_nested() { let result = ConfigLoader::::new() .code( r" optNested: string: hij", Format::Yaml, ) .unwrap() .load() .unwrap(); assert!(result.config.opt_nested.is_some()); assert_eq!(result.config.opt_nested.as_ref().unwrap().string, "hij"); assert_eq!(result.config.opt_nested.as_ref().unwrap().other, 10); } mod helpers { use super::*; #[test] fn discard() { assert_eq!(merge::discard(1, 2, &()).unwrap(), None); } #[test] fn preserve() { assert_eq!(merge::preserve(1, 2, &()).unwrap(), Some(1)); } #[test] fn replace() { assert_eq!(merge::replace(1, 2, &()).unwrap(), Some(2)); } #[test] fn append_vec() { assert_eq!( merge::append_vec(vec![1], vec![2], &()).unwrap(), Some(vec![1, 2]) ); } #[test] fn prepend_vec() { assert_eq!( merge::prepend_vec(vec![1], vec![2], &()).unwrap(), Some(vec![2, 1]) ); } #[test] fn merge_btreemap() { assert_eq!( merge::merge_btreemap( BTreeMap::from_iter([("a".to_string(), 1), ("b".to_string(), 2)]), BTreeMap::from_iter([("b".to_string(), 3), ("c".to_string(), 4)]), &() ) .unwrap(), Some(BTreeMap::from_iter([ ("a".to_string(), 1), ("b".to_string(), 3), ("c".to_string(), 4), ])) ); } #[test] fn merge_btreeset() { assert_eq!( merge::merge_btreeset( BTreeSet::from_iter(["a", "b"]), BTreeSet::from_iter(["a", "b", "c", "d"]), &() ) .unwrap(), Some(BTreeSet::from_iter(["a", "b", "c", "d"])) ); } #[test] fn merge_hashmap() { assert_eq!( merge::merge_hashmap( HashMap::from_iter([("a".to_string(), 1), ("b".to_string(), 2)]), HashMap::from_iter([("b".to_string(), 3), ("c".to_string(), 4)]), &() ) .unwrap(), Some(HashMap::from_iter([ ("a".to_string(), 1), ("b".to_string(), 3), ("c".to_string(), 4), ])) ); } #[test] fn merge_hashset() { assert_eq!( merge::merge_hashset( HashSet::from_iter(["a", "b"]), HashSet::from_iter(["a", "b", "c", "d"]), &() ) .unwrap(), Some(HashSet::from_iter(["a", "b", "c", "d"])) ); } }