use std::sync::{Arc, Mutex}; use log::{Level, Log, Metadata, Record}; use serde::Deserialize; use alacritty_config::SerdeReplace as _; use alacritty_config_derive::{ConfigDeserialize, SerdeReplace}; #[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, #[config(removed = "it's gone")] gone: bool, } 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(), gone: false, } } } #[derive(ConfigDeserialize, Default)] struct Test2 { field1: T, field2: Option, #[config(skip)] field3: usize, #[config(alias = "aliased")] field4: u8, newtype: NewType, } #[derive(ConfigDeserialize, Default)] struct Test3 { flatty: usize, } #[derive(SerdeReplace, Deserialize, Default, PartialEq, Eq, Debug)] struct NewType(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" gone: false "#, ) .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!(!test.gone); 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 has been deprecated; use field2 instead", "Config warning: enom_error has been deprecated", "Config warning: gone has been removed; it's gone", ]); } 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) {} } #[test] fn field_replacement() { let mut test = Test::default(); let value = serde_yaml::to_value(13).unwrap(); test.replace("nesting.field2", value).unwrap(); assert_eq!(test.nesting.field2, Some(13)); } #[test] fn replace_derive() { let mut test = Test::default(); let value = serde_yaml::to_value(9).unwrap(); test.replace("nesting.newtype", value).unwrap(); assert_eq!(test.nesting.newtype, NewType(9)); } #[test] fn replace_flatten() { let mut test = Test::default(); let value = serde_yaml::to_value(7).unwrap(); test.replace("flatty", value).unwrap(); assert_eq!(test.flatten.flatty, 7); }