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