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 = "time")]
15
16 use std::future::Future;
17 use std::pin::Pin;
18 use std::task::{Context, Poll};
19 use std::time::Duration;
20
21 use ylong_runtime::error::ErrorKind;
22 use ylong_runtime::time::sleep;
23
24 /// SDV test cases for canceling a task.
25 ///
26 /// # Brief
27 /// 1. Configure the RuntimeBuilder and start the runtime
28 /// 2. Spawn a task that takes 100 seconds
29 /// 3. Cancel the task after the task returns pending
30 /// 4. Await on the canceled task
31 /// 5. Check return value
32 #[test]
sdv_task_cancel_simple()33 fn sdv_task_cancel_simple() {
34 let handle = ylong_runtime::spawn(async move {
35 let task = ylong_runtime::spawn(async move {
36 sleep(Duration::from_secs(100)).await;
37 });
38 sleep(Duration::from_millis(100)).await;
39 task.cancel();
40 let res = task.await.err().unwrap();
41 assert_eq!(res.kind(), ErrorKind::TaskCanceled);
42 });
43 ylong_runtime::block_on(handle).unwrap();
44 }
45
46 /// SDV test cases for canceling a task after its finished
47 ///
48 /// # Brief
49 /// 1. Configure the RuntimeBuilder and start the runtime
50 /// 2. Spawn a task that returns 1 immediately
51 /// 3. Cancel the task after the task is finished
52 /// 4. Await on the canceled task
53 /// 5. Check return value
54 #[test]
sdv_task_cancel_failed()55 fn sdv_task_cancel_failed() {
56 let handle = ylong_runtime::spawn(async move {
57 let task = ylong_runtime::spawn(async move { 1 });
58 sleep(Duration::from_millis(100)).await;
59 task.cancel();
60 let res = task.await.unwrap();
61 assert_eq!(res, 1);
62 });
63 ylong_runtime::block_on(handle).unwrap();
64 }
65
66 #[derive(Default)]
67 struct TestFuture {
68 flag: usize,
69 }
70
71 impl Future for TestFuture {
72 type Output = u8;
73
poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>74 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
75 let this = self.get_mut();
76 if this.flag < 1000000 {
77 this.flag += 1;
78 cx.waker().wake_by_ref();
79 Poll::Pending
80 } else {
81 Poll::Ready(1)
82 }
83 }
84 }
85
86 /// SDV test cases for multi cancel.
87 ///
88 /// # Brief
89 /// 1. In a loop, create a long-time task and then cancel it.
90 /// 2. Check if the task has been canceled for each run
91 #[test]
sdv_task_cancel_multiple()92 fn sdv_task_cancel_multiple() {
93 for _ in 0..1000 {
94 ylong_runtime::block_on(async move {
95 let handle = ylong_runtime::spawn(async move {
96 TestFuture::default().await;
97 sleep(Duration::from_secs(1000000));
98 1
99 });
100 handle.cancel();
101 let res = handle.await;
102 assert!(res.is_err());
103 })
104 }
105 }
106