use std::sync::{Arc, Mutex}; use log::{Level, Log, Metadata, Record}; use alacritty_config_derive::ConfigDeserialize; #[derive(ConfigDeserialize, Debug, PartialEq, Eq)] enum TestEnum { One, Two, Three, #[config(skip)] Nine(String), } impl Default for TestEnum { fn default() -> Self { Self::Nine(String::from("nine")) } } #[derive(ConfigDeserialize)] struct Test { #[config(alias = "noalias")] #[config(deprecated = "use field2 instead")] field1: usize, #[config(deprecated = "shouldn't be hit")] field2: String, field3: Option, #[doc(hidden)] nesting: Test2, #[config(flatten)] flatten: Test3, enom_small: TestEnum, enom_big: TestEnum, #[config(deprecated)] enom_error: TestEnum, } impl Default for Test { fn default() -> Self { Self { field1: 13, field2: String::from("field2"), field3: Some(23), nesting: Test2::default(), flatten: Test3::default(), enom_small: TestEnum::default(), enom_big: TestEnum::default(), enom_error: TestEnum::default(), } } } #[derive(ConfigDeserialize, Default)] struct Test2 { field1: T, field2: Option, #[config(skip)] field3: usize, #[config(alias = "aliased")] field4: u8, } #[derive(ConfigDeserialize, Default)] struct Test3 { flatty: usize, } #[test] fn config_deserialize() { let logger = unsafe { LOGGER = Some(Logger::default()); LOGGER.as_mut().unwrap() }; log::set_logger(logger).unwrap(); log::set_max_level(log::LevelFilter::Warn); let test: Test = serde_yaml::from_str( r#" field1: 3 field3: 32 nesting: field1: "testing" field2: None field3: 99 aliased: 8 flatty: 123 enom_small: "one" enom_big: "THREE" enom_error: "HugaBuga" "#, ) .unwrap(); // Verify fields were deserialized correctly. assert_eq!(test.field1, 3); assert_eq!(test.field2, Test::default().field2); assert_eq!(test.field3, Some(32)); assert_eq!(test.enom_small, TestEnum::One); assert_eq!(test.enom_big, TestEnum::Three); assert_eq!(test.enom_error, Test::default().enom_error); assert_eq!(test.nesting.field1, Test::default().nesting.field1); assert_eq!(test.nesting.field2, None); assert_eq!(test.nesting.field3, Test::default().nesting.field3); assert_eq!(test.nesting.field4, 8); assert_eq!(test.flatten.flatty, 123); // Verify all log messages are correct. let error_logs = logger.error_logs.lock().unwrap(); assert_eq!(error_logs.as_slice(), [ "Config error: field1: invalid type: string \"testing\", expected usize", "Config error: enom_error: unknown variant `HugaBuga`, expected one of `One`, `Two`, \ `Three`", ]); let warn_logs = logger.warn_logs.lock().unwrap(); assert_eq!(warn_logs.as_slice(), [ "Config warning: field1 is deprecated; use field2 instead", "Config warning: enom_error is deprecated", ]); } static mut LOGGER: Option = None; /// Logger storing all messages for later validation. #[derive(Default)] struct Logger { error_logs: Arc>>, warn_logs: Arc>>, } impl Log for Logger { fn log(&self, record: &Record<'_>) { assert_eq!(record.target(), env!("CARGO_PKG_NAME")); match record.level() { Level::Error => { let mut error_logs = self.error_logs.lock().unwrap(); error_logs.push(record.args().to_string()); }, Level::Warn => { let mut warn_logs = self.warn_logs.lock().unwrap(); warn_logs.push(record.args().to_string()); }, _ => unreachable!(), } } fn enabled(&self, _metadata: &Metadata<'_>) -> bool { true } fn flush(&self) {} }