1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
|
use std::cmp::Ordering;
use std::fmt::Debug;
use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering::SeqCst;
/// A blueprint for crash test dummy instances that monitor drops.
/// Some instances may be configured to panic at some point.
///
/// Crash test dummies are identified and ordered by an id, so they can be used
/// as keys in a BTreeMap.
#[derive(Debug)]
pub struct CrashTestDummy {
pub id: usize,
dropped: AtomicUsize,
}
impl CrashTestDummy {
/// Creates a crash test dummy design. The `id` determines order and equality of instances.
pub fn new(id: usize) -> CrashTestDummy {
CrashTestDummy { id, dropped: AtomicUsize::new(0) }
}
/// Creates an instance of a crash test dummy that records what events it experiences
/// and optionally panics.
pub fn spawn(&self, panic: Panic) -> Instance<'_> {
Instance { origin: self, panic }
}
/// Returns how many times instances of the dummy have been dropped.
pub fn dropped(&self) -> usize {
self.dropped.load(SeqCst)
}
}
#[derive(Debug)]
pub struct Instance<'a> {
origin: &'a CrashTestDummy,
panic: Panic,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Panic {
Never,
InDrop,
}
impl Instance<'_> {
pub fn id(&self) -> usize {
self.origin.id
}
}
impl Drop for Instance<'_> {
fn drop(&mut self) {
self.origin.dropped.fetch_add(1, SeqCst);
if self.panic == Panic::InDrop {
panic!("panic in `drop`");
}
}
}
impl PartialOrd for Instance<'_> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.id().partial_cmp(&other.id())
}
}
impl Ord for Instance<'_> {
fn cmp(&self, other: &Self) -> Ordering {
self.id().cmp(&other.id())
}
}
impl PartialEq for Instance<'_> {
fn eq(&self, other: &Self) -> bool {
self.id().eq(&other.id())
}
}
impl Eq for Instance<'_> {}
|