]> git.lizzy.rs Git - enumset.git/blob - enumset/tests/ops.rs
Add `no_super_impls` option to `EnumSetType` derive.
[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(Clone, Copy, Debug, EnumSetType, Eq, PartialEq)]
19 #[enumset(no_super_impls)]
20 pub enum SmallEnumExplicitDerive {
21     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,
22 }
23 #[derive(EnumSetType, Debug)]
24 pub enum LargeEnum {
25     _00,  _01,  _02,  _03,  _04,  _05,  _06,  _07,
26     _10,  _11,  _12,  _13,  _14,  _15,  _16,  _17,
27     _20,  _21,  _22,  _23,  _24,  _25,  _26,  _27,
28     _30,  _31,  _32,  _33,  _34,  _35,  _36,  _37,
29     _40,  _41,  _42,  _43,  _44,  _45,  _46,  _47,
30     _50,  _51,  _52,  _53,  _54,  _55,  _56,  _57,
31     _60,  _61,  _62,  _63,  _64,  _65,  _66,  _67,
32     _70,  _71,  _72,  _73,  _74,  _75,  _76,  _77,
33     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,
34 }
35 #[derive(EnumSetType, Debug)]
36 pub enum Enum8 {
37     A, B, C, D, E, F, G, H,
38 }
39 #[derive(EnumSetType, Debug)]
40 pub enum Enum128 {
41     A, B, C, D, E, F, G, H, _8, _9, _10, _11, _12, _13, _14, _15,
42     _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31,
43     _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47,
44     _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63,
45     _64, _65, _66, _67, _68, _69, _70, _71, _72, _73, _74, _75, _76, _77, _78, _79,
46     _80, _81, _82, _83, _84, _85, _86, _87, _88, _89, _90, _91, _92, _93, _94, _95,
47     _96, _97, _98, _99, _100, _101, _102, _103, _104, _105, _106, _107, _108, _109,
48     _110, _111, _112, _113, _114, _115, _116, _117, _118, _119, _120, _121, _122,
49     _123, _124,  _125, _126, _127,
50 }
51 #[derive(EnumSetType, Debug)]
52 pub enum SparseEnum {
53     A = 0xA, B = 20, C = 30, D = 40, E = 50, F = 60, G = 70, H = 80,
54 }
55
56 #[repr(u32)]
57 #[derive(EnumSetType, Debug)]
58 pub enum ReprEnum {
59     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,
60 }
61 #[repr(u64)]
62 #[derive(EnumSetType, Debug)]
63 pub enum ReprEnum2 {
64     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,
65 }
66 #[repr(isize)]
67 #[derive(EnumSetType, Debug)]
68 pub enum ReprEnum3 {
69     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,
70 }
71 #[repr(C)]
72 #[derive(EnumSetType, Debug)]
73 pub enum ReprEnum4 {
74     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,
75 }
76
77 macro_rules! test_variants {
78     ($enum_name:ident $all_empty_test:ident $($variant:ident,)*) => {
79         #[test]
80         fn $all_empty_test() {
81             let all = EnumSet::<$enum_name>::all();
82             let empty = EnumSet::<$enum_name>::empty();
83
84             $(
85                 assert!(!empty.contains($enum_name::$variant));
86                 assert!(all.contains($enum_name::$variant));
87             )*
88         }
89     }
90 }
91 test_variants! { SmallEnum small_enum_all_empty
92     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,
93 }
94 test_variants! { SmallEnumExplicitDerive small_enum_explicit_derive_all_empty
95     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,
96 }
97 test_variants! { LargeEnum large_enum_all_empty
98     _00,  _01,  _02,  _03,  _04,  _05,  _06,  _07,
99     _10,  _11,  _12,  _13,  _14,  _15,  _16,  _17,
100     _20,  _21,  _22,  _23,  _24,  _25,  _26,  _27,
101     _30,  _31,  _32,  _33,  _34,  _35,  _36,  _37,
102     _40,  _41,  _42,  _43,  _44,  _45,  _46,  _47,
103     _50,  _51,  _52,  _53,  _54,  _55,  _56,  _57,
104     _60,  _61,  _62,  _63,  _64,  _65,  _66,  _67,
105     _70,  _71,  _72,  _73,  _74,  _75,  _76,  _77,
106     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,
107 }
108 test_variants! { SparseEnum sparse_enum_all_empty
109     A, B, C, D, E, F, G,
110 }
111
112 macro_rules! test_enum {
113     ($e:ident, $mem_size:expr) => {
114         const CONST_SET: EnumSet<$e> = enum_set!($e::A | $e::C);
115         const CONST_1_SET: EnumSet<$e> = enum_set!($e::A);
116         const EMPTY_SET: EnumSet<$e> = enum_set!();
117         #[test]
118         fn const_set() {
119             assert_eq!(CONST_SET.len(), 2);
120             assert_eq!(CONST_1_SET.len(), 1);
121             assert!(CONST_SET.contains($e::A));
122             assert!(CONST_SET.contains($e::C));
123             assert!(EMPTY_SET.is_empty());
124         }
125
126         #[test]
127         fn basic_add_remove() {
128             let mut set = EnumSet::new();
129             set.insert($e::A);
130             set.insert($e::B);
131             set.insert($e::C);
132             assert_eq!(set, $e::A | $e::B | $e::C);
133             set.remove($e::B);
134             assert_eq!(set, $e::A | $e::C);
135             set.insert($e::D);
136             assert_eq!(set, $e::A | $e::C | $e::D);
137             set.insert_all($e::F | $e::E | $e::G);
138             assert_eq!(set, $e::A | $e::C | $e::D | $e::F | $e::E | $e::G);
139             set.remove_all($e::A | $e::D | $e::G);
140             assert_eq!(set, $e::C | $e::F | $e::E);
141             assert!(!set.is_empty());
142             set.clear();
143             assert!(set.is_empty());
144         }
145
146         #[test]
147         fn already_present_element() {
148             let mut set = EnumSet::new();
149             assert!(set.insert($e::A));
150             assert!(!set.insert($e::A));
151             set.remove($e::A);
152             assert!(set.insert($e::A));
153         }
154
155         #[test]
156         fn empty_is_empty() {
157             assert_eq!(EnumSet::<$e>::empty().len(), 0)
158         }
159
160         #[test]
161         fn all_len() {
162             assert_eq!(EnumSet::<$e>::all().len(), EnumSet::<$e>::variant_count() as usize)
163         }
164
165         #[test]
166         fn iter_test() {
167             let mut set = EnumSet::new();
168             set.insert($e::A);
169             set.insert($e::B);
170             set.extend($e::C | $e::E);
171
172             let mut set_2 = EnumSet::new();
173             let vec: Vec<_> = set.iter().collect();
174             for val in vec {
175                 assert!(!set_2.contains(val));
176                 set_2.insert(val);
177             }
178             assert_eq!(set, set_2);
179
180             let mut set_3 = EnumSet::new();
181             for val in set {
182                 assert!(!set_3.contains(val));
183                 set_3.insert(val);
184             }
185             assert_eq!(set, set_3);
186
187             let mut set_4 = EnumSet::new();
188             let vec: EnumSet<_> = set.into_iter().map(EnumSet::only).collect();
189             for val in vec {
190                 assert!(!set_4.contains(val));
191                 set_4.insert(val);
192             }
193             assert_eq!(set, set_4);
194
195             let mut set_5 = EnumSet::new();
196             let vec: EnumSet<_> = set.iter().collect();
197             for val in vec {
198                 assert!(!set_5.contains(val));
199                 set_5.insert(val);
200             }
201             assert_eq!(set, set_5);
202         }
203
204         fn check_iter_size_hint(set: EnumSet<$e>) {
205             let count = set.len();
206             let mut itr = set.iter();
207             for idx in 0 .. count {
208                 assert_eq!(itr.size_hint(), (count-idx, Some(count-idx)));
209                 assert_eq!(itr.len(), count-idx);
210                 assert!(itr.next().is_some());
211             }
212             assert_eq!(itr.size_hint(), (0, Some(0)));
213             assert_eq!(itr.len(), 0);
214         }
215         #[test]
216         fn test_iter_size_hint() {
217             check_iter_size_hint(EnumSet::<$e>::all());
218             let mut set = EnumSet::new();
219             set.insert($e::A);
220             set.insert($e::C);
221             set.insert($e::E);
222             check_iter_size_hint(set);
223         }
224
225         #[test]
226         fn iter_ops_test() {
227             let set = $e::A | $e::B | $e::C | $e::E;
228             let set2 = set.iter().filter(|&v| v != $e::B).collect::<EnumSet<_>>();
229             assert_eq!(set2, $e::A | $e::C | $e::E);
230         }
231
232         #[test]
233         fn basic_ops_test() {
234             assert_eq!(($e::A | $e::B) | ($e::B | $e::C), $e::A | $e::B | $e::C);
235             assert_eq!(($e::A | $e::B) & ($e::B | $e::C), $e::B);
236             assert_eq!(($e::A | $e::B) ^ ($e::B | $e::C), $e::A | $e::C);
237             assert_eq!(($e::A | $e::B) - ($e::B | $e::C), $e::A);
238             assert_eq!($e::A | !$e::A, EnumSet::<$e>::all());
239         }
240
241         #[test]
242         fn mutable_ops_test() {
243             let mut set = $e::A | $e::B;
244             assert_eq!(set, $e::A | $e::B);
245             set |= $e::C | $e::D;
246             assert_eq!(set, $e::A | $e::B | $e::C | $e::D);
247             set -= $e::C;
248             assert_eq!(set, $e::A | $e::B | $e::D);
249             set ^= $e::B | $e::E;
250             assert_eq!(set, $e::A | $e::D | $e::E);
251             set &= $e::A | $e::E | $e::F;
252             assert_eq!(set, $e::A | $e::E);
253         }
254
255         #[test]
256         fn basic_set_status() {
257             assert!(($e::A | $e::B | $e::C).is_disjoint($e::D | $e::E | $e::F));
258             assert!(!($e::A | $e::B | $e::C | $e::D).is_disjoint($e::D | $e::E | $e::F));
259             assert!(($e::A | $e::B).is_subset($e::A | $e::B | $e::C));
260             assert!(!($e::A | $e::D).is_subset($e::A | $e::B | $e::C));
261         }
262
263         #[test]
264         fn debug_impl() {
265             assert_eq!(format!("{:?}", $e::A | $e::B | $e::D), "EnumSet(A | B | D)");
266         }
267
268         #[test]
269         fn to_from_bits() {
270             let value = $e::A | $e::C | $e::D | $e::F | $e::E | $e::G;
271             assert_eq!(EnumSet::from_u128(value.as_u128()), value);
272         }
273
274         #[test]
275         #[should_panic]
276         fn too_many_bits() {
277             if EnumSet::<$e>::variant_count() == 128 {
278                 panic!("(test skipped)")
279             }
280             EnumSet::<$e>::from_u128(!0);
281         }
282
283         #[test]
284         fn match_const_test() {
285             match CONST_SET {
286                 CONST_SET => { /* ok */ }
287                 _ => panic!("match fell through?"),
288             }
289         }
290
291         #[test]
292         fn set_test() {
293             const SET_TEST_A: EnumSet<$e> = enum_set!($e::A | $e::B | $e::C);
294             const SET_TEST_B: EnumSet<$e> = enum_set!($e::A | $e::B | $e::D);
295             const SET_TEST_C: EnumSet<$e> = enum_set!($e::A | $e::B | $e::E);
296             const SET_TEST_D: EnumSet<$e> = enum_set!($e::A | $e::B | $e::F);
297             const SET_TEST_E: EnumSet<$e> = enum_set!($e::A | $e::B | $e::G);
298             macro_rules! test_set {
299                 ($set:ident) => {{
300                     assert!(!$set.contains(&SET_TEST_A));
301                     assert!(!$set.contains(&SET_TEST_B));
302                     assert!(!$set.contains(&SET_TEST_C));
303                     assert!(!$set.contains(&SET_TEST_D));
304                     assert!(!$set.contains(&SET_TEST_E));
305                     $set.insert(SET_TEST_A);
306                     $set.insert(SET_TEST_C);
307                     assert!($set.contains(&SET_TEST_A));
308                     assert!(!$set.contains(&SET_TEST_B));
309                     assert!($set.contains(&SET_TEST_C));
310                     assert!(!$set.contains(&SET_TEST_D));
311                     assert!(!$set.contains(&SET_TEST_E));
312                     $set.remove(&SET_TEST_C);
313                     $set.remove(&SET_TEST_D);
314                     assert!($set.contains(&SET_TEST_A));
315                     assert!(!$set.contains(&SET_TEST_B));
316                     assert!(!$set.contains(&SET_TEST_C));
317                     assert!(!$set.contains(&SET_TEST_D));
318                     assert!(!$set.contains(&SET_TEST_E));
319                     $set.insert(SET_TEST_A);
320                     $set.insert(SET_TEST_D);
321                     assert!($set.contains(&SET_TEST_A));
322                     assert!(!$set.contains(&SET_TEST_B));
323                     assert!(!$set.contains(&SET_TEST_C));
324                     assert!($set.contains(&SET_TEST_D));
325                     assert!(!$set.contains(&SET_TEST_E));
326                 }}
327             }
328
329             let mut hash_set = HashSet::new();
330             test_set!(hash_set);
331
332             let mut tree_set = BTreeSet::new();
333             test_set!(tree_set);
334         }
335
336         #[test]
337         fn sum_test() {
338             let target = $e::A | $e::B | $e::D | $e::E | $e::G | $e::H;
339
340             let list_a = [$e::A | $e::B, $e::D | $e::E, $e::G | $e::H];
341             let sum_a: EnumSet<$e> = list_a.iter().map(|x| *x).sum();
342             assert_eq!(target, sum_a);
343             let sum_b: EnumSet<$e> = list_a.iter().sum();
344             assert_eq!(target, sum_b);
345
346             let list_b = [$e::A, $e::B, $e::D, $e::E, $e::G, $e::H];
347             let sum_c: EnumSet<$e> = list_b.iter().map(|x| *x).sum();
348             assert_eq!(target, sum_c);
349             let sum_d: EnumSet<$e> = list_b.iter().sum();
350             assert_eq!(target, sum_d);
351         }
352
353         #[test]
354         fn check_size() {
355             assert_eq!(::std::mem::size_of::<EnumSet<$e>>(), $mem_size);
356         }
357     }
358 }
359 macro_rules! tests {
360     ($m:ident, $($tt:tt)*) => { mod $m { use super::*; $($tt)*; } }
361 }
362
363 tests!(small_enum, test_enum!(SmallEnum, 4));
364 tests!(small_enum_explicit_derive, test_enum!(SmallEnumExplicitDerive, 4));
365 tests!(large_enum, test_enum!(LargeEnum, 16));
366 tests!(enum8, test_enum!(Enum8, 1));
367 tests!(enum128, test_enum!(Enum128, 16));
368 tests!(sparse_enum, test_enum!(SparseEnum, 16));
369 tests!(repr_enum_u32, test_enum!(ReprEnum, 4));
370 tests!(repr_enum_u64, test_enum!(ReprEnum2, 4));
371 tests!(repr_enum_isize, test_enum!(ReprEnum3, 4));
372 tests!(repr_enum_c, test_enum!(ReprEnum4, 4));
373
374 #[derive(EnumSetType, Debug)]
375 pub enum ThresholdEnum {
376     A = 1, B, C, D,
377     U8 = 0, U16 = 8, U32 = 16, U64 = 32, U128 = 64,
378 }
379 macro_rules! bits_tests {
380     (
381         $mod_name:ident, $threshold_expr:expr, ($($too_big_expr:expr),*), $ty:ty,
382         $to:ident $try_to:ident $to_truncated:ident
383         $from:ident $try_from:ident $from_truncated:ident
384     ) => {
385         mod $mod_name {
386             use super::*;
387             use crate::ThresholdEnum::*;
388
389             #[test]
390             fn to_from_basic() {
391                 for &mask in &[
392                     $threshold_expr | B | C | D,
393                     $threshold_expr | A | D,
394                     $threshold_expr | B | C,
395                 ] {
396                     assert_eq!(mask, EnumSet::<ThresholdEnum>::$from(mask.$to()));
397                     assert_eq!(mask.$to_truncated(), mask.$to());
398                     assert_eq!(Some(mask.$to()), mask.$try_to())
399                 }
400             }
401
402             #[test]
403             #[should_panic]
404             fn from_invalid() {
405                 let invalid_mask: $ty = 0x80;
406                 EnumSet::<ThresholdEnum>::$from(invalid_mask);
407             }
408
409             #[test]
410             fn try_from_invalid() {
411                 assert!(EnumSet::<ThresholdEnum>::$try_from(0xFF).is_none());
412             }
413
414             $(
415                 #[test]
416                 fn try_to_overflow() {
417                         let set: EnumSet<ThresholdEnum> = $too_big_expr.into();
418                         assert!(set.$try_to().is_none());
419                 }
420             )*
421
422             #[test]
423             fn truncated_overflow() {
424                 let trunc_invalid = EnumSet::<ThresholdEnum>::$from_truncated(0xFE);
425                 assert_eq!(A | B | C | D, trunc_invalid);
426                 $(
427                     let set: EnumSet<ThresholdEnum> = $too_big_expr | A;
428                     assert_eq!(2, set.$to_truncated());
429                 )*
430             }
431         }
432     }
433 }
434
435 bits_tests!(test_u8_bits, U8, (U16), u8,
436             as_u8 try_as_u8 as_u8_truncated from_u8 try_from_u8 from_u8_truncated);
437 bits_tests!(test_u16_bits, U16, (U32), u16,
438             as_u16 try_as_u16 as_u16_truncated from_u16 try_from_u16 from_u16_truncated);
439 bits_tests!(test_u32_bits, U32, (U64), u32,
440             as_u32 try_as_u32 as_u32_truncated from_u32 try_from_u32 from_u32_truncated);
441 bits_tests!(test_u64_bits, U64, (U128), u64,
442             as_u64 try_as_u64 as_u64_truncated from_u64 try_from_u64 from_u64_truncated);
443 bits_tests!(test_u128_bits, U128, (), u128,
444             as_u128 try_as_u128 as_u128_truncated from_u128 try_from_u128 from_u128_truncated);
445 bits_tests!(test_uize_bits, U32, (U128), usize,
446             as_usize try_as_usize as_usize_truncated
447             from_usize try_from_usize from_usize_truncated);