]> git.proxmox.com Git - rustc.git/blame - vendor/crossbeam-channel/tests/tick.rs
New upstream version 1.43.0+dfsg1
[rustc.git] / vendor / crossbeam-channel / tests / tick.rs
CommitLineData
dfeec247
XL
1//! Tests for the tick channel flavor.
2
3#[macro_use]
4extern crate crossbeam_channel;
5extern crate crossbeam_utils;
6extern crate rand;
7
8use std::sync::atomic::AtomicUsize;
9use std::sync::atomic::Ordering;
10use std::thread;
11use std::time::{Duration, Instant};
12
13use crossbeam_channel::{after, tick, Select, TryRecvError};
14use crossbeam_utils::thread::scope;
15
16fn ms(ms: u64) -> Duration {
17 Duration::from_millis(ms)
18}
19
20#[test]
21fn fire() {
22 let start = Instant::now();
23 let r = tick(ms(50));
24
25 assert_eq!(r.try_recv(), Err(TryRecvError::Empty));
26 thread::sleep(ms(100));
27
28 let fired = r.try_recv().unwrap();
29 assert!(start < fired);
30 assert!(fired - start >= ms(50));
31
32 let now = Instant::now();
33 assert!(fired < now);
34 assert!(now - fired >= ms(50));
35
36 assert_eq!(r.try_recv(), Err(TryRecvError::Empty));
37
38 select! {
39 recv(r) -> _ => panic!(),
40 default => {}
41 }
42
43 select! {
44 recv(r) -> _ => {}
45 recv(tick(ms(200))) -> _ => panic!(),
46 }
47}
48
49#[test]
50fn intervals() {
51 let start = Instant::now();
52 let r = tick(ms(50));
53
54 let t1 = r.recv().unwrap();
55 assert!(start + ms(50) <= t1);
56 assert!(start + ms(100) > t1);
57
58 thread::sleep(ms(300));
59 let t2 = r.try_recv().unwrap();
60 assert!(start + ms(100) <= t2);
61 assert!(start + ms(150) > t2);
62
63 assert_eq!(r.try_recv(), Err(TryRecvError::Empty));
64 let t3 = r.recv().unwrap();
65 assert!(start + ms(400) <= t3);
66 assert!(start + ms(450) > t3);
67
68 assert_eq!(r.try_recv(), Err(TryRecvError::Empty));
69}
70
71#[test]
72fn capacity() {
73 const COUNT: usize = 10;
74
75 for i in 0..COUNT {
76 let r = tick(ms(i as u64));
77 assert_eq!(r.capacity(), Some(1));
78 }
79}
80
81#[test]
82fn len_empty_full() {
83 let r = tick(ms(50));
84
85 assert_eq!(r.len(), 0);
86 assert_eq!(r.is_empty(), true);
87 assert_eq!(r.is_full(), false);
88
89 thread::sleep(ms(100));
90
91 assert_eq!(r.len(), 1);
92 assert_eq!(r.is_empty(), false);
93 assert_eq!(r.is_full(), true);
94
95 r.try_recv().unwrap();
96
97 assert_eq!(r.len(), 0);
98 assert_eq!(r.is_empty(), true);
99 assert_eq!(r.is_full(), false);
100}
101
102#[test]
103fn try_recv() {
104 let r = tick(ms(200));
105 assert!(r.try_recv().is_err());
106
107 thread::sleep(ms(100));
108 assert!(r.try_recv().is_err());
109
110 thread::sleep(ms(200));
111 assert!(r.try_recv().is_ok());
112 assert!(r.try_recv().is_err());
113
114 thread::sleep(ms(200));
115 assert!(r.try_recv().is_ok());
116 assert!(r.try_recv().is_err());
117}
118
119#[test]
120fn recv() {
121 let start = Instant::now();
122 let r = tick(ms(50));
123
124 let fired = r.recv().unwrap();
125 assert!(start < fired);
126 assert!(fired - start >= ms(50));
127
128 let now = Instant::now();
129 assert!(fired < now);
130 assert!(now - fired < fired - start);
131
132 assert_eq!(r.try_recv(), Err(TryRecvError::Empty));
133}
134
135#[test]
136fn recv_timeout() {
137 let start = Instant::now();
138 let r = tick(ms(200));
139
140 assert!(r.recv_timeout(ms(100)).is_err());
141 let now = Instant::now();
142 assert!(now - start >= ms(100));
143 assert!(now - start <= ms(150));
144
145 let fired = r.recv_timeout(ms(200)).unwrap();
146 assert!(fired - start >= ms(200));
147 assert!(fired - start <= ms(250));
148
149 assert!(r.recv_timeout(ms(100)).is_err());
150 let now = Instant::now();
151 assert!(now - start >= ms(300));
152 assert!(now - start <= ms(350));
153
154 let fired = r.recv_timeout(ms(200)).unwrap();
155 assert!(fired - start >= ms(400));
156 assert!(fired - start <= ms(450));
157}
158
159#[test]
160fn recv_two() {
161 let r1 = tick(ms(50));
162 let r2 = tick(ms(50));
163
164 scope(|scope| {
165 scope.spawn(|_| {
166 for _ in 0..10 {
167 select! {
168 recv(r1) -> _ => {}
169 recv(r2) -> _ => {}
170 }
171 }
172 });
173 scope.spawn(|_| {
174 for _ in 0..10 {
175 select! {
176 recv(r1) -> _ => {}
177 recv(r2) -> _ => {}
178 }
179 }
180 });
74b04a01
XL
181 })
182 .unwrap();
dfeec247
XL
183}
184
185#[test]
186fn recv_race() {
187 select! {
188 recv(tick(ms(50))) -> _ => {}
189 recv(tick(ms(100))) -> _ => panic!(),
190 }
191
192 select! {
193 recv(tick(ms(100))) -> _ => panic!(),
194 recv(tick(ms(50))) -> _ => {}
195 }
196}
197
198#[test]
199fn stress_default() {
200 const COUNT: usize = 10;
201
202 for _ in 0..COUNT {
203 select! {
204 recv(tick(ms(0))) -> _ => {}
205 default => panic!(),
206 }
207 }
208
209 for _ in 0..COUNT {
210 select! {
211 recv(tick(ms(100))) -> _ => panic!(),
212 default => {}
213 }
214 }
215}
216
217#[test]
218fn select() {
219 const THREADS: usize = 4;
220
221 let hits = AtomicUsize::new(0);
222 let r1 = tick(ms(200));
223 let r2 = tick(ms(300));
224
225 scope(|scope| {
226 for _ in 0..THREADS {
227 scope.spawn(|_| {
228 let timeout = after(ms(1100));
229 loop {
230 let mut sel = Select::new();
231 let oper1 = sel.recv(&r1);
232 let oper2 = sel.recv(&r2);
233 let oper3 = sel.recv(&timeout);
234 let oper = sel.select();
235 match oper.index() {
236 i if i == oper1 => {
237 oper.recv(&r1).unwrap();
238 hits.fetch_add(1, Ordering::SeqCst);
239 }
240 i if i == oper2 => {
241 oper.recv(&r2).unwrap();
242 hits.fetch_add(1, Ordering::SeqCst);
243 }
244 i if i == oper3 => {
245 oper.recv(&timeout).unwrap();
246 break;
247 }
248 _ => unreachable!(),
249 }
250 }
251 });
252 }
74b04a01
XL
253 })
254 .unwrap();
dfeec247
XL
255
256 assert_eq!(hits.load(Ordering::SeqCst), 8);
257}
258
259#[test]
260fn ready() {
261 const THREADS: usize = 4;
262
263 let hits = AtomicUsize::new(0);
264 let r1 = tick(ms(200));
265 let r2 = tick(ms(300));
266
267 scope(|scope| {
268 for _ in 0..THREADS {
269 scope.spawn(|_| {
270 let timeout = after(ms(1100));
271 'outer: loop {
272 let mut sel = Select::new();
273 sel.recv(&r1);
274 sel.recv(&r2);
275 sel.recv(&timeout);
276 loop {
277 match sel.ready() {
278 0 => {
279 if r1.try_recv().is_ok() {
280 hits.fetch_add(1, Ordering::SeqCst);
281 break;
282 }
283 }
284 1 => {
285 if r2.try_recv().is_ok() {
286 hits.fetch_add(1, Ordering::SeqCst);
287 break;
288 }
289 }
290 2 => {
291 if timeout.try_recv().is_ok() {
292 break 'outer;
293 }
294 }
295 _ => unreachable!(),
296 }
297 }
298 }
299 });
300 }
74b04a01
XL
301 })
302 .unwrap();
dfeec247
XL
303
304 assert_eq!(hits.load(Ordering::SeqCst), 8);
305}
306
307#[test]
308fn fairness() {
309 const COUNT: usize = 30;
310
311 for &dur in &[0, 1] {
312 let mut hits = [0usize; 2];
313
314 for _ in 0..COUNT {
315 let r1 = tick(ms(dur));
316 let r2 = tick(ms(dur));
317
318 for _ in 0..COUNT {
319 select! {
320 recv(r1) -> _ => hits[0] += 1,
321 recv(r2) -> _ => hits[1] += 1,
322 }
323 }
324 }
325
326 assert!(hits.iter().all(|x| *x >= COUNT / hits.len() / 2));
327 }
328}
329
330#[test]
331fn fairness_duplicates() {
332 const COUNT: usize = 30;
333
334 for &dur in &[0, 1] {
335 let mut hits = [0usize; 5];
336
337 for _ in 0..COUNT {
338 let r = tick(ms(dur));
339
340 for _ in 0..COUNT {
341 select! {
342 recv(r) -> _ => hits[0] += 1,
343 recv(r) -> _ => hits[1] += 1,
344 recv(r) -> _ => hits[2] += 1,
345 recv(r) -> _ => hits[3] += 1,
346 recv(r) -> _ => hits[4] += 1,
347 }
348 }
349 }
350
351 assert!(hits.iter().all(|x| *x >= COUNT / hits.len() / 2));
352 }
353}