1 //! Ensures that a custom config behaves as the default config, until limits are reached.
2 //! Prevents regression after #80.
3 
4 use crate::{cfg::CfgPrivate, Config, Slab};
5 
6 struct CustomConfig;
7 
8 #[cfg(target_pointer_width = "64")]
9 impl Config for CustomConfig {
10     const INITIAL_PAGE_SIZE: usize = 32;
11     const MAX_PAGES: usize = 15;
12     const MAX_THREADS: usize = 256;
13     const RESERVED_BITS: usize = 24;
14 }
15 
16 #[cfg(not(target_pointer_width = "64"))]
17 impl Config for CustomConfig {
18     const INITIAL_PAGE_SIZE: usize = 16;
19     const MAX_PAGES: usize = 6;
20     const MAX_THREADS: usize = 128;
21     const RESERVED_BITS: usize = 12;
22 }
23 
24 // We should repeat actions several times to detect invalid lifecycle changes.
25 const ITERS: u64 = 5;
26 
27 #[track_caller]
slab_eq(mut lhs: Slab<u64, impl Config>, mut rhs: Slab<u64, impl Config>)28 fn slab_eq(mut lhs: Slab<u64, impl Config>, mut rhs: Slab<u64, impl Config>) {
29     let mut lhs_vec = lhs.unique_iter().collect::<Vec<_>>();
30     lhs_vec.sort_unstable();
31     let mut rhs_vec = rhs.unique_iter().collect::<Vec<_>>();
32     rhs_vec.sort_unstable();
33     assert_eq!(lhs_vec, rhs_vec);
34 }
35 
36 /// Calls `insert(); remove()` multiple times to detect invalid releasing.
37 /// Initially, it revealed bugs in the `Slot::release_with()` implementation.
38 #[test]
insert_remove()39 fn insert_remove() {
40     eprintln!("bits={}; config={:#?}", usize::BITS, CustomConfig::debug());
41 
42     let default_slab = Slab::<u64, _>::new();
43     let custom_slab = Slab::<u64, _>::new_with_config::<CustomConfig>();
44 
45     for i in 0..=ITERS {
46         let idx = default_slab.insert(i).unwrap();
47         assert!(default_slab.remove(idx));
48 
49         let idx = custom_slab.insert(i).unwrap();
50         assert!(custom_slab.remove(idx));
51     }
52 
53     slab_eq(custom_slab, default_slab);
54 }
55 
56 /// Calls `get()` multiple times to detect invalid ref counting.
57 /// Initially, it revealed bugs in the `Slot::get()` implementation.
58 #[test]
double_get()59 fn double_get() {
60     eprintln!("bits={}; config={:#?}", usize::BITS, CustomConfig::debug());
61 
62     let default_slab = Slab::<u64, _>::new();
63     let custom_slab = Slab::<u64, _>::new_with_config::<CustomConfig>();
64 
65     for i in 0..=ITERS {
66         let idx = default_slab.insert(i).unwrap();
67         assert!(default_slab.get(idx).is_some());
68         assert!(default_slab.get(idx).is_some());
69         assert!(default_slab.remove(idx));
70 
71         let idx = custom_slab.insert(i).unwrap();
72         assert!(custom_slab.get(idx).is_some());
73         assert!(custom_slab.get(idx).is_some());
74         assert!(custom_slab.remove(idx));
75     }
76 
77     slab_eq(custom_slab, default_slab);
78 }
79