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 = "signal")]
15 
16 #[cfg(unix)]
17 mod linux_test {
18     use std::os::raw::c_int;
19     use std::sync::atomic::AtomicUsize;
20     use std::sync::atomic::Ordering::{Acquire, Release};
21     use std::sync::Arc;
22 
23     use ylong_runtime::futures::poll_fn;
24     use ylong_runtime::signal::{signal, SignalKind};
25 
26     /// SDV cases of `SignalKind` conversion.
27     ///
28     /// # Brief
29     /// 1. Check the trait `From<c_int>` for `SignalKind`.
30     /// 2. Check the trait `From<SignalKind>` for `c_int`.
31     /// 3. Check the method `from_raw` of `SignalKind`.
32     /// 4. Check the method `as_raw` of `SignalKind`.
33     #[test]
sdv_signal_from_and_into_c_int()34     fn sdv_signal_from_and_into_c_int() {
35         assert_eq!(SignalKind::from(1), SignalKind::hangup());
36         assert_eq!(c_int::from(SignalKind::hangup()), 1);
37         assert_eq!(SignalKind::from_raw(2), SignalKind::interrupt());
38         assert_eq!(SignalKind::interrupt().as_raw(), 2);
39     }
40 
41     /// SDV cases for signal `recv()`.
42     ///
43     /// # Brief
44     /// 1. Generate a counter to ensure that notifications are received every
45     ///    time listening.
46     /// 2. Spawns a task to loop and listen to a signal.
47     /// 3. Send notification signals in a loop until all waiting is completed.
48     #[test]
sdv_signal_recv_test()49     fn sdv_signal_recv_test() {
50         let handle = ylong_runtime::spawn(async move {
51             let mut stream = signal(SignalKind::alarm()).unwrap();
52             for _ in 0..10 {
53                 unsafe { libc::raise(libc::SIGALRM) };
54                 stream.recv().await;
55             }
56         });
57         let _ = ylong_runtime::block_on(handle);
58     }
59 
60     /// SDV cases for signal `recv()` in multi thread.
61     ///
62     /// # Brief
63     /// 1. Generate a counter to confirm that all signals are waiting.
64     /// 2. Spawns some tasks to listen to a signal.
65     /// 3. Send a notification signal when all signals are waiting.
66     #[test]
sdv_signal_recv_multi_thread_test()67     fn sdv_signal_recv_multi_thread_test() {
68         let num = Arc::new(AtomicUsize::new(0));
69         let mut handles = Vec::new();
70         for _ in 0..10 {
71             let num_clone = num.clone();
72             handles.push(ylong_runtime::spawn(async move {
73                 let mut stream = signal(SignalKind::child()).unwrap();
74                 num_clone.fetch_add(1, Release);
75                 stream.recv().await;
76             }));
77         }
78         while num.load(Acquire) < 10 {}
79         unsafe { libc::raise(libc::SIGCHLD) };
80         for handle in handles {
81             let _ = ylong_runtime::block_on(handle);
82         }
83     }
84 
85     /// SDV cases for signal `poll_recv()`.
86     ///
87     /// # Brief
88     /// 1. Generate a counter to ensure that notifications are received every
89     ///    time listening.
90     /// 2. Spawns a task to loop and listen to a signal.
91     /// 3. Send notification signals in a loop until all waiting is completed.
92     #[test]
sdv_signal_poll_recv_test()93     fn sdv_signal_poll_recv_test() {
94         let handle = ylong_runtime::spawn(async move {
95             let mut stream = signal(SignalKind::hangup()).unwrap();
96             for _ in 0..10 {
97                 unsafe { libc::raise(libc::SIGHUP) };
98                 poll_fn(|cx| stream.poll_recv(cx)).await;
99             }
100         });
101         let _ = ylong_runtime::block_on(handle);
102     }
103 
104     /// SDV cases for signal `poll_recv()` in multi thread.
105     ///
106     /// # Brief
107     /// 1. Generate a counter to confirm that all signals are waiting.
108     /// 2. Spawns some tasks to listen to a signal.
109     /// 3. Send a notification signal when all signals are waiting.
110     #[test]
sdv_signal_poll_recv_multi_thread_test()111     fn sdv_signal_poll_recv_multi_thread_test() {
112         let num = Arc::new(AtomicUsize::new(0));
113         let mut handles = Vec::new();
114         for _ in 0..10 {
115             let num_clone = num.clone();
116             handles.push(ylong_runtime::spawn(async move {
117                 let mut stream = signal(SignalKind::io()).unwrap();
118                 num_clone.fetch_add(1, Release);
119                 stream.recv().await;
120             }));
121         }
122         while num.load(Acquire) < 10 {}
123         unsafe { libc::raise(libc::SIGIO) };
124         for handle in handles {
125             let _ = ylong_runtime::block_on(handle);
126         }
127     }
128 
129     /// SDV cases for SIGALRM signal.
130     ///
131     /// # Brief
132     /// 1. Generate the SIGALRM signal.
133     /// 2. Check the function of `signal` for the SIGALRM signal.
134     #[test]
sdv_signal_alarm()135     fn sdv_signal_alarm() {
136         let handle = ylong_runtime::spawn(async move {
137             let mut signal = signal(SignalKind::alarm()).unwrap();
138             unsafe { libc::raise(libc::SIGALRM) };
139             signal.recv().await;
140         });
141         let _ = ylong_runtime::block_on(handle);
142     }
143 
144     /// SDV cases for SIGCHLD signal.
145     ///
146     /// # Brief
147     /// 1. Generate the SIGCHLD signal.
148     /// 2. Check the function of `signal` for the SIGCHLD signal.
149     #[test]
sdv_signal_child()150     fn sdv_signal_child() {
151         let handle = ylong_runtime::spawn(async move {
152             let mut signal = signal(SignalKind::child()).unwrap();
153             unsafe { libc::raise(libc::SIGCHLD) };
154             signal.recv().await;
155         });
156         let _ = ylong_runtime::block_on(handle);
157     }
158 
159     /// SDV cases for SIGHUP signal.
160     ///
161     /// # Brief
162     /// 1. Generate the SIGHUP signal.
163     /// 2. Check the function of `signal` for the SIGHUP signal.
164     #[test]
sdv_signal_hangup()165     fn sdv_signal_hangup() {
166         let handle = ylong_runtime::spawn(async move {
167             let mut signal = signal(SignalKind::hangup()).unwrap();
168             unsafe { libc::raise(libc::SIGHUP) };
169             signal.recv().await;
170         });
171         let _ = ylong_runtime::block_on(handle);
172     }
173 
174     /// SDV cases for SIGINT signal.
175     ///
176     /// # Brief
177     /// 1. Generate the SIGINT signal.
178     /// 2. Check the function of `signal` for the SIGINT signal.
179     #[test]
sdv_signal_interrupt()180     fn sdv_signal_interrupt() {
181         let handle = ylong_runtime::spawn(async move {
182             let mut signal = signal(SignalKind::interrupt()).unwrap();
183             unsafe { libc::raise(libc::SIGINT) };
184             signal.recv().await;
185         });
186         let _ = ylong_runtime::block_on(handle);
187     }
188 
189     /// SDV cases for SIGIO signal.
190     ///
191     /// # Brief
192     /// 1. Generate the SIGIO signal.
193     /// 2. Check the function of `signal` for the SIGIO signal.
194     #[test]
sdv_signal_io()195     fn sdv_signal_io() {
196         let handle = ylong_runtime::spawn(async move {
197             let mut signal = signal(SignalKind::io()).unwrap();
198             unsafe { libc::raise(libc::SIGIO) };
199             signal.recv().await;
200         });
201         let _ = ylong_runtime::block_on(handle);
202     }
203 
204     /// SDV cases for SIGPIPE signal.
205     ///
206     /// # Brief
207     /// 1. Generate the SIGPIPE signal.
208     /// 2. Check the function of `signal` for the SIGPIPE signal.
209     #[test]
sdv_signal_pipe()210     fn sdv_signal_pipe() {
211         let handle = ylong_runtime::spawn(async move {
212             let mut signal = signal(SignalKind::pipe()).unwrap();
213             unsafe { libc::raise(libc::SIGPIPE) };
214             signal.recv().await;
215         });
216         let _ = ylong_runtime::block_on(handle);
217     }
218 
219     /// SDV cases for SIGTERM signal.
220     ///
221     /// # Brief
222     /// 1. Generate the SIGTERM signal.
223     /// 2. Check the function of `signal` for the SIGTERM signal.
224     #[test]
sdv_signal_terminate()225     fn sdv_signal_terminate() {
226         let handle = ylong_runtime::spawn(async move {
227             let mut signal = signal(SignalKind::terminate()).unwrap();
228             unsafe { libc::raise(libc::SIGTERM) };
229             signal.recv().await;
230         });
231         let _ = ylong_runtime::block_on(handle);
232     }
233 
234     /// SDV cases for SIGUSR1 signal.
235     ///
236     /// # Brief
237     /// 1. Generate the SIGUSR1 signal.
238     /// 2. Check the function of `signal` for the SIGUSR1 signal.
239     #[test]
sdv_signal_user_defined1()240     fn sdv_signal_user_defined1() {
241         let handle = ylong_runtime::spawn(async move {
242             let mut signal = signal(SignalKind::user_defined1()).unwrap();
243             unsafe { libc::raise(libc::SIGUSR1) };
244             signal.recv().await;
245         });
246         let _ = ylong_runtime::block_on(handle);
247     }
248 
249     /// SDV cases for SIGUSR2 signal.
250     ///
251     /// # Brief
252     /// 1. Generate the SIGUSR2 signal.
253     /// 2. Check the function of `signal` for the SIGUSR2 signal.
254     #[test]
sdv_signal_user_defined2()255     fn sdv_signal_user_defined2() {
256         let handle = ylong_runtime::spawn(async move {
257             let mut signal = signal(SignalKind::user_defined2()).unwrap();
258             unsafe { libc::raise(libc::SIGUSR2) };
259             signal.recv().await;
260         });
261         let _ = ylong_runtime::block_on(handle);
262     }
263 
264     /// SDV cases for SIGWINCH signal.
265     ///
266     /// # Brief
267     /// 1. Generate the SIGWINCH signal.
268     /// 2. Check the function of `signal` for the SIGWINCH signal.
269     #[test]
sdv_signal_window_change()270     fn sdv_signal_window_change() {
271         let handle = ylong_runtime::spawn(async move {
272             let mut signal = signal(SignalKind::window_change()).unwrap();
273             unsafe { libc::raise(libc::SIGWINCH) };
274             signal.recv().await;
275         });
276         let _ = ylong_runtime::block_on(handle);
277     }
278 }
279