]>
Commit | Line | Data |
---|---|---|
064997fb FG |
1 | use std::sync::atomic::{AtomicUsize, Ordering}; |
2 | ||
3 | use crossbeam_queue::SegQueue; | |
4 | use crossbeam_utils::thread::scope; | |
5 | use rand::{thread_rng, Rng}; | |
6 | ||
7 | #[test] | |
8 | fn smoke() { | |
9 | let q = SegQueue::new(); | |
10 | q.push(7); | |
11 | assert_eq!(q.pop(), Some(7)); | |
12 | ||
13 | q.push(8); | |
14 | assert_eq!(q.pop(), Some(8)); | |
15 | assert!(q.pop().is_none()); | |
16 | } | |
17 | ||
18 | #[test] | |
19 | fn len_empty_full() { | |
20 | let q = SegQueue::new(); | |
21 | ||
22 | assert_eq!(q.len(), 0); | |
23 | assert!(q.is_empty()); | |
24 | ||
25 | q.push(()); | |
26 | ||
27 | assert_eq!(q.len(), 1); | |
28 | assert!(!q.is_empty()); | |
29 | ||
30 | q.pop().unwrap(); | |
31 | ||
32 | assert_eq!(q.len(), 0); | |
33 | assert!(q.is_empty()); | |
34 | } | |
35 | ||
36 | #[test] | |
37 | fn len() { | |
38 | let q = SegQueue::new(); | |
39 | ||
40 | assert_eq!(q.len(), 0); | |
41 | ||
42 | for i in 0..50 { | |
43 | q.push(i); | |
44 | assert_eq!(q.len(), i + 1); | |
45 | } | |
46 | ||
47 | for i in 0..50 { | |
48 | q.pop().unwrap(); | |
49 | assert_eq!(q.len(), 50 - i - 1); | |
50 | } | |
51 | ||
52 | assert_eq!(q.len(), 0); | |
53 | } | |
54 | ||
55 | #[cfg_attr(miri, ignore)] // Miri is too slow | |
56 | #[test] | |
57 | fn spsc() { | |
58 | const COUNT: usize = 100_000; | |
59 | ||
60 | let q = SegQueue::new(); | |
61 | ||
62 | scope(|scope| { | |
63 | scope.spawn(|_| { | |
64 | for i in 0..COUNT { | |
65 | loop { | |
66 | if let Some(x) = q.pop() { | |
67 | assert_eq!(x, i); | |
68 | break; | |
69 | } | |
70 | } | |
71 | } | |
72 | assert!(q.pop().is_none()); | |
73 | }); | |
74 | scope.spawn(|_| { | |
75 | for i in 0..COUNT { | |
76 | q.push(i); | |
77 | } | |
78 | }); | |
79 | }) | |
80 | .unwrap(); | |
81 | } | |
82 | ||
83 | #[cfg_attr(miri, ignore)] // Miri is too slow | |
84 | #[test] | |
85 | fn mpmc() { | |
86 | const COUNT: usize = 25_000; | |
87 | const THREADS: usize = 4; | |
88 | ||
89 | let q = SegQueue::<usize>::new(); | |
90 | let v = (0..COUNT).map(|_| AtomicUsize::new(0)).collect::<Vec<_>>(); | |
91 | ||
92 | scope(|scope| { | |
93 | for _ in 0..THREADS { | |
94 | scope.spawn(|_| { | |
95 | for _ in 0..COUNT { | |
96 | let n = loop { | |
97 | if let Some(x) = q.pop() { | |
98 | break x; | |
99 | } | |
100 | }; | |
101 | v[n].fetch_add(1, Ordering::SeqCst); | |
102 | } | |
103 | }); | |
104 | } | |
105 | for _ in 0..THREADS { | |
106 | scope.spawn(|_| { | |
107 | for i in 0..COUNT { | |
108 | q.push(i); | |
109 | } | |
110 | }); | |
111 | } | |
112 | }) | |
113 | .unwrap(); | |
114 | ||
115 | for c in v { | |
116 | assert_eq!(c.load(Ordering::SeqCst), THREADS); | |
117 | } | |
118 | } | |
119 | ||
120 | #[cfg_attr(miri, ignore)] // Miri is too slow | |
121 | #[test] | |
122 | fn drops() { | |
123 | const RUNS: usize = 100; | |
124 | ||
125 | static DROPS: AtomicUsize = AtomicUsize::new(0); | |
126 | ||
127 | #[derive(Debug, PartialEq)] | |
128 | struct DropCounter; | |
129 | ||
130 | impl Drop for DropCounter { | |
131 | fn drop(&mut self) { | |
132 | DROPS.fetch_add(1, Ordering::SeqCst); | |
133 | } | |
134 | } | |
135 | ||
136 | let mut rng = thread_rng(); | |
137 | ||
138 | for _ in 0..RUNS { | |
139 | let steps = rng.gen_range(0..10_000); | |
140 | let additional = rng.gen_range(0..1000); | |
141 | ||
142 | DROPS.store(0, Ordering::SeqCst); | |
143 | let q = SegQueue::new(); | |
144 | ||
145 | scope(|scope| { | |
146 | scope.spawn(|_| { | |
147 | for _ in 0..steps { | |
148 | while q.pop().is_none() {} | |
149 | } | |
150 | }); | |
151 | ||
152 | scope.spawn(|_| { | |
153 | for _ in 0..steps { | |
154 | q.push(DropCounter); | |
155 | } | |
156 | }); | |
157 | }) | |
158 | .unwrap(); | |
159 | ||
160 | for _ in 0..additional { | |
161 | q.push(DropCounter); | |
162 | } | |
163 | ||
164 | assert_eq!(DROPS.load(Ordering::SeqCst), steps); | |
165 | drop(q); | |
166 | assert_eq!(DROPS.load(Ordering::SeqCst), steps + additional); | |
167 | } | |
168 | } | |
169 | ||
170 | #[test] | |
171 | fn into_iter() { | |
172 | let q = SegQueue::new(); | |
173 | for i in 0..100 { | |
174 | q.push(i); | |
175 | } | |
176 | for (i, j) in q.into_iter().enumerate() { | |
177 | assert_eq!(i, j); | |
178 | } | |
179 | } | |
180 | ||
181 | #[test] | |
182 | fn into_iter_drop() { | |
183 | let q = SegQueue::new(); | |
184 | for i in 0..100 { | |
185 | q.push(i); | |
186 | } | |
187 | for (i, j) in q.into_iter().enumerate().take(50) { | |
188 | assert_eq!(i, j); | |
189 | } | |
190 | } |