• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(all(feature = "time", feature = "sync"))]
15 
16 use std::future::Future;
17 use std::pin::Pin;
18 use std::task::{Context, Poll};
19 use std::time::{Duration, Instant};
20 
21 use ylong_runtime::time::{sleep, sleep_until, Sleep};
22 
download()23 async fn download() {
24     const TOTAL_SIZE: usize = 10 * 1024;
25     const RECV_SIZE: usize = 1024;
26 
27     let mut left = TOTAL_SIZE;
28     loop {
29         let recv = RECV_SIZE;
30         left -= recv;
31         if left == 0 {
32             break;
33         }
34         sleep(Duration::from_millis(50)).await;
35     }
36 }
37 
simulate()38 async fn simulate() {
39     let mut handles = Vec::new();
40 
41     for _ in 0..50 {
42         handles.push(ylong_runtime::spawn(async move {
43             download().await;
44         }));
45     }
46 
47     for handle in handles {
48         let _ = handle.await;
49     }
50 }
51 
52 /// SDV test cases for multi time create.
53 ///
54 /// # Brief
55 /// 1. Creates multi threads and multi timers.
56 /// 2. Checks if the test results are correct.
57 #[test]
sdv_multi_timer()58 fn sdv_multi_timer() {
59     ylong_runtime::block_on(simulate());
60 }
61 
62 /// SDV for dropping timer outside of worker context
63 ///
64 /// # Brief
65 /// 1. Creates a `Sleep` on the worker context
66 /// 2. Returns the sleep to the main thread which is not in the worker context
67 /// 3. Drops the timer in the main thread and it should not cause Panic
68 #[test]
69 #[allow(clippy::async_yields_async)]
sdv_sleep_drop_out_context()70 fn sdv_sleep_drop_out_context() {
71     let handle = ylong_runtime::spawn(async move { sleep_until(Instant::now()) });
72     let timer = ylong_runtime::block_on(handle).unwrap();
73     drop(timer);
74 }
75 
76 /// SDV case for calling `block_on` directly on a `timeout` operation
77 ///
78 /// # Brief
79 /// 1. Blocks on the async function that times out
80 /// 2. Checks if the returned value is Ok
81 #[test]
82 #[cfg(not(feature = "ffrt"))]
sdv_block_on_timeout()83 fn sdv_block_on_timeout() {
84     use ylong_runtime::time::timeout;
85 
86     let ret =
87         ylong_runtime::block_on(
88             async move { timeout(Duration::from_secs(2), async move { 1 }).await },
89         );
90     assert_eq!(ret, Ok(1))
91 }
92 
93 struct TimeFuture {
94     sleep: Option<Pin<Box<Sleep>>>,
95     count: u32,
96 }
97 
98 impl Future for TimeFuture {
99     type Output = u32;
100 
poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>101     fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
102         let this = self.get_mut();
103         if this.count < 5 {
104             this.sleep = Some(Box::pin(sleep(Duration::from_millis(50))));
105         }
106         if let Some(mut sleep) = this.sleep.take() {
107             if Pin::new(&mut sleep).poll(cx).is_pending() {
108                 this.count += 1;
109                 this.sleep = Some(sleep);
110                 return Poll::Pending;
111             }
112         }
113         Poll::Ready(0)
114     }
115 }
116 
117 /// SDV case for polling a sleep
118 ///
119 /// # Brief
120 /// 1. Create a future that would create a new sleep during every call to its
121 ///    `poll`
122 /// 2. Spawn and block_on the future, check if the returned value is correct
123 #[test]
sdv_sleep_poll()124 fn sdv_sleep_poll() {
125     let handle = ylong_runtime::spawn(async move {
126         for _ in 0..2 {
127             let future = TimeFuture {
128                 sleep: None,
129                 count: 0,
130             };
131             let ret = future.await;
132             assert_eq!(ret, 0);
133         }
134         1
135     });
136     let ret = ylong_runtime::block_on(handle).unwrap();
137     assert_eq!(ret, 1);
138 }
139