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_ciuse std::io; 15cac7dca0Sopenharmony_ciuse std::mem::MaybeUninit; 16cac7dca0Sopenharmony_ciuse std::os::raw::c_int; 17cac7dca0Sopenharmony_ciuse std::sync::atomic::{AtomicUsize, Ordering}; 18cac7dca0Sopenharmony_ciuse std::sync::{Arc, Once}; 19cac7dca0Sopenharmony_ci 20cac7dca0Sopenharmony_ci/// SDV test cases 21cac7dca0Sopenharmony_ci/// 22cac7dca0Sopenharmony_ci/// Because the following tests cannot be executed in parallel for 23cac7dca0Sopenharmony_ci/// there are only a few signals in windows that we have to use the same signal 24cac7dca0Sopenharmony_ci/// in different test case, so there is a test all case which execute all tests 25cac7dca0Sopenharmony_ci/// serially. 26cac7dca0Sopenharmony_ci#[test] 27cac7dca0Sopenharmony_cifn sdv_test_all() { 28cac7dca0Sopenharmony_ci sdv_signal_register_succeed(); 29cac7dca0Sopenharmony_ci sdv_signal_register_failed(); 30cac7dca0Sopenharmony_ci sdv_signal_register_with_old(); 31cac7dca0Sopenharmony_ci #[cfg(not(windows))] 32cac7dca0Sopenharmony_ci sdv_signal_register_multi(); 33cac7dca0Sopenharmony_ci} 34cac7dca0Sopenharmony_ci 35cac7dca0Sopenharmony_ci/// SDV cases for signal register 36cac7dca0Sopenharmony_ci/// 37cac7dca0Sopenharmony_ci/// # Brief 38cac7dca0Sopenharmony_ci/// 1. Registers two different signals with actions that increment two different 39cac7dca0Sopenharmony_ci/// atomic usize. 40cac7dca0Sopenharmony_ci/// 2. Manually raises the two signals, checks if the registered action behave 41cac7dca0Sopenharmony_ci/// correctly. 42cac7dca0Sopenharmony_ci/// 3. Deregisters the action of the two signals 43cac7dca0Sopenharmony_ci/// 4. Registers the same action for one of the signals again 44cac7dca0Sopenharmony_ci/// 5. Manually raises the signal, checks if the registered action behave 45cac7dca0Sopenharmony_ci/// correctly 46cac7dca0Sopenharmony_ci/// 6. Deregisters both signal's handler hook, checks if the return is ok. 47cac7dca0Sopenharmony_cifn sdv_signal_register_succeed() { 48cac7dca0Sopenharmony_ci let value = Arc::new(AtomicUsize::new(0)); 49cac7dca0Sopenharmony_ci let value_cpy = value.clone(); 50cac7dca0Sopenharmony_ci 51cac7dca0Sopenharmony_ci let value2 = Arc::new(AtomicUsize::new(10)); 52cac7dca0Sopenharmony_ci let value2_cpy = value2.clone(); 53cac7dca0Sopenharmony_ci let value2_cpy2 = value2.clone(); 54cac7dca0Sopenharmony_ci 55cac7dca0Sopenharmony_ci let res = unsafe { 56cac7dca0Sopenharmony_ci ylong_signal::register_signal_action(libc::SIGINT, move || { 57cac7dca0Sopenharmony_ci value_cpy.fetch_add(1, Ordering::Relaxed); 58cac7dca0Sopenharmony_ci }) 59cac7dca0Sopenharmony_ci }; 60cac7dca0Sopenharmony_ci assert!(res.is_ok()); 61cac7dca0Sopenharmony_ci 62cac7dca0Sopenharmony_ci let res = unsafe { 63cac7dca0Sopenharmony_ci ylong_signal::register_signal_action(libc::SIGTERM, move || { 64cac7dca0Sopenharmony_ci value2_cpy.fetch_add(10, Ordering::Relaxed); 65cac7dca0Sopenharmony_ci }) 66cac7dca0Sopenharmony_ci }; 67cac7dca0Sopenharmony_ci assert!(res.is_ok()); 68cac7dca0Sopenharmony_ci assert_eq!(value.load(Ordering::Relaxed), 0); 69cac7dca0Sopenharmony_ci 70cac7dca0Sopenharmony_ci unsafe { libc::raise(libc::SIGINT) }; 71cac7dca0Sopenharmony_ci assert_eq!(value.load(Ordering::Relaxed), 1); 72cac7dca0Sopenharmony_ci assert_eq!(value2.load(Ordering::Relaxed), 10); 73cac7dca0Sopenharmony_ci 74cac7dca0Sopenharmony_ci unsafe { libc::raise(libc::SIGTERM) }; 75cac7dca0Sopenharmony_ci assert_eq!(value.load(Ordering::Relaxed), 1); 76cac7dca0Sopenharmony_ci assert_eq!(value2.load(Ordering::Relaxed), 20); 77cac7dca0Sopenharmony_ci 78cac7dca0Sopenharmony_ci let res = ylong_signal::deregister_signal_action(libc::SIGTERM); 79cac7dca0Sopenharmony_ci assert!(res.is_ok()); 80cac7dca0Sopenharmony_ci 81cac7dca0Sopenharmony_ci ylong_signal::deregister_signal_action(libc::SIGINT).unwrap(); 82cac7dca0Sopenharmony_ci 83cac7dca0Sopenharmony_ci let res = unsafe { 84cac7dca0Sopenharmony_ci ylong_signal::register_signal_action(libc::SIGTERM, move || { 85cac7dca0Sopenharmony_ci value2_cpy2.fetch_add(20, Ordering::Relaxed); 86cac7dca0Sopenharmony_ci }) 87cac7dca0Sopenharmony_ci }; 88cac7dca0Sopenharmony_ci assert!(res.is_ok()); 89cac7dca0Sopenharmony_ci 90cac7dca0Sopenharmony_ci unsafe { libc::raise(libc::SIGTERM) }; 91cac7dca0Sopenharmony_ci assert_eq!(value2.load(Ordering::Relaxed), 40); 92cac7dca0Sopenharmony_ci 93cac7dca0Sopenharmony_ci let res = ylong_signal::deregister_signal_hook(libc::SIGTERM); 94cac7dca0Sopenharmony_ci assert!(res.is_ok()); 95cac7dca0Sopenharmony_ci 96cac7dca0Sopenharmony_ci let res = ylong_signal::deregister_signal_hook(libc::SIGINT); 97cac7dca0Sopenharmony_ci assert!(res.is_ok()); 98cac7dca0Sopenharmony_ci} 99cac7dca0Sopenharmony_ci 100cac7dca0Sopenharmony_ci/// SDV cases for signal register error handling 101cac7dca0Sopenharmony_ci/// 102cac7dca0Sopenharmony_ci/// # Brief 103cac7dca0Sopenharmony_ci/// 1. Registers an action for a forbidden signal 104cac7dca0Sopenharmony_ci/// 2. Checks if the return value is InvalidInput error 105cac7dca0Sopenharmony_ci/// 3. Registers an action for an allowed signal 106cac7dca0Sopenharmony_ci/// 4. Checks if the return value is Ok 107cac7dca0Sopenharmony_ci/// 5. Registers an action for the same signal again 108cac7dca0Sopenharmony_ci/// 6. Checks if the return value is AlreadyExists error 109cac7dca0Sopenharmony_ci/// 7. Deregisters the signal hook of the previous registered signal 110cac7dca0Sopenharmony_ci/// 8. Checks if the return value is OK 111cac7dca0Sopenharmony_ci/// 9. Deregisters the signal action of an unregistered signal 112cac7dca0Sopenharmony_ci/// 10. Deregisters the signal handler of an unregistered signal 113cac7dca0Sopenharmony_ci/// 11. Checks if the return value is Ok 114cac7dca0Sopenharmony_cifn sdv_signal_register_failed() { 115cac7dca0Sopenharmony_ci let res = unsafe { ylong_signal::register_signal_action(libc::SIGSEGV, move || {}) }; 116cac7dca0Sopenharmony_ci assert_eq!(res.unwrap_err().kind(), io::ErrorKind::InvalidInput); 117cac7dca0Sopenharmony_ci 118cac7dca0Sopenharmony_ci let res = unsafe { ylong_signal::register_signal_action(libc::SIGTERM, move || {}) }; 119cac7dca0Sopenharmony_ci assert!(res.is_ok()); 120cac7dca0Sopenharmony_ci let res = unsafe { ylong_signal::register_signal_action(libc::SIGTERM, move || {}) }; 121cac7dca0Sopenharmony_ci assert_eq!(res.unwrap_err().kind(), io::ErrorKind::AlreadyExists); 122cac7dca0Sopenharmony_ci 123cac7dca0Sopenharmony_ci let res = ylong_signal::deregister_signal_hook(libc::SIGTERM); 124cac7dca0Sopenharmony_ci assert!(res.is_ok()); 125cac7dca0Sopenharmony_ci 126cac7dca0Sopenharmony_ci let res = ylong_signal::deregister_signal_action(libc::SIGSEGV); 127cac7dca0Sopenharmony_ci assert!(res.is_ok()); 128cac7dca0Sopenharmony_ci 129cac7dca0Sopenharmony_ci let res = ylong_signal::deregister_signal_hook(libc::SIGSEGV); 130cac7dca0Sopenharmony_ci assert!(res.is_ok()); 131cac7dca0Sopenharmony_ci} 132cac7dca0Sopenharmony_ci 133cac7dca0Sopenharmony_ci/// SDV cases for signal register when there is already an existing handler 134cac7dca0Sopenharmony_ci/// 135cac7dca0Sopenharmony_ci/// # Brief 136cac7dca0Sopenharmony_ci/// 1. Registers a signal handler using libc syscall 137cac7dca0Sopenharmony_ci/// 2. Registers a signal handler using ylong_signal::register_signal_action 138cac7dca0Sopenharmony_ci/// 3. Manually raises the signal 139cac7dca0Sopenharmony_ci/// 4. Checks if the the new action get executed correctly 140cac7dca0Sopenharmony_ci/// 5. Deregisters the signal action 141cac7dca0Sopenharmony_ci/// 6. Manually raises the signal 142cac7dca0Sopenharmony_ci/// 7. Checks if the old handler gets executed correctly 143cac7dca0Sopenharmony_ci/// 8. Deregister the hook. 144cac7dca0Sopenharmony_cifn sdv_signal_register_with_old() { 145cac7dca0Sopenharmony_ci #[cfg(not(windows))] 146cac7dca0Sopenharmony_ci { 147cac7dca0Sopenharmony_ci let mut new_act: libc::sigaction = unsafe { std::mem::zeroed() }; 148cac7dca0Sopenharmony_ci new_act.sa_sigaction = test_handler as usize; 149cac7dca0Sopenharmony_ci unsafe { 150cac7dca0Sopenharmony_ci libc::sigaction(libc::SIGINT, &new_act, std::ptr::null_mut()); 151cac7dca0Sopenharmony_ci } 152cac7dca0Sopenharmony_ci } 153cac7dca0Sopenharmony_ci 154cac7dca0Sopenharmony_ci #[cfg(windows)] 155cac7dca0Sopenharmony_ci { 156cac7dca0Sopenharmony_ci unsafe { 157cac7dca0Sopenharmony_ci libc::signal(libc::SIGINT, test_handler as usize); 158cac7dca0Sopenharmony_ci } 159cac7dca0Sopenharmony_ci } 160cac7dca0Sopenharmony_ci 161cac7dca0Sopenharmony_ci let res = unsafe { 162cac7dca0Sopenharmony_ci ylong_signal::register_signal_action(libc::SIGINT, move || { 163cac7dca0Sopenharmony_ci let global = Global::get_instance(); 164cac7dca0Sopenharmony_ci assert_eq!(global.value.load(Ordering::Relaxed), 0); 165cac7dca0Sopenharmony_ci global.value.fetch_add(2, Ordering::Relaxed); 166cac7dca0Sopenharmony_ci }) 167cac7dca0Sopenharmony_ci }; 168cac7dca0Sopenharmony_ci assert!(res.is_ok()); 169cac7dca0Sopenharmony_ci 170cac7dca0Sopenharmony_ci unsafe { 171cac7dca0Sopenharmony_ci libc::raise(libc::SIGINT); 172cac7dca0Sopenharmony_ci } 173cac7dca0Sopenharmony_ci 174cac7dca0Sopenharmony_ci let global = Global::get_instance(); 175cac7dca0Sopenharmony_ci assert_eq!(global.value.load(Ordering::Relaxed), 2); 176cac7dca0Sopenharmony_ci 177cac7dca0Sopenharmony_ci let res = ylong_signal::deregister_signal_action(libc::SIGINT); 178cac7dca0Sopenharmony_ci assert!(res.is_ok()); 179cac7dca0Sopenharmony_ci 180cac7dca0Sopenharmony_ci unsafe { 181cac7dca0Sopenharmony_ci libc::raise(libc::SIGINT); 182cac7dca0Sopenharmony_ci } 183cac7dca0Sopenharmony_ci assert_eq!(global.value.load(Ordering::Relaxed), 3); 184cac7dca0Sopenharmony_ci let res = ylong_signal::deregister_signal_hook(libc::SIGINT); 185cac7dca0Sopenharmony_ci assert!(res.is_ok()); 186cac7dca0Sopenharmony_ci} 187cac7dca0Sopenharmony_ci 188cac7dca0Sopenharmony_cipub struct Global { 189cac7dca0Sopenharmony_ci value: AtomicUsize, 190cac7dca0Sopenharmony_ci} 191cac7dca0Sopenharmony_ci 192cac7dca0Sopenharmony_ciimpl Global { 193cac7dca0Sopenharmony_ci fn get_instance() -> &'static Global { 194cac7dca0Sopenharmony_ci static mut GLOBAL: MaybeUninit<Global> = MaybeUninit::uninit(); 195cac7dca0Sopenharmony_ci static ONCE: Once = Once::new(); 196cac7dca0Sopenharmony_ci 197cac7dca0Sopenharmony_ci unsafe { 198cac7dca0Sopenharmony_ci ONCE.call_once(|| { 199cac7dca0Sopenharmony_ci GLOBAL = MaybeUninit::new(Global { 200cac7dca0Sopenharmony_ci value: AtomicUsize::new(0), 201cac7dca0Sopenharmony_ci }); 202cac7dca0Sopenharmony_ci }); 203cac7dca0Sopenharmony_ci &*GLOBAL.as_ptr() 204cac7dca0Sopenharmony_ci } 205cac7dca0Sopenharmony_ci } 206cac7dca0Sopenharmony_ci} 207cac7dca0Sopenharmony_ci 208cac7dca0Sopenharmony_ciextern "C" fn test_handler(_sig_num: c_int) { 209cac7dca0Sopenharmony_ci let global = Global::get_instance(); 210cac7dca0Sopenharmony_ci global.value.fetch_add(1, Ordering::Relaxed); 211cac7dca0Sopenharmony_ci} 212cac7dca0Sopenharmony_ci 213cac7dca0Sopenharmony_ci/// SDV cases for signal register in multi-thread env 214cac7dca0Sopenharmony_ci/// 215cac7dca0Sopenharmony_ci/// # Brief 216cac7dca0Sopenharmony_ci/// 1. Registers a signal handler 217cac7dca0Sopenharmony_ci/// 2. Spawns another thread to raise the signal 218cac7dca0Sopenharmony_ci/// 3. Raises the same signal on the main thread 219cac7dca0Sopenharmony_ci/// 4. All execution should return OK 220cac7dca0Sopenharmony_ci#[cfg(not(windows))] 221cac7dca0Sopenharmony_cifn sdv_signal_register_multi() { 222cac7dca0Sopenharmony_ci for i in 0..1000 { 223cac7dca0Sopenharmony_ci let res = unsafe { 224cac7dca0Sopenharmony_ci ylong_signal::register_signal_action(libc::SIGCHLD, move || { 225cac7dca0Sopenharmony_ci let mut data = 100; 226cac7dca0Sopenharmony_ci data += i; 227cac7dca0Sopenharmony_ci assert_eq!(data, 100 + i); 228cac7dca0Sopenharmony_ci }) 229cac7dca0Sopenharmony_ci }; 230cac7dca0Sopenharmony_ci std::thread::spawn(move || { 231cac7dca0Sopenharmony_ci unsafe { libc::raise(libc::SIGCHLD) }; 232cac7dca0Sopenharmony_ci }); 233cac7dca0Sopenharmony_ci assert!(res.is_ok()); 234cac7dca0Sopenharmony_ci unsafe { 235cac7dca0Sopenharmony_ci libc::raise(libc::SIGCHLD); 236cac7dca0Sopenharmony_ci } 237cac7dca0Sopenharmony_ci 238cac7dca0Sopenharmony_ci let res = ylong_signal::deregister_signal_action(libc::SIGCHLD); 239cac7dca0Sopenharmony_ci assert!(res.is_ok()); 240cac7dca0Sopenharmony_ci 241cac7dca0Sopenharmony_ci unsafe { 242cac7dca0Sopenharmony_ci libc::raise(libc::SIGCHLD); 243cac7dca0Sopenharmony_ci } 244cac7dca0Sopenharmony_ci } 245cac7dca0Sopenharmony_ci} 246