use crate::collections::btree_map::*;
const REP: usize = if cfg!(miri) { 2 } else { 100 };
const N: usize = if cfg!(miri) { 100 } else { 100000 };
struct BadClone {
x: usize,
}
impl Clone for BadClone {
fn clone(&self) -> Self {
if self.x == 200 {
panic!();
}
Self { x: self.x }
}
}
#[test]
fn exp_bad_clone_test() {
let mut map = BTreeMap::new();
for i in 0..1000 {
map.insert(i, BadClone { x: i });
}
let _ = std::panic::catch_unwind(|| {
let _ = map.clone();
});
}
#[test]
fn std_bad_clone_test() {
let mut map = std::collections::BTreeMap::new();
for i in 0..100 {
map.insert(i, BadClone { x: i });
}
let _ = std::panic::catch_unwind(|| {
let _ = map.clone();
});
}
#[test]
fn exp_clear_test() {
let n = N;
let mut map = BTreeMap::new();
for i in 0..n {
map.insert(i as u32, 1u8);
}
map.clear();
assert!(map.len() == 0);
}
#[test]
#[cfg(feature = "serde")]
fn exp_serde_test() {
let n = N;
let mut map = BTreeMap::new();
for i in 0..n {
map.insert(i as u32, 1u8);
}
for _i in 0..REP {
let ser = bincode::serialize(&map).unwrap();
let _: BTreeMap<i32, u8> = bincode::deserialize(&ser).unwrap();
}
}
#[test]
#[cfg(feature = "serde")]
fn std_serde_test() {
use std::collections::BTreeMap;
let n = N;
let mut map = BTreeMap::new();
for i in 0..n {
map.insert(i as u32, 1u8);
}
for _i in 0..REP {
let ser = bincode::serialize(&map).unwrap();
let _: BTreeMap<i32, u8> = bincode::deserialize(&ser).unwrap();
}
}
#[test]
fn exp_mem_test() {
let n = N * 10;
let mut map = BTreeMap::new();
for i in 0..n {
map.insert(i as u32, 1u8);
}
println!("Done insertions");
print_memory();
println!("Required memory: {} bytes", n * 5);
}
#[test]
fn std_mem_test() {
let n = N * 10;
let mut map = std::collections::BTreeMap::new();
for i in 0..n {
map.insert(i as u32, 1u8);
}
print_memory();
println!("Required memory: {} bytes", n * 5);
}
#[test]
fn exp_get_test() {
let mut m = BTreeMap::new();
let mut c = m.lower_bound_mut(Bound::Unbounded);
let n = N;
for i in 0..n {
let v = i;
c.insert_before(i, v).unwrap();
}
assert!(m.len() == n);
print_memory();
for _rep in 0..REP {
for i in 0..n {
let v = i;
assert!(m[&i] == v);
}
}
}
#[test]
fn exp_clone_test() {
let mut m = BTreeMap::<usize, usize>::new();
let mut c = m.lower_bound_mut(Bound::Unbounded);
let n = N;
for i in 0..n {
c.insert_before(i, i).unwrap();
}
assert!(m.len() == n);
print_memory();
for _rep in 0..REP {
let cm = m.clone();
assert!(cm.len() == n);
}
}
#[test]
fn exp_split_off_test() {
for _rep in 0..REP {
let mut m = BTreeMap::<usize, usize>::new();
let mut c = m.lower_bound_mut(Bound::Unbounded);
let n = N;
for i in 0..n {
c.insert_before(i, i).unwrap();
}
assert!(m.len() == n);
let m2 = m.split_off(&(n / 2));
assert!(m2.len() == n / 2);
assert!(m.len() + m2.len() == n);
}
}
#[test]
fn exp_cursor_remove_rev_test() {
for _rep in 0..REP {
let mut m = BTreeMap::<usize, usize>::new();
let mut c = m.lower_bound_mut(Bound::Unbounded);
let n = N;
for i in 0..n {
c.insert_before(i, i).unwrap();
}
assert!(m.len() == n);
let mut c = m.upper_bound_mut(Bound::Unbounded);
let mut i = n;
while let Some((k, v)) = c.remove_prev() {
i -= 1;
assert_eq!((k, v), (i, i));
}
assert_eq!(i, 0);
}
}
#[test]
fn exp_cursor_remove_fwd_test() {
for _rep in 0..REP {
let n = N;
let mut m = BTreeMap::<usize, usize>::new();
let mut c = m.lower_bound_mut(Bound::Unbounded);
for i in 0..n {
c.insert_before(i, i).unwrap();
}
assert!(m.len() == n);
let mut c = m.lower_bound_mut(Bound::Unbounded);
let mut i = 0;
while let Some((k, v)) = c.remove_next() {
assert_eq!((k, v), (i, i));
i += 1;
}
assert_eq!(i, n);
}
}
#[test]
fn exp_cursor_tuned_insert_only_test() {
for _rep in 0..REP {
let n = N;
let ct = DefaultTuning::new(1023, 2047);
let mut m = BTreeMap::with_tuning(ct);
m.tuning_mut().set_seq(true);
let mut c = m.lower_bound_mut(Bound::Unbounded);
for i in 0..n {
c.insert_before_unchecked(i, i);
}
if _rep == 0 {
print_memory();
}
}
}
#[test]
fn std_vec_seq_insert_only_test() {
for _rep in 0..REP {
let mut vec = Vec::<(usize, usize)>::default();
let n = N;
for i in 0..n {
vec.push((i, i));
}
if _rep == 0 {
print_memory();
}
}
}
#[test]
fn exp_cursor_insert_only_test() {
for _rep in 0..REP {
let n = N;
let mut m = BTreeMap::<usize, usize>::new();
let mut c = m.lower_bound_mut(Bound::Unbounded);
for i in 0..n {
c.insert_before_unchecked(i, i);
}
if _rep == 0 {
print_memory();
}
}
}
#[test]
fn exp_cursor_insert_test() {
for _rep in 0..REP {
let n = N;
let mut m = BTreeMap::<usize, usize>::new();
let mut c = m.lower_bound_mut(Bound::Unbounded);
for i in 0..n {
c.insert_before(i, i).unwrap();
}
let mut c = m.lower_bound_mut(Bound::Unbounded);
for i in 0..n {
let (k, v) = c.next().unwrap();
assert_eq!((*k, *v), (i, i));
}
let mut c = m.upper_bound_mut(Bound::Unbounded);
for i in 0..n {
let (k, v) = c.prev().unwrap();
assert_eq!((*k, *v), (n - i - 1, n - i - 1));
}
}
}
#[test]
fn mut_cursor_test() {
let n = 200;
let mut m = BTreeMap::<usize, usize>::new();
for i in 0..n {
m.insert(i, i);
}
let mut c = m.lower_bound_mut(Bound::Included(&105));
for i in 105..n {
let (k, v) = c.next().unwrap();
assert_eq!((*k, *v), (i, i));
}
let mut c = m.lower_bound_mut(Bound::Excluded(&105));
for i in 106..n {
let (k, v) = c.next().unwrap();
assert_eq!((*k, *v), (i, i));
}
let mut c = m.upper_bound_mut(Bound::Included(&105));
for i in 106..n {
let (k, v) = c.next().unwrap();
assert_eq!((*k, *v), (i, i));
}
let mut c = m.upper_bound_mut(Bound::Excluded(&105));
for i in 105..n {
let (k, v) = c.next().unwrap();
assert_eq!((*k, *v), (i, i));
}
let mut c = m.upper_bound_mut(Bound::Unbounded);
for i in (0..n).rev() {
let (k, v) = c.prev().unwrap();
assert_eq!((*k, *v), (i, i));
}
let mut a = BTreeMap::new();
a.insert(1, "a");
a.insert(2, "b");
a.insert(3, "c");
a.insert(4, "d");
let mut cursor = a.lower_bound_mut(Bound::Included(&2));
assert_eq!(cursor.peek_prev(), Some((&1, &mut "a")));
assert_eq!(cursor.peek_next(), Some((&2, &mut "b")));
let mut cursor = a.lower_bound_mut(Bound::Excluded(&2));
assert_eq!(cursor.peek_prev(), Some((&2, &mut "b")));
assert_eq!(cursor.peek_next(), Some((&3, &mut "c")));
let mut a = BTreeMap::new();
a.insert(1, "a");
a.insert(2, "b");
a.insert(3, "c");
a.insert(4, "d");
let mut cursor = a.upper_bound_mut(Bound::Included(&3));
assert_eq!(cursor.peek_prev(), Some((&3, &mut "c")));
assert_eq!(cursor.peek_next(), Some((&4, &mut "d")));
let mut cursor = a.upper_bound_mut(Bound::Excluded(&3));
assert_eq!(cursor.peek_prev(), Some((&2, &mut "b")));
assert_eq!(cursor.peek_next(), Some((&3, &mut "c")));
}
#[test]
fn is_this_ub() {
BTreeMap::new().entry(0).or_insert('a');
let mut map = BTreeMap::new();
map.insert(0, 'a');
*map.entry(0).or_insert('a') = 'b';
match map.entry(0) {
Entry::Occupied(e) => e.remove(),
_ => panic!(),
};
}
#[test]
fn basic_range_test() {
let mut map = BTreeMap::<usize, usize>::new();
for i in 0..100 {
map.insert(i, i);
}
for j in 0..100 {
assert_eq!(map.range(0..=j).count(), j + 1);
}
}
#[test]
fn exp_insert_seq_fwd() {
for _rep in 0..REP {
let mut map = BTreeMap::<usize, usize>::default();
map.tuning_mut().set_seq(true);
let n = N;
for i in 0..n {
map.insert(i, i);
}
if _rep == 0 {
print_memory();
}
}
}
#[test]
fn exp_insert_fwd() {
for _rep in 0..REP {
let mut map = BTreeMap::<usize, usize>::default();
let n = N;
for i in 0..n {
map.insert(i, i);
}
if _rep == 0 {
print_memory();
}
}
}
#[test]
fn std_insert_fwd() {
for _rep in 0..REP {
let mut map = std::collections::BTreeMap::<usize, usize>::default();
let n = N;
for i in 0..n {
map.insert(i, i);
}
if _rep == 0 {
print_memory();
}
}
}
#[test]
fn exp_insert_rev() {
for _rep in 0..REP {
let mut map = BTreeMap::<usize, usize>::default();
let n = N;
for i in (0..n).rev() {
map.insert(i, i);
}
if _rep == 0 {
print_memory();
}
}
}
#[test]
fn exp_insert_seq_rev() {
for _rep in 0..REP {
let mut map = BTreeMap::<usize, usize>::default();
map.tuning_mut().set_seq(true);
let n = N;
for i in (0..n).rev() {
map.insert(i, i);
}
if _rep == 0 {
print_memory();
}
}
}
#[test]
fn std_insert_rev() {
for _rep in 0..REP {
let mut map = std::collections::BTreeMap::<usize, usize>::default();
let n = N;
for i in (0..n).rev() {
map.insert(i, i);
}
if _rep == 0 {
print_memory();
}
}
}
#[test]
fn exp_entry() {
for _rep in 0..REP {
let mut map = BTreeMap::<usize, usize>::default();
let n = N;
for i in 0..n {
map.entry(i).or_insert(i);
}
}
}
#[test]
fn std_entry() {
for _rep in 0..REP {
let mut map = std::collections::BTreeMap::<usize, usize>::default();
let n = N;
for i in 0..n {
map.entry(i).or_insert(i);
}
}
}
#[test]
fn exp_iter_nm() {
let mut map = BTreeMap::<usize, usize>::default();
let n = N * 10;
for i in 0..n {
map.entry(i).or_insert(i);
}
for _rep in 0..REP {
for (k, v) in &map {
assert!(k == v);
}
}
}
#[test]
fn std_iter_nm() {
let mut map = std::collections::BTreeMap::<usize, usize>::default();
let n = N * 10;
for i in 0..n {
map.entry(i).or_insert(i);
}
for _rep in 0..REP {
for (k, v) in &map {
assert!(k == v);
}
}
}
#[test]
fn exp_iter_mut() {
let mut map = BTreeMap::<usize, usize>::default();
let n = N * 10;
for i in 0..n {
map.entry(i).or_insert(i);
}
for _rep in 0..REP {
for (k, v) in &mut map {
assert!(k == v);
}
}
}
#[test]
fn std_iter_mut() {
let mut map = std::collections::BTreeMap::<usize, usize>::default();
let n = N * 10;
for i in 0..n {
map.entry(i).or_insert(i);
}
for _rep in 0..REP {
for (k, v) in &mut map {
assert!(k == v);
}
}
}
#[test]
fn exp_into_iter() {
for _rep in 0..REP / 10 {
let mut map = BTreeMap::<usize, usize>::default();
let n = N * 10;
for i in 0..n {
map.insert(i, i);
}
for (k, v) in map {
assert!(k == v);
}
}
}
#[test]
fn std_into_iter() {
for _rep in 0..REP / 10 {
let mut map = std::collections::BTreeMap::<usize, usize>::default();
let n = N * 10;
for i in 0..n {
map.insert(i, i);
}
for (k, v) in map {
assert!(k == v);
}
}
}
#[test]
fn various_tests() {
for _rep in 0..REP {
let mut t = BTreeMap::<usize, usize>::default();
let n = N;
for i in 0..n {
t.insert(i, i);
}
if false {
assert!(t.first_key_value().unwrap().0 == &0);
assert!(t.last_key_value().unwrap().0 == &(n - 1));
println!("doing for x in & test");
for x in &t {
if *x.0 < 50 {
print!("{x:?};");
}
}
println!();
println!("doing for x in &mut test");
for x in &mut t {
*x.1 *= 1;
if *x.0 < 50 {
print!("{x:?};");
}
}
println!();
println!("doing range mut test");
for x in t.range_mut(20..=60000).rev() {
if *x.0 < 50 {
print!("{x:?};");
}
}
println!("done range mut test");
println!("t.len()={} doing range non-mut test", t.len());
for x in t.range(20..=60000).rev() {
if *x.0 < 50 {
print!("{x:?};");
}
}
println!("done range non-mut test");
println!("doing get test");
for i in 0..n {
assert_eq!(t.get(&i).unwrap(), &i);
}
println!("doing get_mut test");
for i in 0..n {
assert_eq!(t.get_mut(&i).unwrap(), &i);
}
println!("doing remove evens test");
for i in 0..n {
if i % 2 == 0 {
assert_eq!(t.remove(&i).unwrap(), i);
}
}
println!("doing retain test - retain only keys divisible by 5");
t.retain(|k, _v| k % 5 == 0);
println!("Consuming iterator test");
for x in t {
if x.0 < 50 {
print!("{x:?};");
}
}
println!();
println!("FromIter collect test");
let a = [1, 2, 3];
let map: BTreeMap<i32, i32> = a.iter().map(|&x| (x, x * x)).collect();
for x in map {
print!("{x:?};");
}
println!();
println!("From test");
let map = BTreeMap::from([(1, 2), (3, 4)]);
for x in map {
print!("{x:?};");
}
println!();
}
}
}
#[test]
fn sizes() {
type K = u64;
type V = u64;
println!("size of Leaf={}", std::mem::size_of::<Leaf<K, V>>());
println!("size of NonLeaf={}", std::mem::size_of::<NonLeaf<K, V>>());
println!(
"size of NonLeafInner={}",
std::mem::size_of::<NonLeafInner<K, V>>()
);
println!("size of Tree={}", std::mem::size_of::<Tree<K, V>>());
println!("size of BTreeMap={}", std::mem::size_of::<BTreeMap<K, V>>());
}
#[test]
fn test_custom_alloc() {
let da = Global {};
let ct = CustomTuning::new_in(32, 8, da);
let mut map = BTreeMap::with_tuning(ct);
map.insert("hello", "there");
}
fn print_memory() {
}
#[test]
fn test_custom_alloc2() {
let a = Global {};
let mut map = BTreeMap::new_in(a);
map.insert("hello", "there");
}
#[derive(Clone)]
struct ExTuning(Global);
unsafe impl Allocator for ExTuning {
fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
self.0.allocate(layout)
}
unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
unsafe {
self.0.deallocate(ptr, layout);
}
}
}
impl ExTuning {
const BRANCH: usize = 32;
const AU: usize = 4;
}
impl Tuning for ExTuning {
fn full_action(&self, i: usize, len: usize) -> FullAction {
let lim = Self::BRANCH * 2 + 1;
if len >= lim {
let b = len / 2;
let r = usize::from(i > b);
let au = Self::AU as usize;
FullAction::Split(b, b + (1 - r) * au, (len - b - 1) + r * au)
} else {
let mut na = len + Self::AU;
if na > lim {
na = lim;
}
FullAction::Extend(na)
}
}
fn space_action(&self, (len, alloc): (usize, usize)) -> Option<usize> {
if alloc - len >= Self::AU as usize {
Some(len)
} else {
None
}
}
fn set_seq(&mut self, _x: bool) -> bool {
false
}
}
#[test]
fn test_custom_alloc3() {
let t = ExTuning(Global {});
let mut map = BTreeMap::with_tuning(t);
map.insert("hello", "there");
for _ in &mut map {}
}