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