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 = "macros")]
15 
16 /// SDV test cases for select! basic usage case
17 ///
18 /// # Brief
19 /// 1. Uses select! to run three async task.
20 /// 2. Uses if to disabled do_async1() and do_async3().
21 /// 3. Only the do_async2() task will be completely first.
22 #[test]
sdv_new_select_basicnull23 fn sdv_new_select_basic() {
24     async fn do_async1() -> i32 {
25         1
26     }
27 
28     async fn do_async2() -> i32 {
29         2
30     }
31 
32     async fn do_async3() -> bool {
33         false
34     }
35 
36     let handle = ylong_runtime::spawn(async {
37         let mut count = 0;
38         ylong_runtime::select! {
39             a = do_async1(), if false => {
40                 count += a;
41             },
42             b = do_async2() => {
43                 count += b;
44             },
45             c = do_async3(), if false => {
46                 if c {
47                     count = 3;
48                 }
49                 else {
50                     count = 4;
51                 }
52             }
53         }
54         assert_eq!(count, 2);
55     });
56     ylong_runtime::block_on(handle).expect("select! fail");
57 }
58 
59 /// SDV test cases for select! oneshot::channel usage
60 ///
61 /// # Brief
62 /// 1. Creates two oneshot::channel and send message.
63 /// 2. Repeated uses select! until both channel return.
64 /// 3. Checks whether the returned information of the two channels is correct.
65 #[test]
66 #[cfg(feature = "sync")]
sdv_new_select_channelnull67 fn sdv_new_select_channel() {
68     let handle = ylong_runtime::spawn(async {
69         let (tx1, mut rx1) = ylong_runtime::sync::oneshot::channel();
70         let (tx2, mut rx2) = ylong_runtime::sync::oneshot::channel();
71 
72         ylong_runtime::spawn(async move {
73             tx1.send("first").unwrap();
74         });
75 
76         ylong_runtime::spawn(async move {
77             tx2.send("second").unwrap();
78         });
79 
80         let mut a = None;
81         let mut b = None;
82 
83         while a.is_none() || b.is_none() {
84             ylong_runtime::select! {
85                 v1 = (&mut rx1), if a.is_none() => a = Some(v1.unwrap()),
86                 v2 = (&mut rx2), if b.is_none() => b = Some(v2.unwrap()),
87             }
88         }
89 
90         let res = (a.unwrap(), b.unwrap());
91 
92         assert_eq!(res.0, "first");
93         assert_eq!(res.1, "second");
94     });
95     ylong_runtime::block_on(handle).expect("select! fail");
96 }
97 
98 /// SDV test cases for select! 'biased' usage
99 ///
100 /// # Brief
101 /// 1. Uses 'biased' to execute four task in the specified sequence.
102 /// 2. Checks whether the 'count' is correct.
103 #[test]
sdv_new_select_biasednull104 fn sdv_new_select_biased() {
105     let handle = ylong_runtime::spawn(async {
106         let mut count = 0u8;
107 
108         loop {
109             ylong_runtime::select! {
110                 biased;
111                 _ = async {}, if count < 1 => {
112                     count += 1;
113                     assert_eq!(count, 1);
114                 }
115                 _ = async {}, if count < 2 => {
116                     count += 1;
117                     assert_eq!(count, 2);
118                 }
119                 _ = async {}, if count < 3 => {
120                     count += 1;
121                     assert_eq!(count, 3);
122                 }
123                 _ = async {}, if count < 4 => {
124                     count += 1;
125                     assert_eq!(count, 4);
126                 }
127                 else => {
128                     break;
129                 }
130             }
131         }
132 
133         assert_eq!(count, 4);
134     });
135     ylong_runtime::block_on(handle).expect("select! fail");
136 }
137 
138 /// SDV test cases for select! match usage
139 ///
140 /// # Brief
141 /// 1. Uses select! to run three async task.
142 /// 2. do_async2() and do_async3() will never match success.
143 /// 3. Only the do_async1() task will be completely.
144 #[test]
sdv_new_select_matchnull145 fn sdv_new_select_match() {
146     async fn do_async1() -> i32 {
147         1
148     }
149 
150     async fn do_async2() -> Option<i32> {
151         Some(2)
152     }
153 
154     async fn do_async3() -> Option<bool> {
155         None
156     }
157 
158     let handle = ylong_runtime::spawn(async {
159         let mut count = 0;
160         ylong_runtime::select! {
161             a = do_async1() => {
162                 count += a;
163             },
164             None = do_async2() => {
165                 count += 2;
166             },
167             Some(c) = do_async3() => {
168                 if c {
169                     count = 3;
170                 }
171                 else {
172                     count = 4;
173                 }
174             }
175         }
176         assert_eq!(count, 1);
177     });
178     ylong_runtime::block_on(handle).expect("select! fail");
179 }
180 
181 /// SDV test cases for select! precondition usage
182 ///
183 /// # Brief
184 /// 1. Creates a struct and implement a call to the `&mut self` async fn.
185 /// 2. Uses select! to run the async fn, and sets the precondition to the struct
186 ///    member variable.
187 /// 3. The select! will be successfully executed.
188 #[test]
sdv_new_select_preconditionnull189 fn sdv_new_select_precondition() {
190     struct TestStruct {
191         bool: bool,
192     }
193     impl TestStruct {
194         async fn do_async(&mut self) {}
195     }
196 
197     let handle = ylong_runtime::spawn(async {
198         let mut count = 0;
199         let mut test_struct = TestStruct { bool: true };
200         ylong_runtime::select! {
201             _ = test_struct.do_async(), if test_struct.bool => {
202                 count += 1;
203             },
204         }
205         assert_eq!(count, 1);
206     });
207     ylong_runtime::block_on(handle).expect("select! fail");
208 }
209 
210 /// SDV test cases for select! panic! usage
211 ///
212 /// # Brief
213 /// 1. Uses select! to run two async task with `if false`.
214 /// 2. All branches will be disabled and select! will be panic!
215 #[test]
216 #[should_panic]
sdv_new_select_panicnull217 fn sdv_new_select_panic() {
218     async fn do_async1() {}
219 
220     async fn do_async2() {}
221 
222     let handle = ylong_runtime::spawn(async {
223         ylong_runtime::select! {
224             _ = do_async1(), if false => {},
225             _ = do_async2(), if false => {}
226         }
227     });
228     ylong_runtime::block_on(handle).expect("select! fail");
229 }
230