• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! Tests for the `select!` macro.
2 
3 #![forbid(unsafe_code)] // select! is safe.
4 #![allow(clippy::drop_copy, clippy::match_single_binding)]
5 
6 use std::any::Any;
7 use std::cell::Cell;
8 use std::ops::Deref;
9 use std::thread;
10 use std::time::{Duration, Instant};
11 
12 use crossbeam_channel::{after, bounded, never, select, tick, unbounded};
13 use crossbeam_channel::{Receiver, RecvError, SendError, Sender, TryRecvError};
14 use crossbeam_utils::thread::scope;
15 
ms(ms: u64) -> Duration16 fn ms(ms: u64) -> Duration {
17     Duration::from_millis(ms)
18 }
19 
20 #[test]
smoke1()21 fn smoke1() {
22     let (s1, r1) = unbounded::<usize>();
23     let (s2, r2) = unbounded::<usize>();
24 
25     s1.send(1).unwrap();
26 
27     select! {
28         recv(r1) -> v => assert_eq!(v, Ok(1)),
29         recv(r2) -> _ => panic!(),
30     }
31 
32     s2.send(2).unwrap();
33 
34     select! {
35         recv(r1) -> _ => panic!(),
36         recv(r2) -> v => assert_eq!(v, Ok(2)),
37     }
38 }
39 
40 #[test]
smoke2()41 fn smoke2() {
42     let (_s1, r1) = unbounded::<i32>();
43     let (_s2, r2) = unbounded::<i32>();
44     let (_s3, r3) = unbounded::<i32>();
45     let (_s4, r4) = unbounded::<i32>();
46     let (s5, r5) = unbounded::<i32>();
47 
48     s5.send(5).unwrap();
49 
50     select! {
51         recv(r1) -> _ => panic!(),
52         recv(r2) -> _ => panic!(),
53         recv(r3) -> _ => panic!(),
54         recv(r4) -> _ => panic!(),
55         recv(r5) -> v => assert_eq!(v, Ok(5)),
56     }
57 }
58 
59 #[test]
disconnected()60 fn disconnected() {
61     let (s1, r1) = unbounded::<i32>();
62     let (s2, r2) = unbounded::<i32>();
63 
64     scope(|scope| {
65         scope.spawn(|_| {
66             drop(s1);
67             thread::sleep(ms(500));
68             s2.send(5).unwrap();
69         });
70 
71         select! {
72             recv(r1) -> v => assert!(v.is_err()),
73             recv(r2) -> _ => panic!(),
74             default(ms(1000)) => panic!(),
75         }
76 
77         r2.recv().unwrap();
78     })
79     .unwrap();
80 
81     select! {
82         recv(r1) -> v => assert!(v.is_err()),
83         recv(r2) -> _ => panic!(),
84         default(ms(1000)) => panic!(),
85     }
86 
87     scope(|scope| {
88         scope.spawn(|_| {
89             thread::sleep(ms(500));
90             drop(s2);
91         });
92 
93         select! {
94             recv(r2) -> v => assert!(v.is_err()),
95             default(ms(1000)) => panic!(),
96         }
97     })
98     .unwrap();
99 }
100 
101 #[test]
default()102 fn default() {
103     let (s1, r1) = unbounded::<i32>();
104     let (s2, r2) = unbounded::<i32>();
105 
106     select! {
107         recv(r1) -> _ => panic!(),
108         recv(r2) -> _ => panic!(),
109         default => {}
110     }
111 
112     drop(s1);
113 
114     select! {
115         recv(r1) -> v => assert!(v.is_err()),
116         recv(r2) -> _ => panic!(),
117         default => panic!(),
118     }
119 
120     s2.send(2).unwrap();
121 
122     select! {
123         recv(r2) -> v => assert_eq!(v, Ok(2)),
124         default => panic!(),
125     }
126 
127     select! {
128         recv(r2) -> _ => panic!(),
129         default => {},
130     }
131 
132     select! {
133         default => {},
134     }
135 }
136 
137 #[test]
timeout()138 fn timeout() {
139     let (_s1, r1) = unbounded::<i32>();
140     let (s2, r2) = unbounded::<i32>();
141 
142     scope(|scope| {
143         scope.spawn(|_| {
144             thread::sleep(ms(1500));
145             s2.send(2).unwrap();
146         });
147 
148         select! {
149             recv(r1) -> _ => panic!(),
150             recv(r2) -> _ => panic!(),
151             default(ms(1000)) => {},
152         }
153 
154         select! {
155             recv(r1) -> _ => panic!(),
156             recv(r2) -> v => assert_eq!(v, Ok(2)),
157             default(ms(1000)) => panic!(),
158         }
159     })
160     .unwrap();
161 
162     scope(|scope| {
163         let (s, r) = unbounded::<i32>();
164 
165         scope.spawn(move |_| {
166             thread::sleep(ms(500));
167             drop(s);
168         });
169 
170         select! {
171             default(ms(1000)) => {
172                 select! {
173                     recv(r) -> v => assert!(v.is_err()),
174                     default => panic!(),
175                 }
176             }
177         }
178     })
179     .unwrap();
180 }
181 
182 #[test]
default_when_disconnected()183 fn default_when_disconnected() {
184     let (_, r) = unbounded::<i32>();
185 
186     select! {
187         recv(r) -> res => assert!(res.is_err()),
188         default => panic!(),
189     }
190 
191     let (_, r) = unbounded::<i32>();
192 
193     select! {
194         recv(r) -> res => assert!(res.is_err()),
195         default(ms(1000)) => panic!(),
196     }
197 
198     let (s, _) = bounded::<i32>(0);
199 
200     select! {
201         send(s, 0) -> res => assert!(res.is_err()),
202         default => panic!(),
203     }
204 
205     let (s, _) = bounded::<i32>(0);
206 
207     select! {
208         send(s, 0) -> res => assert!(res.is_err()),
209         default(ms(1000)) => panic!(),
210     }
211 }
212 
213 #[test]
default_only()214 fn default_only() {
215     let start = Instant::now();
216     select! {
217         default => {}
218     }
219     let now = Instant::now();
220     assert!(now - start <= ms(50));
221 
222     let start = Instant::now();
223     select! {
224         default(ms(500)) => {}
225     }
226     let now = Instant::now();
227     assert!(now - start >= ms(450));
228     assert!(now - start <= ms(550));
229 }
230 
231 #[test]
unblocks()232 fn unblocks() {
233     let (s1, r1) = bounded::<i32>(0);
234     let (s2, r2) = bounded::<i32>(0);
235 
236     scope(|scope| {
237         scope.spawn(|_| {
238             thread::sleep(ms(500));
239             s2.send(2).unwrap();
240         });
241 
242         select! {
243             recv(r1) -> _ => panic!(),
244             recv(r2) -> v => assert_eq!(v, Ok(2)),
245             default(ms(1000)) => panic!(),
246         }
247     })
248     .unwrap();
249 
250     scope(|scope| {
251         scope.spawn(|_| {
252             thread::sleep(ms(500));
253             assert_eq!(r1.recv().unwrap(), 1);
254         });
255 
256         select! {
257             send(s1, 1) -> _ => {},
258             send(s2, 2) -> _ => panic!(),
259             default(ms(1000)) => panic!(),
260         }
261     })
262     .unwrap();
263 }
264 
265 #[test]
both_ready()266 fn both_ready() {
267     let (s1, r1) = bounded(0);
268     let (s2, r2) = bounded(0);
269 
270     scope(|scope| {
271         scope.spawn(|_| {
272             thread::sleep(ms(500));
273             s1.send(1).unwrap();
274             assert_eq!(r2.recv().unwrap(), 2);
275         });
276 
277         for _ in 0..2 {
278             select! {
279                 recv(r1) -> v => assert_eq!(v, Ok(1)),
280                 send(s2, 2) -> _ => {},
281             }
282         }
283     })
284     .unwrap();
285 }
286 
287 #[test]
loop_try()288 fn loop_try() {
289     const RUNS: usize = 20;
290 
291     for _ in 0..RUNS {
292         let (s1, r1) = bounded::<i32>(0);
293         let (s2, r2) = bounded::<i32>(0);
294         let (s_end, r_end) = bounded::<()>(0);
295 
296         scope(|scope| {
297             scope.spawn(|_| loop {
298                 select! {
299                     send(s1, 1) -> _ => break,
300                     default => {}
301                 }
302 
303                 select! {
304                     recv(r_end) -> _ => break,
305                     default => {}
306                 }
307             });
308 
309             scope.spawn(|_| loop {
310                 if let Ok(x) = r2.try_recv() {
311                     assert_eq!(x, 2);
312                     break;
313                 }
314 
315                 select! {
316                     recv(r_end) -> _ => break,
317                     default => {}
318                 }
319             });
320 
321             scope.spawn(|_| {
322                 thread::sleep(ms(500));
323 
324                 select! {
325                     recv(r1) -> v => assert_eq!(v, Ok(1)),
326                     send(s2, 2) -> _ => {},
327                     default(ms(500)) => panic!(),
328                 }
329 
330                 drop(s_end);
331             });
332         })
333         .unwrap();
334     }
335 }
336 
337 #[test]
cloning1()338 fn cloning1() {
339     scope(|scope| {
340         let (s1, r1) = unbounded::<i32>();
341         let (_s2, r2) = unbounded::<i32>();
342         let (s3, r3) = unbounded::<()>();
343 
344         scope.spawn(move |_| {
345             r3.recv().unwrap();
346             drop(s1.clone());
347             assert_eq!(r3.try_recv(), Err(TryRecvError::Empty));
348             s1.send(1).unwrap();
349             r3.recv().unwrap();
350         });
351 
352         s3.send(()).unwrap();
353 
354         select! {
355             recv(r1) -> _ => {},
356             recv(r2) -> _ => {},
357         }
358 
359         s3.send(()).unwrap();
360     })
361     .unwrap();
362 }
363 
364 #[test]
cloning2()365 fn cloning2() {
366     let (s1, r1) = unbounded::<()>();
367     let (s2, r2) = unbounded::<()>();
368     let (_s3, _r3) = unbounded::<()>();
369 
370     scope(|scope| {
371         scope.spawn(move |_| {
372             select! {
373                 recv(r1) -> _ => panic!(),
374                 recv(r2) -> _ => {},
375             }
376         });
377 
378         thread::sleep(ms(500));
379         drop(s1.clone());
380         s2.send(()).unwrap();
381     })
382     .unwrap();
383 }
384 
385 #[test]
preflight1()386 fn preflight1() {
387     let (s, r) = unbounded();
388     s.send(()).unwrap();
389 
390     select! {
391         recv(r) -> _ => {}
392     }
393 }
394 
395 #[test]
preflight2()396 fn preflight2() {
397     let (s, r) = unbounded();
398     drop(s.clone());
399     s.send(()).unwrap();
400     drop(s);
401 
402     select! {
403         recv(r) -> v => assert!(v.is_ok()),
404     }
405     assert_eq!(r.try_recv(), Err(TryRecvError::Disconnected));
406 }
407 
408 #[test]
preflight3()409 fn preflight3() {
410     let (s, r) = unbounded();
411     drop(s.clone());
412     s.send(()).unwrap();
413     drop(s);
414     r.recv().unwrap();
415 
416     select! {
417         recv(r) -> v => assert!(v.is_err())
418     }
419 }
420 
421 #[test]
duplicate_operations()422 fn duplicate_operations() {
423     let (s, r) = unbounded::<i32>();
424     let mut hit = [false; 4];
425 
426     while hit.iter().any(|hit| !hit) {
427         select! {
428             recv(r) -> _ => hit[0] = true,
429             recv(r) -> _ => hit[1] = true,
430             send(s, 0) -> _ => hit[2] = true,
431             send(s, 0) -> _ => hit[3] = true,
432         }
433     }
434 }
435 
436 #[test]
nesting()437 fn nesting() {
438     let (s, r) = unbounded::<i32>();
439 
440     select! {
441         send(s, 0) -> _ => {
442             select! {
443                 recv(r) -> v => {
444                     assert_eq!(v, Ok(0));
445                     select! {
446                         send(s, 1) -> _ => {
447                             select! {
448                                 recv(r) -> v => {
449                                     assert_eq!(v, Ok(1));
450                                 }
451                             }
452                         }
453                     }
454                 }
455             }
456         }
457     }
458 }
459 
460 #[test]
461 #[should_panic(expected = "send panicked")]
panic_sender()462 fn panic_sender() {
463     fn get() -> Sender<i32> {
464         panic!("send panicked")
465     }
466 
467     #[allow(unreachable_code)]
468     {
469         select! {
470             send(get(), panic!()) -> _ => {}
471         }
472     }
473 }
474 
475 #[test]
476 #[should_panic(expected = "recv panicked")]
panic_receiver()477 fn panic_receiver() {
478     fn get() -> Receiver<i32> {
479         panic!("recv panicked")
480     }
481 
482     select! {
483         recv(get()) -> _ => {}
484     }
485 }
486 
487 #[test]
stress_recv()488 fn stress_recv() {
489     #[cfg(miri)]
490     const COUNT: usize = 50;
491     #[cfg(not(miri))]
492     const COUNT: usize = 10_000;
493 
494     let (s1, r1) = unbounded();
495     let (s2, r2) = bounded(5);
496     let (s3, r3) = bounded(100);
497 
498     scope(|scope| {
499         scope.spawn(|_| {
500             for i in 0..COUNT {
501                 s1.send(i).unwrap();
502                 r3.recv().unwrap();
503 
504                 s2.send(i).unwrap();
505                 r3.recv().unwrap();
506             }
507         });
508 
509         for i in 0..COUNT {
510             for _ in 0..2 {
511                 select! {
512                     recv(r1) -> v => assert_eq!(v, Ok(i)),
513                     recv(r2) -> v => assert_eq!(v, Ok(i)),
514                 }
515 
516                 s3.send(()).unwrap();
517             }
518         }
519     })
520     .unwrap();
521 }
522 
523 #[test]
stress_send()524 fn stress_send() {
525     #[cfg(miri)]
526     const COUNT: usize = 100;
527     #[cfg(not(miri))]
528     const COUNT: usize = 10_000;
529 
530     let (s1, r1) = bounded(0);
531     let (s2, r2) = bounded(0);
532     let (s3, r3) = bounded(100);
533 
534     scope(|scope| {
535         scope.spawn(|_| {
536             for i in 0..COUNT {
537                 assert_eq!(r1.recv().unwrap(), i);
538                 assert_eq!(r2.recv().unwrap(), i);
539                 r3.recv().unwrap();
540             }
541         });
542 
543         for i in 0..COUNT {
544             for _ in 0..2 {
545                 select! {
546                     send(s1, i) -> _ => {},
547                     send(s2, i) -> _ => {},
548                 }
549             }
550             s3.send(()).unwrap();
551         }
552     })
553     .unwrap();
554 }
555 
556 #[test]
stress_mixed()557 fn stress_mixed() {
558     #[cfg(miri)]
559     const COUNT: usize = 100;
560     #[cfg(not(miri))]
561     const COUNT: usize = 10_000;
562 
563     let (s1, r1) = bounded(0);
564     let (s2, r2) = bounded(0);
565     let (s3, r3) = bounded(100);
566 
567     scope(|scope| {
568         scope.spawn(|_| {
569             for i in 0..COUNT {
570                 s1.send(i).unwrap();
571                 assert_eq!(r2.recv().unwrap(), i);
572                 r3.recv().unwrap();
573             }
574         });
575 
576         for i in 0..COUNT {
577             for _ in 0..2 {
578                 select! {
579                     recv(r1) -> v => assert_eq!(v, Ok(i)),
580                     send(s2, i) -> _ => {},
581                 }
582             }
583             s3.send(()).unwrap();
584         }
585     })
586     .unwrap();
587 }
588 
589 #[test]
stress_timeout_two_threads()590 fn stress_timeout_two_threads() {
591     const COUNT: usize = 20;
592 
593     let (s, r) = bounded(2);
594 
595     scope(|scope| {
596         scope.spawn(|_| {
597             for i in 0..COUNT {
598                 if i % 2 == 0 {
599                     thread::sleep(ms(500));
600                 }
601 
602                 loop {
603                     select! {
604                         send(s, i) -> _ => break,
605                         default(ms(100)) => {}
606                     }
607                 }
608             }
609         });
610 
611         scope.spawn(|_| {
612             for i in 0..COUNT {
613                 if i % 2 == 0 {
614                     thread::sleep(ms(500));
615                 }
616 
617                 loop {
618                     select! {
619                         recv(r) -> v => {
620                             assert_eq!(v, Ok(i));
621                             break;
622                         }
623                         default(ms(100)) => {}
624                     }
625                 }
626             }
627         });
628     })
629     .unwrap();
630 }
631 
632 #[test]
send_recv_same_channel()633 fn send_recv_same_channel() {
634     let (s, r) = bounded::<i32>(0);
635     select! {
636         send(s, 0) -> _ => panic!(),
637         recv(r) -> _ => panic!(),
638         default(ms(500)) => {}
639     }
640 
641     let (s, r) = unbounded::<i32>();
642     select! {
643         send(s, 0) -> _ => {},
644         recv(r) -> _ => panic!(),
645         default(ms(500)) => panic!(),
646     }
647 }
648 
649 #[test]
matching()650 fn matching() {
651     const THREADS: usize = 44;
652 
653     let (s, r) = &bounded::<usize>(0);
654 
655     scope(|scope| {
656         for i in 0..THREADS {
657             scope.spawn(move |_| {
658                 select! {
659                     recv(r) -> v => assert_ne!(v.unwrap(), i),
660                     send(s, i) -> _ => {},
661                 }
662             });
663         }
664     })
665     .unwrap();
666 
667     assert_eq!(r.try_recv(), Err(TryRecvError::Empty));
668 }
669 
670 #[test]
matching_with_leftover()671 fn matching_with_leftover() {
672     const THREADS: usize = 55;
673 
674     let (s, r) = &bounded::<usize>(0);
675 
676     scope(|scope| {
677         for i in 0..THREADS {
678             scope.spawn(move |_| {
679                 select! {
680                     recv(r) -> v => assert_ne!(v.unwrap(), i),
681                     send(s, i) -> _ => {},
682                 }
683             });
684         }
685         s.send(!0).unwrap();
686     })
687     .unwrap();
688 
689     assert_eq!(r.try_recv(), Err(TryRecvError::Empty));
690 }
691 
692 #[test]
channel_through_channel()693 fn channel_through_channel() {
694     #[cfg(miri)]
695     const COUNT: usize = 100;
696     #[cfg(not(miri))]
697     const COUNT: usize = 1000;
698 
699     type T = Box<dyn Any + Send>;
700 
701     for cap in 0..3 {
702         let (s, r) = bounded::<T>(cap);
703 
704         scope(|scope| {
705             scope.spawn(move |_| {
706                 let mut s = s;
707 
708                 for _ in 0..COUNT {
709                     let (new_s, new_r) = bounded(cap);
710                     let new_r: T = Box::new(Some(new_r));
711 
712                     select! {
713                         send(s, new_r) -> _ => {}
714                     }
715 
716                     s = new_s;
717                 }
718             });
719 
720             scope.spawn(move |_| {
721                 let mut r = r;
722 
723                 for _ in 0..COUNT {
724                     r = select! {
725                         recv(r) -> msg => {
726                             msg.unwrap()
727                                 .downcast_mut::<Option<Receiver<T>>>()
728                                 .unwrap()
729                                 .take()
730                                 .unwrap()
731                         }
732                     }
733                 }
734             });
735         })
736         .unwrap();
737     }
738 }
739 
740 #[test]
linearizable_default()741 fn linearizable_default() {
742     #[cfg(miri)]
743     const COUNT: usize = 100;
744     #[cfg(not(miri))]
745     const COUNT: usize = 100_000;
746 
747     for step in 0..2 {
748         let (start_s, start_r) = bounded::<()>(0);
749         let (end_s, end_r) = bounded::<()>(0);
750 
751         let ((s1, r1), (s2, r2)) = if step == 0 {
752             (bounded::<i32>(1), bounded::<i32>(1))
753         } else {
754             (unbounded::<i32>(), unbounded::<i32>())
755         };
756 
757         scope(|scope| {
758             scope.spawn(|_| {
759                 for _ in 0..COUNT {
760                     start_s.send(()).unwrap();
761 
762                     s1.send(1).unwrap();
763                     select! {
764                         recv(r1) -> _ => {}
765                         recv(r2) -> _ => {}
766                         default => unreachable!()
767                     }
768 
769                     end_s.send(()).unwrap();
770                     let _ = r2.try_recv();
771                 }
772             });
773 
774             for _ in 0..COUNT {
775                 start_r.recv().unwrap();
776 
777                 s2.send(1).unwrap();
778                 let _ = r1.try_recv();
779 
780                 end_r.recv().unwrap();
781             }
782         })
783         .unwrap();
784     }
785 }
786 
787 #[test]
linearizable_timeout()788 fn linearizable_timeout() {
789     #[cfg(miri)]
790     const COUNT: usize = 100;
791     #[cfg(not(miri))]
792     const COUNT: usize = 100_000;
793 
794     for step in 0..2 {
795         let (start_s, start_r) = bounded::<()>(0);
796         let (end_s, end_r) = bounded::<()>(0);
797 
798         let ((s1, r1), (s2, r2)) = if step == 0 {
799             (bounded::<i32>(1), bounded::<i32>(1))
800         } else {
801             (unbounded::<i32>(), unbounded::<i32>())
802         };
803 
804         scope(|scope| {
805             scope.spawn(|_| {
806                 for _ in 0..COUNT {
807                     start_s.send(()).unwrap();
808 
809                     s1.send(1).unwrap();
810                     select! {
811                         recv(r1) -> _ => {}
812                         recv(r2) -> _ => {}
813                         default(ms(0)) => unreachable!()
814                     }
815 
816                     end_s.send(()).unwrap();
817                     let _ = r2.try_recv();
818                 }
819             });
820 
821             for _ in 0..COUNT {
822                 start_r.recv().unwrap();
823 
824                 s2.send(1).unwrap();
825                 let _ = r1.try_recv();
826 
827                 end_r.recv().unwrap();
828             }
829         })
830         .unwrap();
831     }
832 }
833 
834 #[test]
fairness1()835 fn fairness1() {
836     #[cfg(miri)]
837     const COUNT: usize = 100;
838     #[cfg(not(miri))]
839     const COUNT: usize = 10_000;
840 
841     let (s1, r1) = bounded::<()>(COUNT);
842     let (s2, r2) = unbounded::<()>();
843 
844     for _ in 0..COUNT {
845         s1.send(()).unwrap();
846         s2.send(()).unwrap();
847     }
848 
849     let mut hits = [0usize; 4];
850     for _ in 0..COUNT {
851         select! {
852             recv(r1) -> _ => hits[0] += 1,
853             recv(r2) -> _ => hits[1] += 1,
854             recv(after(ms(0))) -> _ => hits[2] += 1,
855             recv(tick(ms(0))) -> _ => hits[3] += 1,
856         }
857     }
858     assert!(hits.iter().all(|x| *x >= COUNT / hits.len() / 2));
859 }
860 
861 #[test]
fairness2()862 fn fairness2() {
863     #[cfg(miri)]
864     const COUNT: usize = 100;
865     #[cfg(not(miri))]
866     const COUNT: usize = 10_000;
867 
868     let (s1, r1) = unbounded::<()>();
869     let (s2, r2) = bounded::<()>(1);
870     let (s3, r3) = bounded::<()>(0);
871 
872     scope(|scope| {
873         scope.spawn(|_| {
874             let (hole, _r) = bounded(0);
875 
876             for _ in 0..COUNT {
877                 let s1 = if s1.is_empty() { &s1 } else { &hole };
878                 let s2 = if s2.is_empty() { &s2 } else { &hole };
879 
880                 select! {
881                     send(s1, ()) -> res => assert!(res.is_ok()),
882                     send(s2, ()) -> res => assert!(res.is_ok()),
883                     send(s3, ()) -> res => assert!(res.is_ok()),
884                 }
885             }
886         });
887 
888         let hits = vec![Cell::new(0usize); 3];
889         for _ in 0..COUNT {
890             select! {
891                 recv(r1) -> _ => hits[0].set(hits[0].get() + 1),
892                 recv(r2) -> _ => hits[1].set(hits[1].get() + 1),
893                 recv(r3) -> _ => hits[2].set(hits[2].get() + 1),
894             }
895         }
896         assert!(hits.iter().all(|x| x.get() >= COUNT / hits.len() / 50));
897     })
898     .unwrap();
899 }
900 
901 #[test]
fairness_recv()902 fn fairness_recv() {
903     #[cfg(miri)]
904     const COUNT: usize = 100;
905     #[cfg(not(miri))]
906     const COUNT: usize = 10_000;
907 
908     let (s1, r1) = bounded::<()>(COUNT);
909     let (s2, r2) = unbounded::<()>();
910 
911     for _ in 0..COUNT {
912         s1.send(()).unwrap();
913         s2.send(()).unwrap();
914     }
915 
916     let mut hits = [0usize; 2];
917     while hits[0] + hits[1] < COUNT {
918         select! {
919             recv(r1) -> _ => hits[0] += 1,
920             recv(r2) -> _ => hits[1] += 1,
921         }
922     }
923     assert!(hits.iter().all(|x| *x >= COUNT / 4));
924 }
925 
926 #[test]
fairness_send()927 fn fairness_send() {
928     #[cfg(miri)]
929     const COUNT: usize = 100;
930     #[cfg(not(miri))]
931     const COUNT: usize = 10_000;
932 
933     let (s1, _r1) = bounded::<()>(COUNT);
934     let (s2, _r2) = unbounded::<()>();
935 
936     let mut hits = [0usize; 2];
937     for _ in 0..COUNT {
938         select! {
939             send(s1, ()) -> _ => hits[0] += 1,
940             send(s2, ()) -> _ => hits[1] += 1,
941         }
942     }
943     assert!(hits.iter().all(|x| *x >= COUNT / 4));
944 }
945 
946 #[allow(clippy::or_fun_call)] // This is intentional.
947 #[test]
references()948 fn references() {
949     let (s, r) = unbounded::<i32>();
950     select! {
951         send(s, 0) -> _ => {}
952         recv(r) -> _ => {}
953     }
954     select! {
955         send(&&&&s, 0) -> _ => {}
956         recv(&&&&r) -> _ => {}
957     }
958     select! {
959         recv(Some(&r).unwrap_or(&never())) -> _ => {},
960         default => {}
961     }
962     select! {
963         recv(Some(r).unwrap_or(never())) -> _ => {},
964         default => {}
965     }
966 }
967 
968 #[test]
case_blocks()969 fn case_blocks() {
970     let (s, r) = unbounded::<i32>();
971 
972     select! {
973         recv(r) -> _ => 3.0,
974         recv(r) -> _ => loop {
975             unreachable!()
976         },
977         recv(r) -> _ => match 7 + 3 {
978             _ => unreachable!()
979         },
980         default => 7.
981     };
982 
983     select! {
984         recv(r) -> msg => if msg.is_ok() {
985             unreachable!()
986         },
987         default => ()
988     }
989 
990     drop(s);
991 }
992 
993 #[allow(clippy::redundant_closure_call)] // This is intentional.
994 #[test]
move_handles()995 fn move_handles() {
996     let (s, r) = unbounded::<i32>();
997     select! {
998         recv((move || r)()) -> _ => {}
999         send((move || s)(), 0) -> _ => {}
1000     }
1001 }
1002 
1003 #[test]
infer_types()1004 fn infer_types() {
1005     let (s, r) = unbounded();
1006     select! {
1007         recv(r) -> _ => {}
1008         default => {}
1009     }
1010     s.send(()).unwrap();
1011 
1012     let (s, r) = unbounded();
1013     select! {
1014         send(s, ()) -> _ => {}
1015     }
1016     r.recv().unwrap();
1017 }
1018 
1019 #[test]
default_syntax()1020 fn default_syntax() {
1021     let (s, r) = bounded::<i32>(0);
1022 
1023     select! {
1024         recv(r) -> _ => panic!(),
1025         default => {}
1026     }
1027     select! {
1028         send(s, 0) -> _ => panic!(),
1029         default() => {}
1030     }
1031     select! {
1032         default => {}
1033     }
1034     select! {
1035         default() => {}
1036     }
1037 }
1038 
1039 #[test]
same_variable_name()1040 fn same_variable_name() {
1041     let (_, r) = unbounded::<i32>();
1042     select! {
1043         recv(r) -> r => assert!(r.is_err()),
1044     }
1045 }
1046 
1047 #[test]
handles_on_heap()1048 fn handles_on_heap() {
1049     let (s, r) = unbounded::<i32>();
1050     let (s, r) = (Box::new(s), Box::new(r));
1051 
1052     select! {
1053         send(*s, 0) -> _ => {}
1054         recv(*r) -> _ => {}
1055         default => {}
1056     }
1057 
1058     drop(s);
1059     drop(r);
1060 }
1061 
1062 #[test]
once_blocks()1063 fn once_blocks() {
1064     let (s, r) = unbounded::<i32>();
1065 
1066     let once = Box::new(());
1067     select! {
1068         send(s, 0) -> _ => drop(once),
1069     }
1070 
1071     let once = Box::new(());
1072     select! {
1073         recv(r) -> _ => drop(once),
1074     }
1075 
1076     let once1 = Box::new(());
1077     let once2 = Box::new(());
1078     select! {
1079         send(s, 0) -> _ => drop(once1),
1080         default => drop(once2),
1081     }
1082 
1083     let once1 = Box::new(());
1084     let once2 = Box::new(());
1085     select! {
1086         recv(r) -> _ => drop(once1),
1087         default => drop(once2),
1088     }
1089 
1090     let once1 = Box::new(());
1091     let once2 = Box::new(());
1092     select! {
1093         recv(r) -> _ => drop(once1),
1094         send(s, 0) -> _ => drop(once2),
1095     }
1096 }
1097 
1098 #[test]
once_receiver()1099 fn once_receiver() {
1100     let (_, r) = unbounded::<i32>();
1101 
1102     let once = Box::new(());
1103     let get = move || {
1104         drop(once);
1105         r
1106     };
1107 
1108     select! {
1109         recv(get()) -> _ => {}
1110     }
1111 }
1112 
1113 #[test]
once_sender()1114 fn once_sender() {
1115     let (s, _) = unbounded::<i32>();
1116 
1117     let once = Box::new(());
1118     let get = move || {
1119         drop(once);
1120         s
1121     };
1122 
1123     select! {
1124         send(get(), 5) -> _ => {}
1125     }
1126 }
1127 
1128 #[test]
parse_nesting()1129 fn parse_nesting() {
1130     let (_, r) = unbounded::<i32>();
1131 
1132     select! {
1133         recv(r) -> _ => {}
1134         recv(r) -> _ => {
1135             select! {
1136                 recv(r) -> _ => {}
1137                 recv(r) -> _ => {
1138                     select! {
1139                         recv(r) -> _ => {}
1140                         recv(r) -> _ => {
1141                             select! {
1142                                 default => {}
1143                             }
1144                         }
1145                     }
1146                 }
1147             }
1148         }
1149     }
1150 }
1151 
1152 #[test]
evaluate()1153 fn evaluate() {
1154     let (s, r) = unbounded::<i32>();
1155 
1156     let v = select! {
1157         recv(r) -> _ => "foo".into(),
1158         send(s, 0) -> _ => "bar".to_owned(),
1159         default => "baz".to_string(),
1160     };
1161     assert_eq!(v, "bar");
1162 
1163     let v = select! {
1164         recv(r) -> _ => "foo".into(),
1165         default => "baz".to_string(),
1166     };
1167     assert_eq!(v, "foo");
1168 
1169     let v = select! {
1170         recv(r) -> _ => "foo".into(),
1171         default => "baz".to_string(),
1172     };
1173     assert_eq!(v, "baz");
1174 }
1175 
1176 #[test]
deref()1177 fn deref() {
1178     use crossbeam_channel as cc;
1179 
1180     struct Sender<T>(cc::Sender<T>);
1181     struct Receiver<T>(cc::Receiver<T>);
1182 
1183     impl<T> Deref for Receiver<T> {
1184         type Target = cc::Receiver<T>;
1185 
1186         fn deref(&self) -> &Self::Target {
1187             &self.0
1188         }
1189     }
1190 
1191     impl<T> Deref for Sender<T> {
1192         type Target = cc::Sender<T>;
1193 
1194         fn deref(&self) -> &Self::Target {
1195             &self.0
1196         }
1197     }
1198 
1199     let (s, r) = bounded::<i32>(0);
1200     let (s, r) = (Sender(s), Receiver(r));
1201 
1202     select! {
1203         send(s, 0) -> _ => panic!(),
1204         recv(r) -> _ => panic!(),
1205         default => {}
1206     }
1207 }
1208 
1209 #[test]
result_types()1210 fn result_types() {
1211     let (s, _) = bounded::<i32>(0);
1212     let (_, r) = bounded::<i32>(0);
1213 
1214     select! {
1215         recv(r) -> res => drop::<Result<i32, RecvError>>(res),
1216     }
1217     select! {
1218         recv(r) -> res => drop::<Result<i32, RecvError>>(res),
1219         default => {}
1220     }
1221     select! {
1222         recv(r) -> res => drop::<Result<i32, RecvError>>(res),
1223         default(ms(0)) => {}
1224     }
1225 
1226     select! {
1227         send(s, 0) -> res => drop::<Result<(), SendError<i32>>>(res),
1228     }
1229     select! {
1230         send(s, 0) -> res => drop::<Result<(), SendError<i32>>>(res),
1231         default => {}
1232     }
1233     select! {
1234         send(s, 0) -> res => drop::<Result<(), SendError<i32>>>(res),
1235         default(ms(0)) => {}
1236     }
1237 
1238     select! {
1239         send(s, 0) -> res => drop::<Result<(), SendError<i32>>>(res),
1240         recv(r) -> res => drop::<Result<i32, RecvError>>(res),
1241     }
1242 }
1243 
1244 #[test]
try_recv()1245 fn try_recv() {
1246     let (s, r) = bounded(0);
1247 
1248     scope(|scope| {
1249         scope.spawn(move |_| {
1250             select! {
1251                 recv(r) -> _ => panic!(),
1252                 default => {}
1253             }
1254             thread::sleep(ms(1500));
1255             select! {
1256                 recv(r) -> v => assert_eq!(v, Ok(7)),
1257                 default => panic!(),
1258             }
1259             thread::sleep(ms(500));
1260             select! {
1261                 recv(r) -> v => assert_eq!(v, Err(RecvError)),
1262                 default => panic!(),
1263             }
1264         });
1265         scope.spawn(move |_| {
1266             thread::sleep(ms(1000));
1267             select! {
1268                 send(s, 7) -> res => res.unwrap(),
1269             }
1270         });
1271     })
1272     .unwrap();
1273 }
1274 
1275 #[test]
recv()1276 fn recv() {
1277     let (s, r) = bounded(0);
1278 
1279     scope(|scope| {
1280         scope.spawn(move |_| {
1281             select! {
1282                 recv(r) -> v => assert_eq!(v, Ok(7)),
1283             }
1284             thread::sleep(ms(1000));
1285             select! {
1286                 recv(r) -> v => assert_eq!(v, Ok(8)),
1287             }
1288             thread::sleep(ms(1000));
1289             select! {
1290                 recv(r) -> v => assert_eq!(v, Ok(9)),
1291             }
1292             select! {
1293                 recv(r) -> v => assert_eq!(v, Err(RecvError)),
1294             }
1295         });
1296         scope.spawn(move |_| {
1297             thread::sleep(ms(1500));
1298             select! {
1299                 send(s, 7) -> res => res.unwrap(),
1300             }
1301             select! {
1302                 send(s, 8) -> res => res.unwrap(),
1303             }
1304             select! {
1305                 send(s, 9) -> res => res.unwrap(),
1306             }
1307         });
1308     })
1309     .unwrap();
1310 }
1311 
1312 #[test]
recv_timeout()1313 fn recv_timeout() {
1314     let (s, r) = bounded::<i32>(0);
1315 
1316     scope(|scope| {
1317         scope.spawn(move |_| {
1318             select! {
1319                 recv(r) -> _ => panic!(),
1320                 default(ms(1000)) => {}
1321             }
1322             select! {
1323                 recv(r) -> v => assert_eq!(v, Ok(7)),
1324                 default(ms(1000)) => panic!(),
1325             }
1326             select! {
1327                 recv(r) -> v => assert_eq!(v, Err(RecvError)),
1328                 default(ms(1000)) => panic!(),
1329             }
1330         });
1331         scope.spawn(move |_| {
1332             thread::sleep(ms(1500));
1333             select! {
1334                 send(s, 7) -> res => res.unwrap(),
1335             }
1336         });
1337     })
1338     .unwrap();
1339 }
1340 
1341 #[test]
try_send()1342 fn try_send() {
1343     let (s, r) = bounded(0);
1344 
1345     scope(|scope| {
1346         scope.spawn(move |_| {
1347             select! {
1348                 send(s, 7) -> _ => panic!(),
1349                 default => {}
1350             }
1351             thread::sleep(ms(1500));
1352             select! {
1353                 send(s, 8) -> res => res.unwrap(),
1354                 default => panic!(),
1355             }
1356             thread::sleep(ms(500));
1357             select! {
1358                 send(s, 8) -> res => assert_eq!(res, Err(SendError(8))),
1359                 default => panic!(),
1360             }
1361         });
1362         scope.spawn(move |_| {
1363             thread::sleep(ms(1000));
1364             select! {
1365                 recv(r) -> v => assert_eq!(v, Ok(8)),
1366             }
1367         });
1368     })
1369     .unwrap();
1370 }
1371 
1372 #[test]
send()1373 fn send() {
1374     let (s, r) = bounded(0);
1375 
1376     scope(|scope| {
1377         scope.spawn(move |_| {
1378             select! {
1379                 send(s, 7) -> res => res.unwrap(),
1380             }
1381             thread::sleep(ms(1000));
1382             select! {
1383                 send(s, 8) -> res => res.unwrap(),
1384             }
1385             thread::sleep(ms(1000));
1386             select! {
1387                 send(s, 9) -> res => res.unwrap(),
1388             }
1389         });
1390         scope.spawn(move |_| {
1391             thread::sleep(ms(1500));
1392             select! {
1393                 recv(r) -> v => assert_eq!(v, Ok(7)),
1394             }
1395             select! {
1396                 recv(r) -> v => assert_eq!(v, Ok(8)),
1397             }
1398             select! {
1399                 recv(r) -> v => assert_eq!(v, Ok(9)),
1400             }
1401         });
1402     })
1403     .unwrap();
1404 }
1405 
1406 #[test]
send_timeout()1407 fn send_timeout() {
1408     let (s, r) = bounded(0);
1409 
1410     scope(|scope| {
1411         scope.spawn(move |_| {
1412             select! {
1413                 send(s, 7) -> _ => panic!(),
1414                 default(ms(1000)) => {}
1415             }
1416             select! {
1417                 send(s, 8) -> res => res.unwrap(),
1418                 default(ms(1000)) => panic!(),
1419             }
1420             select! {
1421                 send(s, 9) -> res => assert_eq!(res, Err(SendError(9))),
1422                 default(ms(1000)) => panic!(),
1423             }
1424         });
1425         scope.spawn(move |_| {
1426             thread::sleep(ms(1500));
1427             select! {
1428                 recv(r) -> v => assert_eq!(v, Ok(8)),
1429             }
1430         });
1431     })
1432     .unwrap();
1433 }
1434 
1435 #[test]
disconnect_wakes_sender()1436 fn disconnect_wakes_sender() {
1437     let (s, r) = bounded(0);
1438 
1439     scope(|scope| {
1440         scope.spawn(move |_| {
1441             select! {
1442                 send(s, ()) -> res => assert_eq!(res, Err(SendError(()))),
1443             }
1444         });
1445         scope.spawn(move |_| {
1446             thread::sleep(ms(1000));
1447             drop(r);
1448         });
1449     })
1450     .unwrap();
1451 }
1452 
1453 #[test]
disconnect_wakes_receiver()1454 fn disconnect_wakes_receiver() {
1455     let (s, r) = bounded::<()>(0);
1456 
1457     scope(|scope| {
1458         scope.spawn(move |_| {
1459             select! {
1460                 recv(r) -> res => assert_eq!(res, Err(RecvError)),
1461             }
1462         });
1463         scope.spawn(move |_| {
1464             thread::sleep(ms(1000));
1465             drop(s);
1466         });
1467     })
1468     .unwrap();
1469 }
1470 
1471 #[test]
trailing_comma()1472 fn trailing_comma() {
1473     let (s, r) = unbounded::<usize>();
1474 
1475     select! {
1476         send(s, 1,) -> _ => {},
1477         recv(r,) -> _ => {},
1478         default(ms(1000),) => {},
1479     }
1480 }
1481