3 releases
0.1.2 | Mar 25, 2024 |
---|---|
0.1.1 | Mar 24, 2024 |
0.1.0 | Mar 24, 2024 |
#291 in Testing
72 downloads per month
Used in compact-rc
19KB
281 lines
dropcount
Count destructor calls.
Rust is memory safe, but memory bugs may occur in unsafe blocks. The unsafe programming is often required when implementing our own data structures like containers or smart pointers. This crate provides a way to test memory leaks or multiple destruction by counting destructor calls.
If this crate is used only for tests, use 'dev-dependencies' section in Cargo.toml as follows;
# Cargo.toml
[dev-dependencies]
dropcount = "0.1"
Usage
// Create a pair of counter and viewer.
// They share an internal count value.
let (counter, viewer) = dropcount::new();
// The viewer returns 0.
// The counter has not been destructed.
assert_eq!(viewer.get(), 0);
// Destruct the counter.
drop(counter);
// The viewer returns 1 after destructing the counter.
assert_eq!(viewer.get(), 1);
Example
Testing smart pointers
An example for testing a smart pointer destructs its value exactly once.
use std::rc::Rc;
fn test_rc() {
let (counter, viewer) = dropcount::new();
// rc1 and rc2 shares the counter object.
let rc1 = Rc::new(counter);
let rc2 = rc1.clone();
// The counter is not destructed.
assert_eq!(viewer.get(), 0);
drop(rc1);
// The counter is not destructed.
assert_eq!(viewer.get(), 0);
drop(rc2);
// The counter is destructed.
assert_eq!(viewer.get(), 1);
}
Testing collections
An example for testing a container destructs each value exactly once.
use std::collections::HashMap;
fn test_hashmap() {
let (counters, viewers) = dropcount::new_vec(5);
let mut map: HashMap<usize, dropcount::Counter> =
counters.into_iter().enumerate().collect();
assert_eq!(viewers[0].get(), 0);
assert_eq!(viewers[1].get(), 0);
assert_eq!(viewers[2].get(), 0);
assert_eq!(viewers[3].get(), 0);
assert_eq!(viewers[4].get(), 0);
// Remove an element.
map.remove(&2);
// The viewer paired with the removed element returns 1.
assert_eq!(viewers[0].get(), 0);
assert_eq!(viewers[1].get(), 0);
assert_eq!(viewers[2].get(), 1);
assert_eq!(viewers[3].get(), 0);
assert_eq!(viewers[4].get(), 0);
// Drop the container.
drop(map);
// All viewers returns 1 after the container is dropped.
assert_eq!(viewers[0].get(), 1);
assert_eq!(viewers[1].get(), 1);
assert_eq!(viewers[2].get(), 1);
assert_eq!(viewers[3].get(), 1);
assert_eq!(viewers[4].get(), 1);
}
Multi-threading support
This crate supports multi-threading. Atomic integers are used as the internal coutner values. Therefore, it is possible to capture the number of destructions with multi-threading.
use std::thread;
fn test_multi_thread() {
let (counter, viewer) = dropcount::new();
let handle = thread::spawn(move || {
drop(counter);
});
handle.join().expect("Error in thread.");
assert_eq!(viewer.get(), 1);
}