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