]> git.lizzy.rs Git - enumset.git/blob - enumset/tests/ops.rs
b5fd0e55378a4e6eea9684382302eb10ba72afd0
[enumset.git] / enumset / tests / ops.rs
1 #![allow(dead_code)]
2
3 use enumset::*;
4 use std::collections::{HashSet, BTreeSet};
5
6 #[derive(EnumSetType, Debug)]
7 pub enum EmptyEnum { }
8
9 #[derive(EnumSetType, Debug)]
10 pub enum Enum1 {
11     A,
12 }
13
14 #[derive(EnumSetType, Debug)]
15 pub enum SmallEnum {
16     A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z,
17 }
18 #[derive(EnumSetType, Debug)]
19 pub enum LargeEnum {
20     _00,  _01,  _02,  _03,  _04,  _05,  _06,  _07,
21     _10,  _11,  _12,  _13,  _14,  _15,  _16,  _17,
22     _20,  _21,  _22,  _23,  _24,  _25,  _26,  _27,
23     _30,  _31,  _32,  _33,  _34,  _35,  _36,  _37,
24     _40,  _41,  _42,  _43,  _44,  _45,  _46,  _47,
25     _50,  _51,  _52,  _53,  _54,  _55,  _56,  _57,
26     _60,  _61,  _62,  _63,  _64,  _65,  _66,  _67,
27     _70,  _71,  _72,  _73,  _74,  _75,  _76,  _77,
28     A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z,
29 }
30 #[derive(EnumSetType, Debug)]
31 pub enum Enum8 {
32     A, B, C, D, E, F, G, H,
33 }
34 #[derive(EnumSetType, Debug)]
35 pub enum Enum128 {
36     A, B, C, D, E, F, G, H, _8, _9, _10, _11, _12, _13, _14, _15,
37     _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31,
38     _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47,
39     _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63,
40     _64, _65, _66, _67, _68, _69, _70, _71, _72, _73, _74, _75, _76, _77, _78, _79,
41     _80, _81, _82, _83, _84, _85, _86, _87, _88, _89, _90, _91, _92, _93, _94, _95,
42     _96, _97, _98, _99, _100, _101, _102, _103, _104, _105, _106, _107, _108, _109,
43     _110, _111, _112, _113, _114, _115, _116, _117, _118, _119, _120, _121, _122,
44     _123, _124,  _125, _126, _127,
45 }
46 #[derive(EnumSetType, Debug)]
47 pub enum SparseEnum {
48     A = 0xA, B = 20, C = 30, D = 40, E = 50, F = 60, G = 70, H = 80,
49 }
50
51 #[repr(u32)]
52 #[derive(EnumSetType, Debug)]
53 pub enum ReprEnum {
54     A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z,
55 }
56
57 macro_rules! test_variants {
58     ($enum_name:ident $all_empty_test:ident $($variant:ident,)*) => {
59         #[test]
60         fn $all_empty_test() {
61             let all = EnumSet::<$enum_name>::all();
62             let empty = EnumSet::<$enum_name>::empty();
63
64             $(
65                 assert!(!empty.contains($enum_name::$variant));
66                 assert!(all.contains($enum_name::$variant));
67             )*
68         }
69     }
70 }
71 test_variants! { SmallEnum small_enum_all_empty
72     A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z,
73 }
74 test_variants! { LargeEnum large_enum_all_empty
75     _00,  _01,  _02,  _03,  _04,  _05,  _06,  _07,
76     _10,  _11,  _12,  _13,  _14,  _15,  _16,  _17,
77     _20,  _21,  _22,  _23,  _24,  _25,  _26,  _27,
78     _30,  _31,  _32,  _33,  _34,  _35,  _36,  _37,
79     _40,  _41,  _42,  _43,  _44,  _45,  _46,  _47,
80     _50,  _51,  _52,  _53,  _54,  _55,  _56,  _57,
81     _60,  _61,  _62,  _63,  _64,  _65,  _66,  _67,
82     _70,  _71,  _72,  _73,  _74,  _75,  _76,  _77,
83     A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z,
84 }
85 test_variants! { SparseEnum sparse_enum_all_empty
86     A, B, C, D, E, F, G,
87 }
88
89 macro_rules! test_enum {
90     ($e:ident, $mem_size:expr) => {
91         const CONST_SET: EnumSet<$e> = enum_set!($e::A | $e::C);
92         const EMPTY_SET: EnumSet<$e> = enum_set!();
93         #[test]
94         fn const_set() {
95             assert_eq!(CONST_SET.len(), 2);
96             assert!(CONST_SET.contains($e::A));
97             assert!(CONST_SET.contains($e::C));
98             assert!(EMPTY_SET.is_empty());
99         }
100
101         #[test]
102         fn basic_add_remove() {
103             let mut set = EnumSet::new();
104             set.insert($e::A);
105             set.insert($e::B);
106             set.insert($e::C);
107             assert_eq!(set, $e::A | $e::B | $e::C);
108             set.remove($e::B);
109             assert_eq!(set, $e::A | $e::C);
110             set.insert($e::D);
111             assert_eq!(set, $e::A | $e::C | $e::D);
112             set.insert_all($e::F | $e::E | $e::G);
113             assert_eq!(set, $e::A | $e::C | $e::D | $e::F | $e::E | $e::G);
114             set.remove_all($e::A | $e::D | $e::G);
115             assert_eq!(set, $e::C | $e::F | $e::E);
116             assert!(!set.is_empty());
117             set.clear();
118             assert!(set.is_empty());
119         }
120
121         #[test]
122         fn already_present_element() {
123             let mut set = EnumSet::new();
124             assert!(set.insert($e::A));
125             assert!(!set.insert($e::A));
126             set.remove($e::A);
127             assert!(set.insert($e::A));
128         }
129
130         #[test]
131         fn empty_is_empty() {
132             assert_eq!(EnumSet::<$e>::empty().len(), 0)
133         }
134
135         #[test]
136         fn all_len() {
137             assert_eq!(EnumSet::<$e>::all().len(), EnumSet::<$e>::variant_count() as usize)
138         }
139
140         #[test]
141         fn basic_iter_test() {
142             let mut set = EnumSet::new();
143             set.insert($e::A);
144             set.insert($e::B);
145             set.insert($e::C);
146             set.insert($e::E);
147
148             let mut set_2 = EnumSet::new();
149             let vec: Vec<$e> = set.iter().collect();
150             for val in vec {
151                 assert!(!set_2.contains(val));
152                 set_2.insert(val);
153             }
154             assert_eq!(set, set_2);
155
156             let mut set_3 = EnumSet::new();
157             for val in set {
158                 assert!(!set_3.contains(val));
159                 set_3.insert(val);
160             }
161             assert_eq!(set, set_3);
162         }
163
164         fn check_iter_size_hint(set: EnumSet<$e>) {
165             let count = set.len();
166             let mut itr = set.iter();
167             for idx in 0 .. count {
168                 assert_eq!(itr.size_hint(), (count-idx, Some(count-idx)));
169                 assert!(itr.next().is_some());
170             }
171             assert_eq!(itr.size_hint(), (0, Some(0)));
172         }
173         #[test]
174         fn test_iter_size_hint() {
175             check_iter_size_hint(EnumSet::<$e>::all());
176             let mut set = EnumSet::new();
177             set.insert($e::A);
178             set.insert($e::C);
179             set.insert($e::E);
180             check_iter_size_hint(set);
181         }
182
183         #[test]
184         fn iter_ops_test() {
185             let set = $e::A | $e::B | $e::C | $e::E;
186             let set2 = set.iter().filter(|&v| v != $e::B).collect::<EnumSet<_>>();
187             assert_eq!(set2, $e::A | $e::C | $e::E);
188         }
189
190         #[test]
191         fn basic_ops_test() {
192             assert_eq!(($e::A | $e::B) | ($e::B | $e::C), $e::A | $e::B | $e::C);
193             assert_eq!(($e::A | $e::B) & ($e::B | $e::C), $e::B);
194             assert_eq!(($e::A | $e::B) ^ ($e::B | $e::C), $e::A | $e::C);
195             assert_eq!(($e::A | $e::B) - ($e::B | $e::C), $e::A);
196             assert_eq!($e::A | !$e::A, EnumSet::<$e>::all());
197         }
198
199         #[test]
200         fn mutable_ops_test() {
201             let mut set = $e::A | $e::B;
202             assert_eq!(set, $e::A | $e::B);
203             set |= $e::C | $e::D;
204             assert_eq!(set, $e::A | $e::B | $e::C | $e::D);
205             set -= $e::C;
206             assert_eq!(set, $e::A | $e::B | $e::D);
207             set ^= $e::B | $e::E;
208             assert_eq!(set, $e::A | $e::D | $e::E);
209             set &= $e::A | $e::E | $e::F;
210             assert_eq!(set, $e::A | $e::E);
211         }
212
213         #[test]
214         fn basic_set_status() {
215             assert!(($e::A | $e::B | $e::C).is_disjoint($e::D | $e::E | $e::F));
216             assert!(!($e::A | $e::B | $e::C | $e::D).is_disjoint($e::D | $e::E | $e::F));
217             assert!(($e::A | $e::B).is_subset($e::A | $e::B | $e::C));
218             assert!(!($e::A | $e::D).is_subset($e::A | $e::B | $e::C));
219         }
220
221         #[test]
222         fn debug_impl() {
223             assert_eq!(format!("{:?}", $e::A | $e::B | $e::D), "EnumSet(A | B | D)");
224         }
225
226         #[test]
227         fn to_from_bits() {
228             let value = $e::A | $e::C | $e::D | $e::F | $e::E | $e::G;
229             assert_eq!(EnumSet::from_u128(value.to_u128()), value);
230         }
231
232         #[test]
233         #[should_panic]
234         fn too_many_bits() {
235             if EnumSet::<$e>::variant_count() == 128 {
236                 panic!("(test skipped)")
237             }
238             EnumSet::<$e>::from_u128(!0);
239         }
240
241         #[test]
242         fn match_const_test() {
243             match CONST_SET {
244                 CONST_SET => { /* ok */ }
245                 _ => panic!("match fell through?"),
246             }
247         }
248
249         #[test]
250         fn set_test() {
251             const SET_TEST_A: EnumSet<$e> = enum_set!($e::A | $e::B | $e::C);
252             const SET_TEST_B: EnumSet<$e> = enum_set!($e::A | $e::B | $e::D);
253             const SET_TEST_C: EnumSet<$e> = enum_set!($e::A | $e::B | $e::E);
254             const SET_TEST_D: EnumSet<$e> = enum_set!($e::A | $e::B | $e::F);
255             const SET_TEST_E: EnumSet<$e> = enum_set!($e::A | $e::B | $e::G);
256             macro_rules! test_set {
257                 ($set:ident) => {{
258                     assert!(!$set.contains(&SET_TEST_A));
259                     assert!(!$set.contains(&SET_TEST_B));
260                     assert!(!$set.contains(&SET_TEST_C));
261                     assert!(!$set.contains(&SET_TEST_D));
262                     assert!(!$set.contains(&SET_TEST_E));
263                     $set.insert(SET_TEST_A);
264                     $set.insert(SET_TEST_C);
265                     assert!($set.contains(&SET_TEST_A));
266                     assert!(!$set.contains(&SET_TEST_B));
267                     assert!($set.contains(&SET_TEST_C));
268                     assert!(!$set.contains(&SET_TEST_D));
269                     assert!(!$set.contains(&SET_TEST_E));
270                     $set.remove(&SET_TEST_C);
271                     $set.remove(&SET_TEST_D);
272                     assert!($set.contains(&SET_TEST_A));
273                     assert!(!$set.contains(&SET_TEST_B));
274                     assert!(!$set.contains(&SET_TEST_C));
275                     assert!(!$set.contains(&SET_TEST_D));
276                     assert!(!$set.contains(&SET_TEST_E));
277                     $set.insert(SET_TEST_A);
278                     $set.insert(SET_TEST_D);
279                     assert!($set.contains(&SET_TEST_A));
280                     assert!(!$set.contains(&SET_TEST_B));
281                     assert!(!$set.contains(&SET_TEST_C));
282                     assert!($set.contains(&SET_TEST_D));
283                     assert!(!$set.contains(&SET_TEST_E));
284                 }}
285             }
286             
287             let mut hash_set = HashSet::new();
288             test_set!(hash_set);
289             
290             let mut tree_set = BTreeSet::new();
291             test_set!(tree_set);
292         }
293
294         #[test]
295         fn check_size() {
296             assert_eq!(::std::mem::size_of::<EnumSet<$e>>(), $mem_size);
297         }
298     }
299 }
300 macro_rules! tests {
301     ($m:ident, $($tt:tt)*) => { mod $m { use super::*; $($tt)*; } }
302 }
303
304 tests!(small_enum, test_enum!(SmallEnum, 4));
305 tests!(large_enum, test_enum!(LargeEnum, 16));
306 tests!(enum8, test_enum!(Enum8, 1));
307 tests!(enum128, test_enum!(Enum128, 16));
308 tests!(sparse_enum, test_enum!(SparseEnum, 16));
309 tests!(repr_enum, test_enum!(ReprEnum, 4));
310
311 #[derive(EnumSetType, Debug)]
312 pub enum ThresholdEnum {
313     A = 1, B, C, D,
314     U8 = 0, U16 = 8, U32 = 16, U64 = 32, U128 = 64,
315 }
316 macro_rules! bits_tests {
317     (
318         $mod_name:ident, $threshold_expr:expr, ($($too_big_expr:expr),*), $ty:ty,
319         $to:ident $try_to:ident $to_truncated:ident
320         $from:ident $try_from:ident $from_truncated:ident
321     ) => {
322         mod $mod_name {
323             use super::*;
324             use crate::ThresholdEnum::*;
325
326             #[test]
327             fn to_from_basic() {
328                 for &mask in &[
329                     $threshold_expr | B | C | D,
330                     $threshold_expr | A | D,
331                     $threshold_expr | B | C,
332                 ] {
333                     assert_eq!(mask, EnumSet::<ThresholdEnum>::$from(mask.$to()));
334                     assert_eq!(mask.$to_truncated(), mask.$to());
335                     assert_eq!(Some(mask.$to()), mask.$try_to())
336                 }
337             }
338
339             #[test]
340             #[should_panic]
341             fn from_invalid() {
342                 let invalid_mask: $ty = 0x80;
343                 EnumSet::<ThresholdEnum>::$from(invalid_mask);
344             }
345
346             #[test]
347             fn try_from_invalid() {
348                 assert!(EnumSet::<ThresholdEnum>::$try_from(0xFF).is_none());
349             }
350
351             $(
352                 #[test]
353                 fn try_to_overflow() {
354                         let set: EnumSet<ThresholdEnum> = $too_big_expr.into();
355                         assert!(set.$try_to().is_none());
356                 }
357             )*
358
359             #[test]
360             fn truncated_overflow() {
361                 let trunc_invalid = EnumSet::<ThresholdEnum>::$from_truncated(0xFE);
362                 assert_eq!(A | B | C | D, trunc_invalid);
363                 $(
364                     let set: EnumSet<ThresholdEnum> = $too_big_expr | A;
365                     assert_eq!(2, set.$to_truncated());
366                 )*
367             }
368         }
369     }
370 }
371
372 bits_tests!(test_u8_bits, U8, (U16), u8,
373             to_u8 to_u8_checked to_u8_truncated from_u8 try_from_u8 from_u8_truncated);
374 bits_tests!(test_u16_bits, U16, (U32), u16,
375             to_u16 to_u16_checked to_u16_truncated from_u16 try_from_u16 from_u16_truncated);
376 bits_tests!(test_u32_bits, U32, (U64), u32,
377             to_u32 to_u32_checked to_u32_truncated from_u32 try_from_u32 from_u32_truncated);
378 bits_tests!(test_u64_bits, U64, (U128), u64,
379             to_u64 to_u64_checked to_u64_truncated from_u64 try_from_u64 from_u64_truncated);
380 bits_tests!(test_u128_bits, U128, (), u128,
381             to_u128 to_u128_checked to_u128_truncated from_u128 try_from_u128 from_u128_truncated);