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