use std::str::from_utf8; use macroconf::config; use miniconf::{Error::Absent, JsonCoreSlash, Tree, TreeKey}; use serde::{Deserialize, Serialize}; #[config] #[derive(Debug, Clone, Copy, Serialize, Deserialize, Tree)] struct SubConfig { skipped: i32, #[min] min: i32, #[max] max: i32, #[default = 0] default: i32, /// This is a description description: i32, } #[config] #[derive(Debug, Clone, Copy, Tree)] struct Config { #[tree(depth(2))] sub_config: SubConfig, } #[test] fn keys() { for (id, field) in ["skipped", "min", "max", "default", "description"] .into_iter() .enumerate() { assert_eq!( SubConfig::traverse_by_key(std::iter::once(field), |index, name| { assert_eq!((id, field), (index, name)); Ok::<_, ()>(()) }), Ok(1) ); } } #[test] fn sub_keys() { assert_eq!( SubConfig::traverse_by_key(["skipped", "value"].into_iter(), |_, _| Ok::<_, ()>(())), Ok(1) ); for field in ["min", "max", "default", "description"] { assert_eq!( SubConfig::traverse_by_key([field, "value"].into_iter(), |_, _| Ok::<_, ()>(())), Ok(2) ); assert_eq!( SubConfig::traverse_by_key([field, field].into_iter(), |_, _| Ok::<_, ()>(())), Ok(2) ); } } #[test] fn serialize() { let mut buffer = [0u8; 32]; let config = SubConfig { skipped: 1, min: __SubConfigMin::new(2), max: __SubConfigMax::new(3), default: __SubConfigDefault::new(4), description: __SubConfigDescription::new(5), }; for (input, output) in [ ("/skipped", "1"), ("/min", "2"), ("/min/value", "2"), ("/min/min", "-2147483648"), ("/max", "3"), ("/max/value", "3"), ("/max/max", "2147483647"), ("/default", "4"), ("/default/value", "4"), ("/default/default", "0"), ("/description", "5"), ("/description/value", "5"), ("/description/description", "\"This is a description\""), ] { let res = config.get_json(input, &mut buffer); assert_eq!(res, Ok(output.len())); assert_eq!(from_utf8(&buffer[..output.len()]), Ok(output)); } } #[test] fn deserialize() { let mut config = SubConfig { skipped: 0, min: __SubConfigMin::new(0), max: __SubConfigMax::new(0), default: __SubConfigDefault::new(0), description: __SubConfigDescription::new(0), }; for input in [ "/skipped", "/min", "/min/value", "/max", "/max/value", "/default", "/default/value", "/description", "/description/value", ] { let res = config.set_json(input, b"10"); assert_eq!(res, Ok(2)); } for input in [ "/min/min", "/max/max", "/default/default", "/description/description", ] { let res = config.set_json(input, b"10"); assert_eq!(res, Err(Absent(1))); } } #[test] fn subconfig() { let control = vec![ "/sub_config/skipped".to_owned(), "/sub_config/min/value".to_owned(), "/sub_config/min/min".to_owned(), "/sub_config/max/value".to_owned(), "/sub_config/max/max".to_owned(), "/sub_config/default/value".to_owned(), "/sub_config/default/default".to_owned(), "/sub_config/description/value".to_owned(), "/sub_config/description/description".to_owned(), ]; let paths: Vec = Config::iter_paths::("/") .filter_map(|path| path.ok()) .collect(); assert_eq!(paths, control); }