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