blob: 0ac41638e78928f8cb096632363249ec14a3f815 [file] [log] [blame]
// SPDX-FileCopyrightText: 2020 Robin Krahl <[email protected]>
// SPDX-License-Identifier: Apache-2.0 or MIT
#![cfg(feature = "derive")]
use merge::Merge;
fn test<T: std::fmt::Debug + Merge + PartialEq>(expected: T, mut left: T, right: T) {
left.merge(right);
assert_eq!(expected, left);
}
#[test]
fn test_one_option_field() {
#[derive(Debug, Merge, PartialEq)]
struct S {
field1: Option<usize>,
}
impl S {
pub fn new(field1: Option<usize>) -> S {
S { field1 }
}
}
test(S::new(Some(1)), S::new(Some(1)), S::new(Some(2)));
test(S::new(Some(1)), S::new(Some(1)), S::new(None));
test(S::new(Some(2)), S::new(None), S::new(Some(2)));
test(S::new(None), S::new(None), S::new(None));
}
#[test]
fn test_two_option_fields() {
#[derive(Debug, Merge, PartialEq)]
struct S {
field1: Option<usize>,
field2: Option<usize>,
}
impl S {
pub fn new(field1: Option<usize>, field2: Option<usize>) -> S {
S { field1, field2 }
}
}
// left.field1 == Some(1)
// right.field1 == Some(2)
test(
S::new(Some(1), Some(1)),
S::new(Some(1), Some(1)),
S::new(Some(2), Some(2)),
);
test(
S::new(Some(1), Some(1)),
S::new(Some(1), Some(1)),
S::new(Some(2), None),
);
test(
S::new(Some(1), Some(2)),
S::new(Some(1), None),
S::new(Some(2), Some(2)),
);
test(
S::new(Some(1), None),
S::new(Some(1), None),
S::new(Some(2), None),
);
// left.field1 == Some(1)
// right.field1 == None
test(
S::new(Some(1), Some(1)),
S::new(Some(1), Some(1)),
S::new(None, Some(2)),
);
test(
S::new(Some(1), Some(1)),
S::new(Some(1), Some(1)),
S::new(None, None),
);
test(
S::new(Some(1), Some(2)),
S::new(Some(1), None),
S::new(None, Some(2)),
);
test(
S::new(Some(1), None),
S::new(Some(1), None),
S::new(None, None),
);
// left.field1 == None
// right.field1 == Some(2)
test(
S::new(Some(2), Some(1)),
S::new(None, Some(1)),
S::new(Some(2), Some(2)),
);
test(
S::new(Some(2), Some(1)),
S::new(None, Some(1)),
S::new(Some(2), None),
);
test(
S::new(Some(2), Some(2)),
S::new(None, None),
S::new(Some(2), Some(2)),
);
test(
S::new(Some(2), None),
S::new(None, None),
S::new(Some(2), None),
);
// left.field1 == None
// right.field1 == None
test(
S::new(None, Some(1)),
S::new(None, Some(1)),
S::new(None, Some(2)),
);
test(
S::new(None, Some(1)),
S::new(None, Some(1)),
S::new(None, None),
);
test(
S::new(None, Some(2)),
S::new(None, None),
S::new(None, Some(2)),
);
test(S::new(None, None), S::new(None, None), S::new(None, None));
}
#[test]
fn test_skip_valid() {
#[derive(Debug, Merge, PartialEq)]
struct S {
field1: Option<usize>,
#[merge(skip)]
field2: Option<usize>,
}
impl S {
pub fn new(field1: Option<usize>, field2: Option<usize>) -> S {
S { field1, field2 }
}
}
// left.field1 == Some(1)
// right.field1 == Some(2)
test(
S::new(Some(1), Some(1)),
S::new(Some(1), Some(1)),
S::new(Some(2), Some(2)),
);
test(
S::new(Some(1), Some(1)),
S::new(Some(1), Some(1)),
S::new(Some(2), None),
);
test(
S::new(Some(1), None),
S::new(Some(1), None),
S::new(Some(2), Some(2)),
);
test(
S::new(Some(1), None),
S::new(Some(1), None),
S::new(Some(2), None),
);
// left.field1 == Some(1)
// right.field1 == None
test(
S::new(Some(1), Some(1)),
S::new(Some(1), Some(1)),
S::new(None, Some(2)),
);
test(
S::new(Some(1), Some(1)),
S::new(Some(1), Some(1)),
S::new(None, None),
);
test(
S::new(Some(1), None),
S::new(Some(1), None),
S::new(None, Some(2)),
);
test(
S::new(Some(1), None),
S::new(Some(1), None),
S::new(None, None),
);
// left.field1 == None
// right.field1 == Some(2)
test(
S::new(Some(2), Some(1)),
S::new(None, Some(1)),
S::new(Some(2), Some(2)),
);
test(
S::new(Some(2), Some(1)),
S::new(None, Some(1)),
S::new(Some(2), None),
);
test(
S::new(Some(2), None),
S::new(None, None),
S::new(Some(2), Some(2)),
);
test(
S::new(Some(2), None),
S::new(None, None),
S::new(Some(2), None),
);
// left.field1 == None
// right.field1 == None
test(
S::new(None, Some(1)),
S::new(None, Some(1)),
S::new(None, Some(2)),
);
test(
S::new(None, Some(1)),
S::new(None, Some(1)),
S::new(None, None),
);
test(
S::new(None, None),
S::new(None, None),
S::new(None, Some(2)),
);
test(S::new(None, None), S::new(None, None), S::new(None, None));
}
#[test]
fn test_skip_invalid() {
#[derive(Debug, Merge, PartialEq)]
struct S {
field1: Option<usize>,
#[merge(skip)]
field2: usize,
}
impl S {
pub fn new(field1: Option<usize>, field2: usize) -> S {
S { field1, field2 }
}
}
// left.field1 == Some(1)
// right.field1 == Some(2)
test(S::new(Some(1), 1), S::new(Some(1), 1), S::new(Some(2), 2));
test(S::new(Some(1), 1), S::new(Some(1), 1), S::new(Some(2), 0));
test(S::new(Some(1), 0), S::new(Some(1), 0), S::new(Some(2), 2));
test(S::new(Some(1), 0), S::new(Some(1), 0), S::new(Some(2), 0));
// left.field1 == Some(1)
// right.field1 == None
test(S::new(Some(1), 1), S::new(Some(1), 1), S::new(None, 2));
test(S::new(Some(1), 1), S::new(Some(1), 1), S::new(None, 0));
test(S::new(Some(1), 0), S::new(Some(1), 0), S::new(None, 2));
test(S::new(Some(1), 0), S::new(Some(1), 0), S::new(None, 0));
// left.field1 == None
// right.field1 == Some(2)
test(S::new(Some(2), 1), S::new(None, 1), S::new(Some(2), 2));
test(S::new(Some(2), 1), S::new(None, 1), S::new(Some(2), 0));
test(S::new(Some(2), 0), S::new(None, 0), S::new(Some(2), 2));
test(S::new(Some(2), 0), S::new(None, 0), S::new(Some(2), 0));
// left.field1 == None
// right.field1 == None
test(S::new(None, 1), S::new(None, 1), S::new(None, 2));
test(S::new(None, 1), S::new(None, 1), S::new(None, 0));
test(S::new(None, 0), S::new(None, 0), S::new(None, 2));
test(S::new(None, 0), S::new(None, 0), S::new(None, 0));
}
#[test]
fn test_strategy_usize_add() {
#[derive(Debug, Merge, PartialEq)]
struct S {
#[merge(strategy = add)]
field1: usize,
}
impl S {
pub fn new(field1: usize) -> S {
S { field1 }
}
}
fn add(left: &mut usize, right: usize) {
*left = *left + right;
}
test(S::new(0), S::new(0), S::new(0));
test(S::new(1), S::new(1), S::new(0));
test(S::new(1), S::new(0), S::new(1));
test(S::new(2), S::new(1), S::new(1));
}
#[test]
fn test_strategy_vec_append() {
#[derive(Debug, Merge, PartialEq)]
struct S {
#[merge(strategy = append)]
field1: Vec<usize>,
}
impl S {
pub fn new(field1: Vec<usize>) -> S {
S { field1 }
}
}
fn append(left: &mut Vec<usize>, mut right: Vec<usize>) {
left.append(&mut right);
}
test(
S::new(vec![0, 1, 2, 3]),
S::new(vec![0, 1]),
S::new(vec![2, 3]),
);
test(
S::new(vec![0, 1, 2, 3]),
S::new(vec![0, 1, 2, 3]),
S::new(vec![]),
);
test(
S::new(vec![0, 1, 2, 3]),
S::new(vec![]),
S::new(vec![0, 1, 2, 3]),
);
}
#[test]
fn test_unnamed_fields() {
#[derive(Debug, Merge, PartialEq)]
struct S(Option<usize>, Option<usize>);
impl S {
pub fn new(field1: Option<usize>, field2: Option<usize>) -> S {
S(field1, field2)
}
}
// left.field1 == Some(1)
// right.field1 == Some(2)
test(
S::new(Some(1), Some(1)),
S::new(Some(1), Some(1)),
S::new(Some(2), Some(2)),
);
test(
S::new(Some(1), Some(1)),
S::new(Some(1), Some(1)),
S::new(Some(2), None),
);
test(
S::new(Some(1), Some(2)),
S::new(Some(1), None),
S::new(Some(2), Some(2)),
);
test(
S::new(Some(1), None),
S::new(Some(1), None),
S::new(Some(2), None),
);
// left.field1 == Some(1)
// right.field1 == None
test(
S::new(Some(1), Some(1)),
S::new(Some(1), Some(1)),
S::new(None, Some(2)),
);
test(
S::new(Some(1), Some(1)),
S::new(Some(1), Some(1)),
S::new(None, None),
);
test(
S::new(Some(1), Some(2)),
S::new(Some(1), None),
S::new(None, Some(2)),
);
test(
S::new(Some(1), None),
S::new(Some(1), None),
S::new(None, None),
);
// left.field1 == None
// right.field1 == Some(2)
test(
S::new(Some(2), Some(1)),
S::new(None, Some(1)),
S::new(Some(2), Some(2)),
);
test(
S::new(Some(2), Some(1)),
S::new(None, Some(1)),
S::new(Some(2), None),
);
test(
S::new(Some(2), Some(2)),
S::new(None, None),
S::new(Some(2), Some(2)),
);
test(
S::new(Some(2), None),
S::new(None, None),
S::new(Some(2), None),
);
// left.field1 == None
// right.field1 == None
test(
S::new(None, Some(1)),
S::new(None, Some(1)),
S::new(None, Some(2)),
);
test(
S::new(None, Some(1)),
S::new(None, Some(1)),
S::new(None, None),
);
test(
S::new(None, Some(2)),
S::new(None, None),
S::new(None, Some(2)),
);
test(S::new(None, None), S::new(None, None), S::new(None, None));
}
#[test]
fn test_unnamed_fields_skip() {
#[derive(Debug, Merge, PartialEq)]
struct S(Option<usize>, #[merge(skip)] Option<usize>);
impl S {
pub fn new(field1: Option<usize>, field2: Option<usize>) -> S {
S(field1, field2)
}
}
// left.field1 == Some(1)
// right.field1 == Some(2)
test(
S::new(Some(1), Some(1)),
S::new(Some(1), Some(1)),
S::new(Some(2), Some(2)),
);
test(
S::new(Some(1), Some(1)),
S::new(Some(1), Some(1)),
S::new(Some(2), None),
);
test(
S::new(Some(1), None),
S::new(Some(1), None),
S::new(Some(2), Some(2)),
);
test(
S::new(Some(1), None),
S::new(Some(1), None),
S::new(Some(2), None),
);
// left.field1 == Some(1)
// right.field1 == None
test(
S::new(Some(1), Some(1)),
S::new(Some(1), Some(1)),
S::new(None, Some(2)),
);
test(
S::new(Some(1), Some(1)),
S::new(Some(1), Some(1)),
S::new(None, None),
);
test(
S::new(Some(1), None),
S::new(Some(1), None),
S::new(None, Some(2)),
);
test(
S::new(Some(1), None),
S::new(Some(1), None),
S::new(None, None),
);
// left.field1 == None
// right.field1 == Some(2)
test(
S::new(Some(2), Some(1)),
S::new(None, Some(1)),
S::new(Some(2), Some(2)),
);
test(
S::new(Some(2), Some(1)),
S::new(None, Some(1)),
S::new(Some(2), None),
);
test(
S::new(Some(2), None),
S::new(None, None),
S::new(Some(2), Some(2)),
);
test(
S::new(Some(2), None),
S::new(None, None),
S::new(Some(2), None),
);
// left.field1 == None
// right.field1 == None
test(
S::new(None, Some(1)),
S::new(None, Some(1)),
S::new(None, Some(2)),
);
test(
S::new(None, Some(1)),
S::new(None, Some(1)),
S::new(None, None),
);
test(
S::new(None, None),
S::new(None, None),
S::new(None, Some(2)),
);
test(S::new(None, None), S::new(None, None), S::new(None, None));
}