1 extern crate futures;
2 extern crate tokio_mock_task;
3 extern crate tokio_sync;
4
5 use tokio_mock_task::*;
6 use tokio_sync::semaphore::{Permit, Semaphore};
7
8 macro_rules! assert_ready {
9 ($e:expr) => {{
10 match $e {
11 Ok(futures::Async::Ready(v)) => v,
12 Ok(_) => panic!("not ready"),
13 Err(e) => panic!("error = {:?}", e),
14 }
15 }};
16 }
17
18 macro_rules! assert_not_ready {
19 ($e:expr) => {{
20 match $e {
21 Ok(futures::Async::NotReady) => {}
22 Ok(futures::Async::Ready(v)) => panic!("ready; value = {:?}", v),
23 Err(e) => panic!("error = {:?}", e),
24 }
25 }};
26 }
27
28 #[test]
available_permits()29 fn available_permits() {
30 let s = Semaphore::new(100);
31 assert_eq!(s.available_permits(), 100);
32
33 // Polling for a permit succeeds immediately
34 let mut permit = Permit::new();
35 assert!(!permit.is_acquired());
36
37 assert_ready!(permit.poll_acquire(&s));
38 assert_eq!(s.available_permits(), 99);
39 assert!(permit.is_acquired());
40
41 // Polling again on the same waiter does not claim a new permit
42 assert_ready!(permit.poll_acquire(&s));
43 assert_eq!(s.available_permits(), 99);
44 assert!(permit.is_acquired());
45 }
46
47 #[test]
unavailable_permits()48 fn unavailable_permits() {
49 let s = Semaphore::new(1);
50
51 let mut permit_1 = Permit::new();
52 let mut permit_2 = Permit::new();
53
54 // Acquire the first permit
55 assert_ready!(permit_1.poll_acquire(&s));
56 assert_eq!(s.available_permits(), 0);
57
58 let mut task = MockTask::new();
59
60 task.enter(|| {
61 // Try to acquire the second permit
62 assert_not_ready!(permit_2.poll_acquire(&s));
63 });
64
65 permit_1.release(&s);
66
67 assert_eq!(s.available_permits(), 0);
68 assert!(task.is_notified());
69 assert_ready!(permit_2.poll_acquire(&s));
70
71 permit_2.release(&s);
72 assert_eq!(s.available_permits(), 1);
73 }
74
75 #[test]
zero_permits()76 fn zero_permits() {
77 let s = Semaphore::new(0);
78 assert_eq!(s.available_permits(), 0);
79
80 let mut permit = Permit::new();
81 let mut task = MockTask::new();
82
83 // Try to acquire the permit
84 task.enter(|| {
85 assert_not_ready!(permit.poll_acquire(&s));
86 });
87
88 s.add_permits(1);
89
90 assert!(task.is_notified());
91 assert_ready!(permit.poll_acquire(&s));
92 }
93
94 #[test]
95 #[should_panic]
validates_max_permits()96 fn validates_max_permits() {
97 use std::usize;
98 Semaphore::new((usize::MAX >> 2) + 1);
99 }
100
101 #[test]
close_semaphore_prevents_acquire()102 fn close_semaphore_prevents_acquire() {
103 let s = Semaphore::new(1);
104 s.close();
105
106 assert_eq!(1, s.available_permits());
107
108 let mut permit = Permit::new();
109
110 assert!(permit.poll_acquire(&s).is_err());
111 assert_eq!(1, s.available_permits());
112 }
113
114 #[test]
close_semaphore_notifies_permit1()115 fn close_semaphore_notifies_permit1() {
116 let s = Semaphore::new(0);
117
118 let mut permit = Permit::new();
119 let mut task = MockTask::new();
120
121 task.enter(|| {
122 assert_not_ready!(permit.poll_acquire(&s));
123 });
124
125 s.close();
126
127 assert!(task.is_notified());
128 assert!(permit.poll_acquire(&s).is_err());
129 }
130
131 #[test]
close_semaphore_notifies_permit2()132 fn close_semaphore_notifies_permit2() {
133 let s = Semaphore::new(2);
134
135 let mut permit1 = Permit::new();
136 let mut permit2 = Permit::new();
137 let mut permit3 = Permit::new();
138 let mut permit4 = Permit::new();
139
140 // Acquire a couple of permits
141 assert_ready!(permit1.poll_acquire(&s));
142 assert_ready!(permit2.poll_acquire(&s));
143
144 let mut task1 = MockTask::new();
145 let mut task2 = MockTask::new();
146
147 task1.enter(|| {
148 assert_not_ready!(permit3.poll_acquire(&s));
149 });
150
151 task2.enter(|| {
152 assert_not_ready!(permit4.poll_acquire(&s));
153 });
154
155 s.close();
156
157 assert!(task1.is_notified());
158 assert!(task2.is_notified());
159
160 assert!(permit3.poll_acquire(&s).is_err());
161 assert!(permit4.poll_acquire(&s).is_err());
162
163 assert_eq!(0, s.available_permits());
164
165 permit1.release(&s);
166
167 assert_eq!(1, s.available_permits());
168
169 assert!(permit1.poll_acquire(&s).is_err());
170
171 permit2.release(&s);
172
173 assert_eq!(2, s.available_permits());
174 }
175