]> git.lizzy.rs Git - rust.git/blob - library/alloc/src/testing/crash_test.rs
Rollup merge of #107248 - erikdesjardins:addrspace, r=oli-obk
[rust.git] / library / alloc / src / testing / crash_test.rs
1 // We avoid relying on anything else in the crate, apart from the `Debug` trait.
2 use crate::fmt::Debug;
3 use std::cmp::Ordering;
4 use std::sync::atomic::{AtomicUsize, Ordering::SeqCst};
5
6 /// A blueprint for crash test dummy instances that monitor particular events.
7 /// Some instances may be configured to panic at some point.
8 /// Events are `clone`, `drop` or some anonymous `query`.
9 ///
10 /// Crash test dummies are identified and ordered by an id, so they can be used
11 /// as keys in a BTreeMap.
12 #[derive(Debug)]
13 pub struct CrashTestDummy {
14     pub id: usize,
15     cloned: AtomicUsize,
16     dropped: AtomicUsize,
17     queried: AtomicUsize,
18 }
19
20 impl CrashTestDummy {
21     /// Creates a crash test dummy design. The `id` determines order and equality of instances.
22     pub fn new(id: usize) -> CrashTestDummy {
23         CrashTestDummy {
24             id,
25             cloned: AtomicUsize::new(0),
26             dropped: AtomicUsize::new(0),
27             queried: AtomicUsize::new(0),
28         }
29     }
30
31     /// Creates an instance of a crash test dummy that records what events it experiences
32     /// and optionally panics.
33     pub fn spawn(&self, panic: Panic) -> Instance<'_> {
34         Instance { origin: self, panic }
35     }
36
37     /// Returns how many times instances of the dummy have been cloned.
38     pub fn cloned(&self) -> usize {
39         self.cloned.load(SeqCst)
40     }
41
42     /// Returns how many times instances of the dummy have been dropped.
43     pub fn dropped(&self) -> usize {
44         self.dropped.load(SeqCst)
45     }
46
47     /// Returns how many times instances of the dummy have had their `query` member invoked.
48     pub fn queried(&self) -> usize {
49         self.queried.load(SeqCst)
50     }
51 }
52
53 #[derive(Debug)]
54 pub struct Instance<'a> {
55     origin: &'a CrashTestDummy,
56     panic: Panic,
57 }
58
59 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
60 pub enum Panic {
61     Never,
62     InClone,
63     InDrop,
64     InQuery,
65 }
66
67 impl Instance<'_> {
68     pub fn id(&self) -> usize {
69         self.origin.id
70     }
71
72     /// Some anonymous query, the result of which is already given.
73     pub fn query<R>(&self, result: R) -> R {
74         self.origin.queried.fetch_add(1, SeqCst);
75         if self.panic == Panic::InQuery {
76             panic!("panic in `query`");
77         }
78         result
79     }
80 }
81
82 impl Clone for Instance<'_> {
83     fn clone(&self) -> Self {
84         self.origin.cloned.fetch_add(1, SeqCst);
85         if self.panic == Panic::InClone {
86             panic!("panic in `clone`");
87         }
88         Self { origin: self.origin, panic: Panic::Never }
89     }
90 }
91
92 impl Drop for Instance<'_> {
93     fn drop(&mut self) {
94         self.origin.dropped.fetch_add(1, SeqCst);
95         if self.panic == Panic::InDrop {
96             panic!("panic in `drop`");
97         }
98     }
99 }
100
101 impl PartialOrd for Instance<'_> {
102     fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
103         self.id().partial_cmp(&other.id())
104     }
105 }
106
107 impl Ord for Instance<'_> {
108     fn cmp(&self, other: &Self) -> Ordering {
109         self.id().cmp(&other.id())
110     }
111 }
112
113 impl PartialEq for Instance<'_> {
114     fn eq(&self, other: &Self) -> bool {
115         self.id().eq(&other.id())
116     }
117 }
118
119 impl Eq for Instance<'_> {}