| 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 ] |
| 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] |
| 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] |
| 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 | |