1 #![cfg(feature = "sync")]
2 
3 #[cfg(all(target_family = "wasm", not(target_os = "wasi")))]
4 use wasm_bindgen_test::wasm_bindgen_test as test;
5 
6 use std::sync::Arc;
7 use tokio::sync::Semaphore;
8 
9 #[test]
no_permits()10 fn no_permits() {
11     // this should not panic
12     Semaphore::new(0);
13 }
14 
15 #[test]
try_acquire()16 fn try_acquire() {
17     let sem = Semaphore::new(1);
18     {
19         let p1 = sem.try_acquire();
20         assert!(p1.is_ok());
21         let p2 = sem.try_acquire();
22         assert!(p2.is_err());
23     }
24     let p3 = sem.try_acquire();
25     assert!(p3.is_ok());
26 }
27 
28 #[tokio::test]
29 #[cfg(feature = "full")]
acquire()30 async fn acquire() {
31     let sem = Arc::new(Semaphore::new(1));
32     let p1 = sem.try_acquire().unwrap();
33     let sem_clone = sem.clone();
34     let j = tokio::spawn(async move {
35         let _p2 = sem_clone.acquire().await;
36     });
37     drop(p1);
38     j.await.unwrap();
39 }
40 
41 #[tokio::test]
42 #[cfg(feature = "full")]
add_permits()43 async fn add_permits() {
44     let sem = Arc::new(Semaphore::new(0));
45     let sem_clone = sem.clone();
46     let j = tokio::spawn(async move {
47         let _p2 = sem_clone.acquire().await;
48     });
49     sem.add_permits(1);
50     j.await.unwrap();
51 }
52 
53 #[test]
forget()54 fn forget() {
55     let sem = Arc::new(Semaphore::new(1));
56     {
57         let p = sem.try_acquire().unwrap();
58         assert_eq!(sem.available_permits(), 0);
59         p.forget();
60         assert_eq!(sem.available_permits(), 0);
61     }
62     assert_eq!(sem.available_permits(), 0);
63     assert!(sem.try_acquire().is_err());
64 }
65 
66 #[test]
merge()67 fn merge() {
68     let sem = Arc::new(Semaphore::new(3));
69     {
70         let mut p1 = sem.try_acquire().unwrap();
71         assert_eq!(sem.available_permits(), 2);
72         let p2 = sem.try_acquire_many(2).unwrap();
73         assert_eq!(sem.available_permits(), 0);
74         p1.merge(p2);
75         assert_eq!(sem.available_permits(), 0);
76     }
77     assert_eq!(sem.available_permits(), 3);
78 }
79 
80 #[test]
81 #[cfg(not(target_family = "wasm"))] // No stack unwinding on wasm targets
82 #[should_panic]
merge_unrelated_permits()83 fn merge_unrelated_permits() {
84     let sem1 = Arc::new(Semaphore::new(3));
85     let sem2 = Arc::new(Semaphore::new(3));
86     let mut p1 = sem1.try_acquire().unwrap();
87     let p2 = sem2.try_acquire().unwrap();
88     p1.merge(p2);
89 }
90 
91 #[test]
split()92 fn split() {
93     let sem = Semaphore::new(5);
94     let mut p1 = sem.try_acquire_many(3).unwrap();
95     assert_eq!(sem.available_permits(), 2);
96     assert_eq!(p1.num_permits(), 3);
97     let mut p2 = p1.split(1).unwrap();
98     assert_eq!(sem.available_permits(), 2);
99     assert_eq!(p1.num_permits(), 2);
100     assert_eq!(p2.num_permits(), 1);
101     let p3 = p1.split(0).unwrap();
102     assert_eq!(p3.num_permits(), 0);
103     drop(p1);
104     assert_eq!(sem.available_permits(), 4);
105     let p4 = p2.split(1).unwrap();
106     assert_eq!(p2.num_permits(), 0);
107     assert_eq!(p4.num_permits(), 1);
108     assert!(p2.split(1).is_none());
109     drop(p2);
110     assert_eq!(sem.available_permits(), 4);
111     drop(p3);
112     assert_eq!(sem.available_permits(), 4);
113     drop(p4);
114     assert_eq!(sem.available_permits(), 5);
115 }
116 
117 #[tokio::test]
118 #[cfg(feature = "full")]
stress_test()119 async fn stress_test() {
120     let sem = Arc::new(Semaphore::new(5));
121     let mut join_handles = Vec::new();
122     for _ in 0..1000 {
123         let sem_clone = sem.clone();
124         join_handles.push(tokio::spawn(async move {
125             let _p = sem_clone.acquire().await;
126         }));
127     }
128     for j in join_handles {
129         j.await.unwrap();
130     }
131     // there should be exactly 5 semaphores available now
132     let _p1 = sem.try_acquire().unwrap();
133     let _p2 = sem.try_acquire().unwrap();
134     let _p3 = sem.try_acquire().unwrap();
135     let _p4 = sem.try_acquire().unwrap();
136     let _p5 = sem.try_acquire().unwrap();
137     assert!(sem.try_acquire().is_err());
138 }
139 
140 #[test]
add_max_amount_permits()141 fn add_max_amount_permits() {
142     let s = tokio::sync::Semaphore::new(0);
143     s.add_permits(tokio::sync::Semaphore::MAX_PERMITS);
144     assert_eq!(s.available_permits(), tokio::sync::Semaphore::MAX_PERMITS);
145 }
146 
147 #[cfg(not(target_family = "wasm"))] // wasm currently doesn't support unwinding
148 #[test]
149 #[should_panic]
add_more_than_max_amount_permits1()150 fn add_more_than_max_amount_permits1() {
151     let s = tokio::sync::Semaphore::new(1);
152     s.add_permits(tokio::sync::Semaphore::MAX_PERMITS);
153 }
154 
155 #[cfg(not(target_family = "wasm"))] // wasm currently doesn't support unwinding
156 #[test]
157 #[should_panic]
add_more_than_max_amount_permits2()158 fn add_more_than_max_amount_permits2() {
159     let s = Semaphore::new(Semaphore::MAX_PERMITS - 1);
160     s.add_permits(1);
161     s.add_permits(1);
162 }
163 
164 #[cfg(not(target_family = "wasm"))] // wasm currently doesn't support unwinding
165 #[test]
166 #[should_panic]
panic_when_exceeds_maxpermits()167 fn panic_when_exceeds_maxpermits() {
168     let _ = Semaphore::new(Semaphore::MAX_PERMITS + 1);
169 }
170 
171 #[test]
no_panic_at_maxpermits()172 fn no_panic_at_maxpermits() {
173     let _ = Semaphore::new(Semaphore::MAX_PERMITS);
174     let s = Semaphore::new(Semaphore::MAX_PERMITS - 1);
175     s.add_permits(1);
176 }
177