aboutsummaryrefslogtreecommitdiff
path: root/src/tests/iter.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/tests/iter.rs')
-rw-r--r--src/tests/iter.rs209
1 files changed, 209 insertions, 0 deletions
diff --git a/src/tests/iter.rs b/src/tests/iter.rs
new file mode 100644
index 0000000..54b1d27
--- /dev/null
+++ b/src/tests/iter.rs
@@ -0,0 +1,209 @@
+use super::*;
+
+use crate::Flags;
+
+#[test]
+#[cfg(not(miri))] // Very slow in miri
+fn roundtrip() {
+ for a in 0u8..=255 {
+ for b in 0u8..=255 {
+ let f = TestFlags::from_bits_retain(a | b);
+
+ assert_eq!(f, f.iter().collect::<TestFlags>());
+ assert_eq!(
+ TestFlags::from_bits_truncate(f.bits()),
+ f.iter_names().map(|(_, f)| f).collect::<TestFlags>()
+ );
+
+ let f = TestExternal::from_bits_retain(a | b);
+
+ assert_eq!(f, f.iter().collect::<TestExternal>());
+ }
+ }
+}
+
+mod collect {
+ use super::*;
+
+ #[test]
+ fn cases() {
+ assert_eq!(0, [].into_iter().collect::<TestFlags>().bits());
+
+ assert_eq!(1, [TestFlags::A,].into_iter().collect::<TestFlags>().bits());
+
+ assert_eq!(
+ 1 | 1 << 1 | 1 << 2,
+ [TestFlags::A, TestFlags::B | TestFlags::C,]
+ .into_iter()
+ .collect::<TestFlags>()
+ .bits()
+ );
+
+ assert_eq!(
+ 1 | 1 << 3,
+ [
+ TestFlags::from_bits_retain(1 << 3),
+ TestFlags::empty(),
+ TestFlags::A,
+ ]
+ .into_iter()
+ .collect::<TestFlags>()
+ .bits()
+ );
+
+ assert_eq!(
+ 1 << 5 | 1 << 7,
+ [
+ TestExternal::empty(),
+ TestExternal::from_bits_retain(1 << 5),
+ TestExternal::from_bits_retain(1 << 7),
+ ]
+ .into_iter()
+ .collect::<TestExternal>()
+ .bits()
+ );
+ }
+}
+
+mod iter {
+ use super::*;
+
+ #[test]
+ fn cases() {
+ case(&[], TestFlags::empty(), TestFlags::iter);
+
+ case(&[1], TestFlags::A, TestFlags::iter);
+ case(&[1, 1 << 1], TestFlags::A | TestFlags::B, TestFlags::iter);
+ case(
+ &[1, 1 << 1, 1 << 3],
+ TestFlags::A | TestFlags::B | TestFlags::from_bits_retain(1 << 3),
+ TestFlags::iter,
+ );
+
+ case(&[1, 1 << 1, 1 << 2], TestFlags::ABC, TestFlags::iter);
+ case(
+ &[1, 1 << 1, 1 << 2, 1 << 3],
+ TestFlags::ABC | TestFlags::from_bits_retain(1 << 3),
+ TestFlags::iter,
+ );
+
+ case(
+ &[1 | 1 << 1 | 1 << 2],
+ TestFlagsInvert::ABC,
+ TestFlagsInvert::iter,
+ );
+
+ case(&[], TestZero::ZERO, TestZero::iter);
+
+ case(
+ &[1, 1 << 1, 1 << 2, 0b1111_1000],
+ TestExternal::all(),
+ TestExternal::iter,
+ );
+ }
+
+ #[track_caller]
+ fn case<T: Flags + std::fmt::Debug + IntoIterator<Item = T> + Copy>(
+ expected: &[T::Bits],
+ value: T,
+ inherent: impl FnOnce(&T) -> crate::iter::Iter<T>,
+ ) where
+ T::Bits: std::fmt::Debug + PartialEq,
+ {
+ assert_eq!(
+ expected,
+ inherent(&value).map(|f| f.bits()).collect::<Vec<_>>(),
+ "{:?}.iter()",
+ value
+ );
+ assert_eq!(
+ expected,
+ Flags::iter(&value).map(|f| f.bits()).collect::<Vec<_>>(),
+ "Flags::iter({:?})",
+ value
+ );
+ assert_eq!(
+ expected,
+ value.into_iter().map(|f| f.bits()).collect::<Vec<_>>(),
+ "{:?}.into_iter()",
+ value
+ );
+ }
+}
+
+mod iter_names {
+ use super::*;
+
+ #[test]
+ fn cases() {
+ case(&[], TestFlags::empty(), TestFlags::iter_names);
+
+ case(&[("A", 1)], TestFlags::A, TestFlags::iter_names);
+ case(
+ &[("A", 1), ("B", 1 << 1)],
+ TestFlags::A | TestFlags::B,
+ TestFlags::iter_names,
+ );
+ case(
+ &[("A", 1), ("B", 1 << 1)],
+ TestFlags::A | TestFlags::B | TestFlags::from_bits_retain(1 << 3),
+ TestFlags::iter_names,
+ );
+
+ case(
+ &[("A", 1), ("B", 1 << 1), ("C", 1 << 2)],
+ TestFlags::ABC,
+ TestFlags::iter_names,
+ );
+ case(
+ &[("A", 1), ("B", 1 << 1), ("C", 1 << 2)],
+ TestFlags::ABC | TestFlags::from_bits_retain(1 << 3),
+ TestFlags::iter_names,
+ );
+
+ case(
+ &[("ABC", 1 | 1 << 1 | 1 << 2)],
+ TestFlagsInvert::ABC,
+ TestFlagsInvert::iter_names,
+ );
+
+ case(&[], TestZero::ZERO, TestZero::iter_names);
+
+ case(
+ &[("A", 1)],
+ TestOverlappingFull::A,
+ TestOverlappingFull::iter_names,
+ );
+ case(
+ &[("A", 1), ("D", 1 << 1)],
+ TestOverlappingFull::A | TestOverlappingFull::D,
+ TestOverlappingFull::iter_names,
+ );
+ }
+
+ #[track_caller]
+ fn case<T: Flags + std::fmt::Debug>(
+ expected: &[(&'static str, T::Bits)],
+ value: T,
+ inherent: impl FnOnce(&T) -> crate::iter::IterNames<T>,
+ ) where
+ T::Bits: std::fmt::Debug + PartialEq,
+ {
+ assert_eq!(
+ expected,
+ inherent(&value)
+ .map(|(n, f)| (n, f.bits()))
+ .collect::<Vec<_>>(),
+ "{:?}.iter_names()",
+ value
+ );
+ assert_eq!(
+ expected,
+ Flags::iter_names(&value)
+ .map(|(n, f)| (n, f.bits()))
+ .collect::<Vec<_>>(),
+ "Flags::iter_names({:?})",
+ value
+ );
+ }
+}