1#![cfg(feature = "sync")]
2
3#[cfg(all(target_family = "wasm", not(target_os = "wasi")))]
4use wasm_bindgen_test::wasm_bindgen_test as test;
5
6use std::sync::Arc;
7use tokio::sync::Semaphore;
8
9#[test]
10fn no_permits() {
11 // this should not panic
12 Semaphore::new(0);
13}
14
15#[test]
16fn 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")]
30async 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")]
43async 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]
54fn 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]
67fn 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]
83fn 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#[tokio::test]
92#[cfg(feature = "full")]
93async fn stress_test() {
94 let sem = Arc::new(Semaphore::new(5));
95 let mut join_handles = Vec::new();
96 for _ in 0..1000 {
97 let sem_clone = sem.clone();
98 join_handles.push(tokio::spawn(async move {
99 let _p = sem_clone.acquire().await;
100 }));
101 }
102 for j in join_handles {
103 j.await.unwrap();
104 }
105 // there should be exactly 5 semaphores available now
106 let _p1 = sem.try_acquire().unwrap();
107 let _p2 = sem.try_acquire().unwrap();
108 let _p3 = sem.try_acquire().unwrap();
109 let _p4 = sem.try_acquire().unwrap();
110 let _p5 = sem.try_acquire().unwrap();
111 assert!(sem.try_acquire().is_err());
112}
113
114#[test]
115fn add_max_amount_permits() {
116 let s = tokio::sync::Semaphore::new(0);
117 s.add_permits(tokio::sync::Semaphore::MAX_PERMITS);
118 assert_eq!(s.available_permits(), tokio::sync::Semaphore::MAX_PERMITS);
119}
120
121#[cfg(not(target_family = "wasm"))] // wasm currently doesn't support unwinding
122#[test]
123#[should_panic]
124fn add_more_than_max_amount_permits1() {
125 let s = tokio::sync::Semaphore::new(1);
126 s.add_permits(tokio::sync::Semaphore::MAX_PERMITS);
127}
128
129#[cfg(not(target_family = "wasm"))] // wasm currently doesn't support unwinding
130#[test]
131#[should_panic]
132fn add_more_than_max_amount_permits2() {
133 let s = Semaphore::new(Semaphore::MAX_PERMITS - 1);
134 s.add_permits(1);
135 s.add_permits(1);
136}
137
138#[cfg(not(target_family = "wasm"))] // wasm currently doesn't support unwinding
139#[test]
140#[should_panic]
141fn panic_when_exceeds_maxpermits() {
142 let _ = Semaphore::new(Semaphore::MAX_PERMITS + 1);
143}
144
145#[test]
146fn no_panic_at_maxpermits() {
147 let _ = Semaphore::new(Semaphore::MAX_PERMITS);
148 let s = Semaphore::new(Semaphore::MAX_PERMITS - 1);
149 s.add_permits(1);
150}
151