#![cfg(feature = "std")]
#![cfg(feature = "derive")]
use mem_dbg::*;
use std::rc::Rc;
use std::sync::Arc;
#[test]
fn test_box_in_struct() {
#[derive(MemSize)]
struct Test {
boxed: Box<u64>,
}
let s = Test {
boxed: Box::new(42),
};
let size = s.mem_size(SizeFlags::default());
let expected = std::mem::size_of::<Box<u64>>() + std::mem::size_of::<u64>();
assert_eq!(size, expected);
}
#[test]
fn test_arc_in_struct() {
#[allow(dead_code)]
struct ArcInner<T> {
strong: core::sync::atomic::AtomicUsize,
weak: core::sync::atomic::AtomicUsize,
data: T,
}
#[derive(MemSize)]
struct Test {
arc: Arc<u64>,
}
let s = Test { arc: Arc::new(42) };
let size = s.mem_size(SizeFlags::default());
assert_eq!(size, std::mem::size_of::<Arc<u64>>());
let size_follow = s.mem_size(SizeFlags::FOLLOW_RCS);
assert_eq!(
size_follow,
std::mem::size_of::<Arc<u64>>() + std::mem::size_of::<ArcInner<u64>>()
);
}
#[test]
fn test_arc_with_heap_payload() {
#[allow(dead_code)]
struct ArcInner<T> {
strong: core::sync::atomic::AtomicUsize,
weak: core::sync::atomic::AtomicUsize,
data: T,
}
#[derive(MemSize)]
struct Test {
arc: Arc<String>,
}
let payload = String::from("hello");
let payload_len = payload.len();
let payload_cap = payload.capacity();
let s = Test {
arc: Arc::new(payload),
};
let size = s.mem_size(SizeFlags::default());
assert_eq!(size, std::mem::size_of::<Arc<String>>());
let size_follow = s.mem_size(SizeFlags::FOLLOW_RCS);
assert_eq!(
size_follow,
std::mem::size_of::<Arc<String>>() + std::mem::size_of::<ArcInner<String>>() + payload_len
);
let size_follow_cap = s.mem_size(SizeFlags::FOLLOW_RCS | SizeFlags::CAPACITY);
assert_eq!(
size_follow_cap,
std::mem::size_of::<Arc<String>>() + std::mem::size_of::<ArcInner<String>>() + payload_cap
);
}
#[test]
fn test_rc_deduplication() {
#[derive(MemSize)]
struct Test {
rc1: Rc<[u8; 1000]>,
rc2: Rc<[u8; 1000]>,
}
let shared = Rc::new([0u8; 1000]);
let s = Test {
rc1: Rc::clone(&shared),
rc2: Rc::clone(&shared),
};
let size_no_follow = s.mem_size(SizeFlags::default());
assert_eq!(size_no_follow, 2 * std::mem::size_of::<Rc<[u8; 1000]>>());
let size_with_follow = s.mem_size(SizeFlags::FOLLOW_RCS);
let rc_ptr_size = std::mem::size_of::<Rc<[u8; 1000]>>();
assert!(
size_with_follow < 2 * rc_ptr_size + 2 * 1000,
"Deduplication failed: size {} should be less than {}",
size_with_follow,
2 * rc_ptr_size + 2 * 1000
);
}
#[test]
fn test_arc_deduplication() {
#[derive(MemSize)]
struct Test {
arc1: Arc<[u8; 1000]>,
arc2: Arc<[u8; 1000]>,
}
let shared = Arc::new([0u8; 1000]);
let s = Test {
arc1: Arc::clone(&shared),
arc2: Arc::clone(&shared),
};
let size_no_follow = s.mem_size(SizeFlags::default());
assert_eq!(size_no_follow, 2 * std::mem::size_of::<Arc<[u8; 1000]>>());
let size_with_follow = s.mem_size(SizeFlags::FOLLOW_RCS);
let arc_ptr_size = std::mem::size_of::<Arc<[u8; 1000]>>();
assert!(
size_with_follow < 2 * arc_ptr_size + 2 * 1000,
"Deduplication failed: size {} should be less than {}",
size_with_follow,
2 * arc_ptr_size + 2 * 1000
);
}
#[test]
fn test_reference_then_rc_counts_rc_allocation() {
#[derive(MemSize)]
#[mem_size(rec)]
struct Test<'a> {
borrowed: &'a String,
shared: Rc<String>,
}
let shared = Rc::new(String::from("hello"));
let s = Test {
borrowed: shared.as_ref(),
shared: Rc::clone(&shared),
};
let flags = SizeFlags::FOLLOW_REFS | SizeFlags::FOLLOW_RCS;
let shared_allocation =
Rc::clone(&shared).mem_size(SizeFlags::FOLLOW_RCS) - core::mem::size_of::<Rc<String>>();
assert_eq!(
s.mem_size(flags),
core::mem::size_of_val(&s) + shared_allocation
);
}
#[test]
fn test_reference_then_arc_counts_arc_allocation() {
#[derive(MemSize)]
#[mem_size(rec)]
struct Test<'a> {
borrowed: &'a String,
shared: Arc<String>,
}
let shared = Arc::new(String::from("hello"));
let s = Test {
borrowed: shared.as_ref(),
shared: Arc::clone(&shared),
};
let flags = SizeFlags::FOLLOW_REFS | SizeFlags::FOLLOW_RCS;
let shared_allocation =
Arc::clone(&shared).mem_size(SizeFlags::FOLLOW_RCS) - core::mem::size_of::<Arc<String>>();
assert_eq!(
s.mem_size(flags),
core::mem::size_of_val(&s) + shared_allocation
);
}
#[test]
fn test_reference_deduplication() {
#[derive(MemSize)]
struct Test<'a> {
ref1: &'a [u8; 1000],
ref2: &'a [u8; 1000],
}
let data = [0u8; 1000];
let s = Test {
ref1: &data,
ref2: &data,
};
let size_no_follow = s.mem_size(SizeFlags::default());
assert_eq!(size_no_follow, 2 * std::mem::size_of::<&[u8; 1000]>());
let size_with_follow = s.mem_size(SizeFlags::FOLLOW_REFS);
let ref_size = std::mem::size_of::<&[u8; 1000]>();
assert!(
size_with_follow < 2 * ref_size + 2 * 1000,
"Deduplication failed: size {} should be less than {}",
size_with_follow,
2 * ref_size + 2 * 1000
);
assert_eq!(size_with_follow, 2 * ref_size + 1000);
}