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