1 // Copyright (c) 2023 Huawei Device Co., Ltd.
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 //     http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13 
14 #![cfg(feature = "sync")]
15 
16 use std::future::Future;
17 use std::pin::Pin;
18 use std::sync::atomic::AtomicUsize;
19 use std::sync::atomic::Ordering::{Acquire, Release};
20 use std::sync::{Arc, Mutex};
21 use std::task::{Context, Poll};
22 use std::thread;
23 use std::thread::sleep;
24 use std::time::Duration;
25 
26 use ylong_runtime::sync::{Mutex as YlongMutex, RwLock, Waiter};
27 
28 const NUM: usize = 200;
29 
30 pub struct TestFuture {
31     value: usize,
32     total: usize,
33 }
34 
create_new(t: usize) -> TestFuture35 pub fn create_new(t: usize) -> TestFuture {
36     TestFuture { value: 0, total: t }
37 }
38 
39 impl Future for TestFuture {
40     type Output = usize;
poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>41     fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
42         if self.total > self.value {
43             self.get_mut().value += 1;
44             cx.waker().wake_by_ref();
45             Poll::Pending
46         } else {
47             Poll::Ready(self.total)
48         }
49     }
50 }
51 
test_future() -> usize52 async fn test_future() -> usize {
53     create_new(1000).await
54 }
55 
56 /// SDV test cases for `Mutex`.
57 ///
58 /// # Brief
59 /// 1. Create Runtime.
60 /// 2. Create a variable of Mutex.
61 /// 3. Executing an async task and change the variable.
62 /// 4. Check if the test results are correct.
63 #[test]
sdv_concurrency_with_mutex1()64 fn sdv_concurrency_with_mutex1() {
65     ylong_runtime::block_on(async {
66         let mutex1 = Arc::new(YlongMutex::new(0));
67         let mutex2 = mutex1.clone();
68         let mutex3 = mutex1.clone();
69         let mutex4 = mutex1.clone();
70         let mutex5 = mutex1.clone();
71 
72         ylong_runtime::spawn(async move {
73             let mut n = mutex1.lock().await;
74             *n += 1;
75             assert_eq!(1, *n);
76         })
77         .await
78         .unwrap();
79 
80         ylong_runtime::spawn(async move {
81             let mut n = mutex2.lock().await;
82             *n += 2;
83             assert_eq!(3, *n);
84         })
85         .await
86         .unwrap();
87 
88         ylong_runtime::spawn(async move {
89             let mut n = mutex3.lock().await;
90             *n += 3;
91             assert_eq!(6, *n);
92         })
93         .await
94         .unwrap();
95 
96         ylong_runtime::spawn(async move {
97             let mut n = mutex4.lock().await;
98             *n += 4;
99             assert_eq!(10, *n);
100         })
101         .await
102         .unwrap();
103 
104         ylong_runtime::spawn(async move {
105             let mut n = mutex5.lock().await;
106             *n += 5;
107             assert_eq!(15, *n);
108         })
109         .await
110         .unwrap();
111     });
112 }
113 
114 /// SDV test cases for `Mutex`.
115 ///
116 /// # Brief
117 /// 1. Create Runtime.
118 /// 2. Create a variable of Mutex.
119 /// 3. Executing an async task and change the variable for 100 times.
120 /// 4. Check if the test results are correct.
121 #[test]
sdv_concurrency_with_mutex2()122 fn sdv_concurrency_with_mutex2() {
123     ylong_runtime::block_on(async {
124         let mutex1 = Arc::new(YlongMutex::new(0));
125         for _ in 0..200 {
126             let mutex = mutex1.clone();
127             ylong_runtime::spawn(async move {
128                 let mut n = mutex.lock().await;
129                 *n += 1;
130             })
131             .await
132             .unwrap();
133         }
134         let mutex = mutex1.clone();
135         let n = mutex.lock().await;
136         assert_eq!(*n, 200);
137     });
138 }
139 
140 /// SDV test cases for `Mutex`.
141 ///
142 /// # Brief
143 /// 1. Create Runtime.
144 /// 2. Executing async tasks and Change the variable for 5 times
145 /// 3. Check if the test results are correct.
146 #[test]
sdv_concurrency_with_mutex3()147 fn sdv_concurrency_with_mutex3() {
148     ylong_runtime::block_on(async {
149         let mutex1 = Arc::new(YlongMutex::new(0));
150         for _ in 0..5 {
151             let m1 = mutex1.clone();
152             ylong_runtime::spawn(async move {
153                 let mut n = m1.lock().await;
154                 sleep(Duration::new(0, 400));
155                 *n += 1;
156             });
157         }
158 
159         sleep(Duration::new(0, 200));
160         loop {
161             if *mutex1.lock().await >= 5 {
162                 break;
163             }
164         }
165         let mutex = mutex1.clone();
166         let n = mutex.lock().await;
167         assert_eq!(*n, 5);
168     });
169 }
170 
171 /// SDV test cases for `Mutex`.
172 ///
173 /// # Brief
174 /// 1. Create Runtime.
175 /// 2. Executing an async task which contains an async task and locking
176 /// 3. Check if the test results are correct.
177 #[test]
sdv_concurrency_with_mutex4()178 fn sdv_concurrency_with_mutex4() {
179     let mutex1 = Arc::new(YlongMutex::new(0));
180     // If test_future().await and the lock operation are put together to form a
181     // future, there is a sequential relationship between the two futures,
182     let mut handlers1 = Vec::with_capacity(NUM);
183     let mut handlers2 = Vec::with_capacity(NUM);
184 
185     for _ in 0..200 {
186         let mutex = mutex1.clone();
187         handlers1.push(ylong_runtime::spawn(async move {
188             // test_future() and locking do not exist concurrently.
189             test_future().await;
190             let mut n = mutex.lock().await;
191             *n += 1;
192         }));
193     }
194 
195     for _ in 0..200 {
196         handlers2.push(ylong_runtime::spawn(
197             // test_future() and locking exist concurrently.
198             test_future(),
199         ));
200     }
201 
202     for handler in handlers1 {
203         let _ret = ylong_runtime::block_on(handler);
204     }
205 
206     for handler in handlers2 {
207         let _ret = ylong_runtime::block_on(handler);
208     }
209     ylong_runtime::block_on(async {
210         let mutex = mutex1.clone();
211         let n = mutex.lock().await;
212         assert_eq!(*n, 200);
213     });
214 }
215 
216 /// SDV test cases for RwLock.
217 ///
218 /// # Brief
219 /// 1. Create producer_lock.
220 /// 2. Write for 100000 times.
221 /// 3. Two read thread to read for 100000 times.
222 /// 4. Check if the test results are correct.
223 #[test]
sdv_rwlock_multi_threads()224 fn sdv_rwlock_multi_threads() {
225     // Put the counter initial value into a read/write lock encapsulated
226     // in an atomic reference to allow secure sharing.
227     let producer_lock = Arc::new(std::sync::RwLock::new(1));
228     // Create a clone for each thread
229     let consumer_id_lock = producer_lock.clone();
230     let consumer_square_lock = producer_lock.clone();
231     let producer_thread = thread::spawn(move || {
232         for _i in 0..100000 {
233             // The write() method blocks the thread until exclusive access is available.
234             if let Ok(mut write_guard) = producer_lock.write() {
235                 *write_guard += 1;
236             }
237         }
238     });
239 
240     let mutex = Arc::new(Mutex::new(0));
241     let mutex1 = mutex.clone();
242     let mutex2 = mutex.clone();
243     // read thread
244     let consumer_id_thread = thread::spawn(move || {
245         for _i in 0..100000 {
246             // The read() method blocks only when the producer_thread thread holds a lock
247             let guard = consumer_id_lock.read();
248             drop(guard);
249 
250             let mut n = mutex1.lock().unwrap();
251             *n += 1;
252         }
253     });
254 
255     // Another read thread
256     let consumer_square_thread = thread::spawn(move || {
257         for _i in 0..10000 {
258             let guard = consumer_square_lock.read();
259             drop(guard);
260             let mut n = mutex2.lock().unwrap();
261             *n += 1;
262         }
263     });
264     let _ = producer_thread.join();
265     let _ = consumer_id_thread.join();
266     let _ = consumer_square_thread.join();
267     assert_eq!(*mutex.lock().unwrap(), 110000);
268 }
269 
270 /// SDV test cases for RwLock read.
271 ///
272 /// # Brief
273 /// 1. Create a variable of Rwlock.
274 /// 2. Create Runtime.
275 /// 3. Executing an async task for 200 times.
276 /// 4. Check if the test results are correct.
277 #[test]
sdv_rwlock_with_read1()278 fn sdv_rwlock_with_read1() {
279     let rwlock = Arc::new(RwLock::new(5));
280     let mut future0_handlers = Vec::with_capacity(NUM);
281     let mut future1_handlers = Vec::with_capacity(NUM);
282 
283     for _ in 0..200 {
284         let rwlock = rwlock.clone();
285         future0_handlers.push(ylong_runtime::spawn(async move {
286             let n = rwlock.read().await;
287             assert_eq!(5, *n);
288         }));
289     }
290     for _ in 0..200 {
291         future1_handlers.push(ylong_runtime::spawn(test_future()));
292     }
293     for handler in future0_handlers {
294         let _ret = ylong_runtime::block_on(handler);
295     }
296     for handler in future1_handlers {
297         let _ret = ylong_runtime::block_on(handler);
298     }
299 }
300 
301 /// SDV test cases for read lock.
302 ///
303 /// # Brief
304 /// 1. Create a variable of Rwlock.
305 /// 2. Create Runtime.
306 /// 3. Read for 200 times.
307 /// 4. Check if the test results are correct.
308 #[test]
sdv_rwlock_with_read2()309 fn sdv_rwlock_with_read2() {
310     let rwlock = Arc::new(RwLock::new(5));
311     let mut handlers = Vec::with_capacity(NUM);
312 
313     for _ in 0..200 {
314         let rwlock = rwlock.clone();
315         handlers.push(ylong_runtime::spawn(async move {
316             let n = rwlock.read().await;
317             assert_eq!(5, *n);
318         }));
319     }
320     for handler in handlers {
321         ylong_runtime::block_on(handler).expect("block_on failed");
322     }
323 }
324 
325 /// SDV test cases for read-write lock.
326 ///
327 /// # Brief
328 /// 1. Create a variable of Rwlock.
329 /// 2. Create Runtime.
330 /// 3. Executing an async task.
331 /// 4. Read and write for 200 times.
332 /// 5. Check if the test results are correct.
333 #[test]
sdv_rwlock_read_and_write()334 fn sdv_rwlock_read_and_write() {
335     let rwlock = Arc::new(RwLock::new(5));
336     let mut future0_handlers = Vec::with_capacity(NUM);
337     let mut future1_handlers = Vec::with_capacity(NUM);
338     for _ in 0..200 {
339         let rwlock = rwlock.clone();
340         future0_handlers.push(ylong_runtime::spawn(async move {
341             let mut n = rwlock.write().await;
342             *n += 1;
343         }));
344     }
345     for _ in 0..200 {
346         let rwlock = rwlock.clone();
347         future0_handlers.push(ylong_runtime::spawn(async move {
348             let _n = rwlock.read().await;
349         }));
350     }
351     for _ in 0..200 {
352         future1_handlers.push(ylong_runtime::spawn(test_future()));
353     }
354     for handler in future0_handlers {
355         ylong_runtime::block_on(handler).expect("block_on failed");
356     }
357     for handler in future1_handlers {
358         let _ret = ylong_runtime::block_on(handler).expect("block_on failed");
359     }
360     ylong_runtime::block_on(async {
361         let mutex = rwlock.clone();
362         let n = mutex.read().await;
363         assert_eq!(*n, 205);
364     });
365 }
366 
367 /// SDV test cases for Rwlock.
368 ///
369 /// # Brief
370 /// 1. Create a variable of Rwlock.
371 /// 2. Create Runtime.
372 /// 3. Write and execute another task for 200 times.
373 /// 4. Check if the test results are correct.
374 #[test]
sdv_rwlock_with_write1()375 fn sdv_rwlock_with_write1() {
376     let rwlock = Arc::new(RwLock::new(5));
377     let mut future0_handlers = Vec::with_capacity(NUM);
378     let mut future1_handlers = Vec::with_capacity(NUM);
379 
380     for _ in 0..200 {
381         let rwlock = rwlock.clone();
382         future0_handlers.push(ylong_runtime::spawn(async move {
383             let mut n = rwlock.write().await;
384             *n += 1;
385         }));
386     }
387     for _ in 0..200 {
388         future1_handlers.push(ylong_runtime::spawn(test_future()));
389     }
390     for handler in future0_handlers {
391         let _ret = ylong_runtime::block_on(handler);
392     }
393     for handler in future1_handlers {
394         let _ret = ylong_runtime::block_on(handler);
395     }
396     ylong_runtime::block_on(async {
397         let mutex = rwlock.clone();
398         let n = mutex.read().await;
399         assert_eq!(*n, 205);
400     });
401 }
402 
403 /// SDV test cases for Rwlock.
404 ///
405 /// # Brief
406 /// 1. Create a variable of Rwlock.
407 /// 2. Create Runtime.
408 /// 3. Write for 200 times.
409 /// 4. Check if the test results are correct.
410 #[test]
sdv_rwlock_with_write2()411 fn sdv_rwlock_with_write2() {
412     let rwlock = Arc::new(RwLock::new(5));
413     let mut handlers = Vec::with_capacity(NUM);
414 
415     for _ in 0..200 {
416         let rwlock = rwlock.clone();
417         handlers.push(ylong_runtime::spawn(async move {
418             let mut n = rwlock.write().await;
419             *n += 1;
420         }));
421     }
422     for handler in handlers {
423         ylong_runtime::block_on(handler).expect("block_on failed");
424     }
425     ylong_runtime::block_on(async {
426         let mutex = rwlock.clone();
427         let n = mutex.read().await;
428         assert_eq!(*n, 205);
429     });
430 }
431 
432 /// SDV test cases for `Waiter::wake_one()`.
433 ///
434 /// # Brief
435 /// 1. Call `wake_one` before a task calling `wait`.
436 /// 2. Call `wake_one` after a task calling `wait`.
437 #[test]
sdv_waiter_with_wake_one()438 fn sdv_waiter_with_wake_one() {
439     let waiter = Arc::new(Waiter::new());
440     let waiter2 = waiter.clone();
441     let waiter3 = waiter.clone();
442     let waiter4 = waiter.clone();
443 
444     let handle = ylong_runtime::spawn(async move {
445         waiter.wake_one();
446         waiter2.wait().await;
447     });
448 
449     let _ = ylong_runtime::block_on(handle);
450 
451     let handle2 = ylong_runtime::spawn(async move {
452         waiter3.wait().await;
453     });
454 
455     let handle3 = ylong_runtime::spawn(async move {
456         waiter4.wake_one();
457     });
458 
459     let _ = ylong_runtime::block_on(handle2);
460     let _ = ylong_runtime::block_on(handle3);
461 }
462 
463 /// SDV test cases for `Waiter::wake_all()`.
464 ///
465 /// # Brief
466 /// 1. Call `wake_all` after some tasks calling `wait`.
467 #[test]
sdv_waiter_with_wake_all()468 fn sdv_waiter_with_wake_all() {
469     let waiter = Arc::new(Waiter::new());
470 
471     let num = Arc::new(AtomicUsize::new(0));
472 
473     for _ in 0..1000 {
474         let waiter3 = waiter.clone();
475         let num3 = num.clone();
476         ylong_runtime::spawn(async move {
477             waiter3.wait().await;
478             num3.fetch_add(1, Release);
479         });
480     }
481 
482     while num.load(Acquire) < 1000 {
483         waiter.wake_all();
484     }
485 }
486