Repository: alacritty/alacritty
File: alacritty_config_derive/tests/config.rs (Rust)

Code before:
    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\nUse `alacritty migrate` \
         to automatically resolve it",
        "Config warning: enom_error has been deprecated\nUse `alacritty migrate` to automatically \
         resolve it",
        "Config warning: gone has been removed; it's gone\nUse `alacritty migrate` to \
         automatically resolve it",
        "Unused config key: field3",
    ]);
}

/// 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!(),

Review comment (bug):
This actually failed after the update, it should never fail again with the sort in place. I don't think order actually matters so this should be fine.

Code after:
    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 mut error_logs = logger.error_logs.lock().unwrap();
    error_logs.sort_unstable();
    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 mut warn_logs = logger.warn_logs.lock().unwrap();
    warn_logs.sort_unstable();
    assert_eq!(warn_logs.as_slice(), [
        "Config warning: enom_error has been deprecated\nUse `alacritty migrate` to automatically \
         resolve it",
        "Config warning: field1 has been deprecated; use field2 instead\nUse `alacritty migrate` \
         to automatically resolve it",
        "Config warning: gone has been removed; it's gone\nUse `alacritty migrate` to \
         automatically resolve it",
        "Unused config key: field3",
    ]);
}

/// 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());