1
0
Fork 0
mirror of https://github.com/alacritty/alacritty.git synced 2024-11-11 13:51:01 -05:00
alacritty/alacritty_config_derive/tests/config.rs
Christian Duerr afffdbe612
Fix alacritty msg config toml replacement
This fixes a regression introduced in bd49067 which broke the override
of configuration file variables using `alacritty msg config`.

To fix this the `replace` functionality was rewritten to behave more
like the `serde_utils::merge` where entire values are inserted into the
existing structure rather than separating the keys from the values.

Fixes: bd49067 (Switch to TOML configuration format)
2023-06-15 08:59:12 +00:00

200 lines
5 KiB
Rust

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<u8>,
#[doc(hidden)]
nesting: Test2<usize>,
#[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<T: Default> {
field1: T,
field2: Option<usize>,
#[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 = toml::from_str(
r#"
field1 = 3
field3 = 32
flatty = 123
enom_small = "one"
enom_big = "THREE"
enom_error = "HugaBuga"
gone = false
[nesting]
field1 = "testing"
field2 = "None"
field3 = 99
aliased = 8
"#,
)
.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: enom_error: unknown variant `HugaBuga`, expected one of `One`, `Two`, \
`Three`",
"Config error: field1: invalid type: string \"testing\", expected usize",
]);
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",
"Unused config key: field3",
]);
}
static mut LOGGER: Option<Logger> = None;
/// Logger storing all messages for later validation.
#[derive(Default)]
struct Logger {
error_logs: Arc<Mutex<Vec<String>>>,
warn_logs: Arc<Mutex<Vec<String>>>,
}
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 = toml::from_str("nesting.field2=13").unwrap();
test.replace(value).unwrap();
assert_eq!(test.nesting.field2, Some(13));
}
#[test]
fn replace_derive() {
let mut test = Test::default();
let value = toml::from_str("nesting.newtype=9").unwrap();
test.replace(value).unwrap();
assert_eq!(test.nesting.newtype, NewType(9));
}
#[test]
fn replace_flatten() {
let mut test = Test::default();
let value = toml::from_str("flatty=7").unwrap();
test.replace(value).unwrap();
assert_eq!(test.flatten.flatty, 7);
}