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