#![cfg(test)]
use crate::prelude::*;
macro_rules! test {
($($name: ident),*) => {
$(
concat_idents::concat_idents!(fn_name = mset, $name {
#[test]
#[doc = concat!("Test [`Mset::", stringify!($name), "`].")]
fn fn_name() {
Mset::$name();
}
});
concat_idents::concat_idents!(fn_name = set, $name {
#[test]
#[doc = concat!("Test [`Set::", stringify!($name), "`].")]
fn fn_name() {
Set::$name();
}
});
)*
};
}
macro_rules! assert_beq {
($expect: expr, $cmp: expr, $msg: literal) => {
let expect = $expect;
if expect != $cmp {
let not = if expect { " not " } else { " " };
panic!($msg, not);
}
};
}
trait Suite: SetTrait {
const SUITE: &'static [&'static str];
const MEM: &'static [(usize, usize)];
fn parse(str: &str) -> Self {
str.parse().expect("could not parse string")
}
#[must_use]
fn normalize(str: &str) -> String {
Self::parse(str).to_string()
}
fn roundtrip(&self, str: &str) {
assert_eq!(
self,
&Self::parse(str),
"roundtrip fail: {str} not mapped to {self}"
);
assert_eq!(
self.to_string(),
str,
"roundtrip fail: {self} not mapped to {str}"
);
}
fn suite() -> impl Iterator<Item = (usize, &'static str, Self)> {
Self::SUITE
.iter()
.enumerate()
.map(|(i, &str)| (i, str, Self::parse(str)))
}
fn _suite() {
for j in 1..Self::SUITE.len() {
let i = j - 1;
let fst = &Self::SUITE[i];
let snd = &Self::SUITE[j];
assert!(
fst > snd,
"suite fail at {i}, {j}: {fst} not greater than {snd}",
);
}
for (i, str) in Self::SUITE.iter().enumerate() {
assert_eq!(
str,
&Self::normalize(str),
"suite fail at {i}: set {str} is not normalized"
);
}
}
fn _empty() {
Self::empty().roundtrip("{}");
}
fn _singleton() {
for (_, str, set) in Self::suite() {
set.singleton().roundtrip(&format!("{{{str}}}"));
}
}
fn _pair() {
for (i, str_1, set_1) in Self::suite() {
for (_, str_2, set_2) in Self::suite().skip(i + 1) {
set_1
.clone()
.pair(set_2.clone())
.roundtrip(&format!("{{{str_1}, {str_2}}}"));
}
}
}
fn _eq() {
for (i, _, set_1) in Self::suite() {
for (j, _, set_2) in Self::suite() {
assert_beq!(
i == j,
set_1 == set_2,
"set equality fail at {i}, {j}: {set_1}{}equal to {set_2}"
);
assert_beq!(
i == j,
set_1.partial_cmp(&set_2) == Some(Ordering::Equal),
"set equality fail at {i}, {j}: {set_1}{}equal to {set_2}"
);
}
}
}
fn _subset() {
for (i, _, set_1) in Self::suite() {
for (j, _, set_2) in Self::suite() {
let subset = set_1.iter().all(|s| set_1.count(s) <= set_2.count(s));
assert_beq!(
subset,
set_1 <= set_2,
"set equality fail at {i}, {j}: {set_1}{}a subset of {set_2}"
);
assert_beq!(
subset,
set_1.partial_cmp(&set_2).is_some_and(Ordering::is_le),
"set equality fail at {i}, {j}: {set_1}{}a subset of {set_2}"
);
}
}
}
fn _contains() {
for (i, _, set_1) in Self::suite() {
for (j, _, set_2) in Self::suite() {
let exp = Self::MEM.contains(&(i, j));
assert_beq!(
exp,
set_2.contains(&set_1),
"set membership fail at {i}, {j}: {set_1}{}a member of {set_2}"
);
}
}
}
fn _nat() {
let mut outputs = Vec::<String>::new();
for n in 0..5 {
let mut str = String::from('{');
let mut iter = outputs.iter();
if let Some(fst) = iter.next() {
str.push_str(fst);
}
for set in iter {
str.push_str(", ");
str.push_str(set);
}
str.push('}');
Self::nat(n).roundtrip(&str);
outputs.push(str);
}
}
fn _sum();
fn _union() {
for (i, _, set_1) in Self::suite() {
for (j, _, set_2) in Self::suite() {
let union = set_1.clone().union(set_2.clone());
for set in [&set_1, &set_2] {
assert!(
set.subset(&union),
"union fail at {i}, {j}: {set} not a subset of {union}"
);
}
}
}
}
fn _inter() {
for (i, _, set_1) in Self::suite() {
for (j, _, set_2) in Self::suite() {
let inter = set_1.clone().inter(set_2.clone());
for set in [&set_1, &set_2] {
assert!(
inter.subset(set),
"intersection fail at {i}, {j}: {inter} not a subset of {set}"
);
}
}
}
}
fn _powerset() {
for (i, _, set) in Self::suite() {
for subset in Self::powerset(set.clone()) {
assert!(
subset.subset(&set),
"powerset fail at {i}: {subset} not a subset of {set}"
);
}
}
}
fn _choose() {
for (i, _, set) in Self::suite() {
if !set.is_empty() {
let choose_1 = set.choose().expect("could not choose set");
assert!(
set.contains(choose_1),
"choice fail at {i}: {choose_1} not an element of {set}"
);
let choose_2 = set.choose_uniq().expect("could not choose set");
assert!(
set.contains(choose_2),
"unique choice fail at {i}: {choose_2} not an element of {set}"
);
}
}
}
fn _disjoint() {
for (i, _, set_1) in Self::suite() {
for (j, _, set_2) in Self::suite() {
assert_beq!(
set_1.clone().inter(set_2.clone()).is_empty(),
set_1.disjoint(&set_2),
"disjoint fail at {i}, {j}: {set_1} is{}disjoint with {set_2}"
);
}
}
}
fn _disjoint_set() {
for (i, _, set) in Self::suite() {
let expect = set
.clone()
.big_inter()
.map(|set| set.is_empty())
.unwrap_or_default();
assert_beq!(
expect,
set.disjoint_set(),
"disjoint fail at {i}: {set} is{}disjoint"
);
}
}
fn _disjoint_pairwise_set() {
for (i, _, set) in Self::suite() {
let expect =
set.iter().map(|c| c.card()).sum::<usize>() == set.clone().big_union().card();
assert_beq!(
expect,
set.disjoint_pairwise_set(),
"disjoint fail at {i}: {set} is{}pairwise disjoint"
);
}
}
}
impl Suite for Mset {
const SUITE: &'static [&'static str] = &[
"{}",
"{{}}",
"{{}, {}}",
"{{}, {{}}}",
"{{}, {{}}, {{}, {{}}}}",
"{{{}, {}}, {{}, {}}}",
"{{{{{}}}}}",
];
#[rustfmt::skip]
const MEM: &'static [(usize, usize)] = &[
(0, 1), (0, 2), (0, 3), (0, 4), (1, 3), (1, 4), (2, 5), (3, 4)
];
fn _sum() {
let suite: Vec<_> = Self::suite()
.map(|(_, str, set)| (&str[1..(str.len() - 1)], set))
.collect();
for (str_1, set_1) in suite.iter() {
for (str_2, set_2) in suite.iter() {
set_1
.clone()
.sum(set_2.clone())
.roundtrip(&Self::normalize(&format!("{{{str_1}, {str_2}}}")));
}
}
}
}
impl Suite for Set {
const SUITE: &'static [&'static str] = &[
"{}",
"{{}}",
"{{}, {{}}}",
"{{}, {{}}, {{}, {{}}}}",
"{{}, {{}}, {{{}}}}",
"{{{}, {{}}}, {{}, {{{}}}}}",
"{{{{{}}}}}",
];
#[rustfmt::skip]
const MEM: &'static [(usize, usize)] = &[
(0, 1), (0, 2), (0, 3), (0, 4), (1, 2), (1, 3), (1, 4), (2, 3), (2, 5)
];
fn _sum() {
Self::_union();
}
}
#[rustfmt::skip]
test!(
_suite, _empty, _singleton, _pair, _eq, _subset, _contains, _nat, _sum, _union, _inter,
_powerset, _choose, _disjoint, _disjoint_set, _disjoint_pairwise_set
);
#[test]
fn mset_is_set() {
const IS_SET: &[bool] = &[true, true, false, true, true, false, true];
for (i, _, set) in Mset::suite() {
assert_beq!(
IS_SET[i],
set.is_set(),
"is_set fail at {i}: multiset is{}a set"
);
}
}
#[test]
fn set_is_set() {
for (i, _, set) in Set::suite() {
assert!(
set.mset().is_set(),
"is_set fail at {i}: multiset is not a set"
);
}
}
#[test]
fn mset_flatten() {
const FLATTEN: &'static [&'static str] = &[
"{}",
"{{}}",
"{{}}",
"{{}, {{}}}",
"{{}, {{}}, {{}, {{}}}}",
"{{{}}}",
"{{{{{}}}}}",
];
for (i, _, set) in Mset::suite() {
set.flatten().roundtrip(FLATTEN[i])
}
}
#[test]
fn set_kpair() {
for (i, _, set_1) in Set::suite() {
for (j, _, set_2) in Set::suite() {
let pair = Set::kpair(set_1.clone(), set_2.clone());
assert_eq!(
pair.ksplit().expect("could not split pair").pair(),
(&set_1, &set_2),
"kpair fail at {i}, {j}: pair not split correctly"
);
assert_eq!(
pair.into_ksplit()
.expect("could not split pair")
.into_pair(),
(set_1.clone(), set_2),
"kpair fail at {i}, {j}: pair not split correctly"
);
}
}
}