1f857971dSopenharmony_ci/* 2f857971dSopenharmony_ci * Copyright (C) 2023 Huawei Device Co., Ltd. 3f857971dSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4f857971dSopenharmony_ci * you may not use this file except in compliance with the License. 5f857971dSopenharmony_ci * You may obtain a copy of the License at 6f857971dSopenharmony_ci * 7f857971dSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8f857971dSopenharmony_ci * 9f857971dSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10f857971dSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11f857971dSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12f857971dSopenharmony_ci * See the License for the specific language governing permissions and 13f857971dSopenharmony_ci * limitations under the License. 14f857971dSopenharmony_ci */ 15f857971dSopenharmony_ci 16f857971dSopenharmony_ci//! Tests of asynchronous scheduling. 17f857971dSopenharmony_ci 18f857971dSopenharmony_ciuse std::ffi::{ c_void, c_char, c_int, CString }; 19f857971dSopenharmony_ciuse std::io::Error; 20f857971dSopenharmony_ciuse std::os::fd::RawFd; 21f857971dSopenharmony_ciuse std::sync::{ Arc, Condvar, Mutex }; 22f857971dSopenharmony_ciuse std::sync::atomic::{ AtomicI32, Ordering }; 23f857971dSopenharmony_ciuse std::time::Duration; 24f857971dSopenharmony_ci 25f857971dSopenharmony_ciuse hilog_rust::{ debug, info, error, hilog, HiLogLabel, LogType }; 26f857971dSopenharmony_ci 27f857971dSopenharmony_ciuse fusion_scheduler_rust::{ Handler, IEpollHandler, LIBC_EPOLLIN }; 28f857971dSopenharmony_ciuse fusion_utils_rust::call_debug_enter; 29f857971dSopenharmony_ci 30f857971dSopenharmony_ciconst LOG_LABEL: HiLogLabel = HiLogLabel { 31f857971dSopenharmony_ci log_type: LogType::LogCore, 32f857971dSopenharmony_ci domain: 0xD002220, 33f857971dSopenharmony_ci tag: "FusionSchedulerTest", 34f857971dSopenharmony_ci}; 35f857971dSopenharmony_ci 36f857971dSopenharmony_cistruct EpollHandlerImpl { 37f857971dSopenharmony_ci fds: [RawFd; 2], 38f857971dSopenharmony_ci data: i32, 39f857971dSopenharmony_ci} 40f857971dSopenharmony_ci 41f857971dSopenharmony_ciimpl EpollHandlerImpl { 42f857971dSopenharmony_ci fn signal(&self, data: i32) 43f857971dSopenharmony_ci { 44f857971dSopenharmony_ci error!(LOG_LABEL, "EpollHandlerImpl::signal once"); 45f857971dSopenharmony_ci let ret = unsafe { 46f857971dSopenharmony_ci libc::write(self.fds[1], std::ptr::addr_of!(data) as *const c_void, std::mem::size_of_val(&data)) 47f857971dSopenharmony_ci }; 48f857971dSopenharmony_ci if ret == -1 { 49f857971dSopenharmony_ci error!(LOG_LABEL, "libc::write fail"); 50f857971dSopenharmony_ci } 51f857971dSopenharmony_ci } 52f857971dSopenharmony_ci 53f857971dSopenharmony_ci fn fd(&self) -> RawFd 54f857971dSopenharmony_ci { 55f857971dSopenharmony_ci self.fds[0] 56f857971dSopenharmony_ci } 57f857971dSopenharmony_ci 58f857971dSopenharmony_ci fn dispatch(&mut self, events: u32) 59f857971dSopenharmony_ci { 60f857971dSopenharmony_ci call_debug_enter!("EpollHandlerImpl::dispatch"); 61f857971dSopenharmony_ci if (events & LIBC_EPOLLIN) == LIBC_EPOLLIN { 62f857971dSopenharmony_ci let data: i32 = 0; 63f857971dSopenharmony_ci 64f857971dSopenharmony_ci let ret = unsafe { 65f857971dSopenharmony_ci libc::read(self.fds[0], std::ptr::addr_of!(data) as *mut c_void, std::mem::size_of_val(&data)) 66f857971dSopenharmony_ci }; 67f857971dSopenharmony_ci if ret == -1 { 68f857971dSopenharmony_ci error!(LOG_LABEL, "libc::read fail"); 69f857971dSopenharmony_ci } 70f857971dSopenharmony_ci info!(LOG_LABEL, "EpollHandlerImpl::dispatch({}), data:{}", @public(self.fds[0]), @public(data)); 71f857971dSopenharmony_ci self.data = data; 72f857971dSopenharmony_ci } 73f857971dSopenharmony_ci } 74f857971dSopenharmony_ci 75f857971dSopenharmony_ci fn data(&self) -> i32 76f857971dSopenharmony_ci { 77f857971dSopenharmony_ci self.data 78f857971dSopenharmony_ci } 79f857971dSopenharmony_ci} 80f857971dSopenharmony_ci 81f857971dSopenharmony_ciimpl Drop for EpollHandlerImpl { 82f857971dSopenharmony_ci fn drop(&mut self) 83f857971dSopenharmony_ci { 84f857971dSopenharmony_ci for fd in &mut self.fds { 85f857971dSopenharmony_ci if *fd != -1 { 86f857971dSopenharmony_ci unsafe { libc::close(*fd) }; 87f857971dSopenharmony_ci *fd = -1; 88f857971dSopenharmony_ci } 89f857971dSopenharmony_ci } 90f857971dSopenharmony_ci } 91f857971dSopenharmony_ci} 92f857971dSopenharmony_ci 93f857971dSopenharmony_cistruct EpollHandler { 94f857971dSopenharmony_ci inner: Mutex<EpollHandlerImpl>, 95f857971dSopenharmony_ci var: Condvar, 96f857971dSopenharmony_ci} 97f857971dSopenharmony_ci 98f857971dSopenharmony_ciimpl EpollHandler { 99f857971dSopenharmony_ci fn new() -> Self 100f857971dSopenharmony_ci { 101f857971dSopenharmony_ci let mut fds: [c_int; 2] = [-1; 2]; 102f857971dSopenharmony_ci 103f857971dSopenharmony_ci let ret = unsafe { libc::pipe2(fds.as_mut_ptr(), libc::O_CLOEXEC | libc::O_NONBLOCK) }; 104f857971dSopenharmony_ci if ret != 0 { 105f857971dSopenharmony_ci error!(LOG_LABEL, "In EpollHandler::new, libc::pipe2 fail:{:?}", @public(Error::last_os_error())); 106f857971dSopenharmony_ci } 107f857971dSopenharmony_ci debug!(LOG_LABEL, "In EpollHandler::new, fds:({},{})", @public(fds[0]), @public(fds[1])); 108f857971dSopenharmony_ci Self { 109f857971dSopenharmony_ci inner: Mutex::new(EpollHandlerImpl { 110f857971dSopenharmony_ci fds, 111f857971dSopenharmony_ci data: -1, 112f857971dSopenharmony_ci }), 113f857971dSopenharmony_ci var: Condvar::new(), 114f857971dSopenharmony_ci } 115f857971dSopenharmony_ci } 116f857971dSopenharmony_ci 117f857971dSopenharmony_ci fn signal(&self, data: i32) 118f857971dSopenharmony_ci { 119f857971dSopenharmony_ci let guard = self.inner.lock().unwrap(); 120f857971dSopenharmony_ci guard.signal(data); 121f857971dSopenharmony_ci } 122f857971dSopenharmony_ci 123f857971dSopenharmony_ci fn data(&self) -> i32 124f857971dSopenharmony_ci { 125f857971dSopenharmony_ci let guard = self.inner.lock().unwrap(); 126f857971dSopenharmony_ci guard.data() 127f857971dSopenharmony_ci } 128f857971dSopenharmony_ci 129f857971dSopenharmony_ci fn wait(&self, dur: Duration) -> bool 130f857971dSopenharmony_ci { 131f857971dSopenharmony_ci call_debug_enter!("EpollHandler::wait"); 132f857971dSopenharmony_ci let guard = self.inner.lock().unwrap(); 133f857971dSopenharmony_ci let (_, ret) = self.var.wait_timeout(guard, dur).unwrap(); 134f857971dSopenharmony_ci if ret.timed_out() { 135f857971dSopenharmony_ci info!(LOG_LABEL, "In EpollHandler::wait, timeout"); 136f857971dSopenharmony_ci false 137f857971dSopenharmony_ci } else { 138f857971dSopenharmony_ci true 139f857971dSopenharmony_ci } 140f857971dSopenharmony_ci } 141f857971dSopenharmony_ci} 142f857971dSopenharmony_ci 143f857971dSopenharmony_ciimpl IEpollHandler for EpollHandler { 144f857971dSopenharmony_ci fn fd(&self) -> RawFd 145f857971dSopenharmony_ci { 146f857971dSopenharmony_ci let guard = self.inner.lock().unwrap(); 147f857971dSopenharmony_ci guard.fd() 148f857971dSopenharmony_ci } 149f857971dSopenharmony_ci 150f857971dSopenharmony_ci fn dispatch(&self, events: u32) 151f857971dSopenharmony_ci { 152f857971dSopenharmony_ci call_debug_enter!("EpollHandler::dispatch"); 153f857971dSopenharmony_ci let mut guard = self.inner.lock().unwrap(); 154f857971dSopenharmony_ci guard.dispatch(events); 155f857971dSopenharmony_ci self.var.notify_one(); 156f857971dSopenharmony_ci } 157f857971dSopenharmony_ci} 158f857971dSopenharmony_ci 159f857971dSopenharmony_ci#[test] 160f857971dSopenharmony_cifn test_add_epoll_handler() 161f857971dSopenharmony_ci{ 162f857971dSopenharmony_ci let handler: Arc<Handler> = Arc::default(); 163f857971dSopenharmony_ci let epoll = Arc::new(EpollHandler::new()); 164f857971dSopenharmony_ci assert!(handler.add_epoll_handler(epoll.clone()).is_ok()); 165f857971dSopenharmony_ci 166f857971dSopenharmony_ci let data: i32 = 13574; 167f857971dSopenharmony_ci epoll.signal(data); 168f857971dSopenharmony_ci assert!(epoll.wait(Duration::from_millis(100))); 169f857971dSopenharmony_ci info!(LOG_LABEL, "In test_add_epoll_handler, data:{}", @public(epoll.data())); 170f857971dSopenharmony_ci assert_eq!(epoll.data(), data); 171f857971dSopenharmony_ci assert!(handler.remove_epoll_handler(epoll).is_ok()); 172f857971dSopenharmony_ci} 173f857971dSopenharmony_ci 174f857971dSopenharmony_cifn hash(param: usize) -> usize 175f857971dSopenharmony_ci{ 176f857971dSopenharmony_ci const HASHER: usize = 0xAAAAAAAA; 177f857971dSopenharmony_ci HASHER ^ param 178f857971dSopenharmony_ci} 179f857971dSopenharmony_ci 180f857971dSopenharmony_ci#[test] 181f857971dSopenharmony_cifn test_post_sync_task() 182f857971dSopenharmony_ci{ 183f857971dSopenharmony_ci let handler: Arc<Handler> = Arc::default(); 184f857971dSopenharmony_ci let param: usize = 0xAB1807; 185f857971dSopenharmony_ci 186f857971dSopenharmony_ci let ret = handler.post_sync_task(move || { 187f857971dSopenharmony_ci hash(param) 188f857971dSopenharmony_ci }); 189f857971dSopenharmony_ci let expected = hash(param); 190f857971dSopenharmony_ci assert_eq!(ret, expected); 191f857971dSopenharmony_ci} 192f857971dSopenharmony_ci 193f857971dSopenharmony_ci#[test] 194f857971dSopenharmony_cifn test_post_async_task() 195f857971dSopenharmony_ci{ 196f857971dSopenharmony_ci let handler: Arc<Handler> = Arc::default(); 197f857971dSopenharmony_ci let param: usize = 0xAB1807; 198f857971dSopenharmony_ci 199f857971dSopenharmony_ci let mut task_handle = handler.post_async_task(move || { 200f857971dSopenharmony_ci hash(param) 201f857971dSopenharmony_ci }); 202f857971dSopenharmony_ci let ret = task_handle.result().unwrap(); 203f857971dSopenharmony_ci let expected = hash(param); 204f857971dSopenharmony_ci assert_eq!(ret, expected); 205f857971dSopenharmony_ci} 206f857971dSopenharmony_ci 207f857971dSopenharmony_ci#[test] 208f857971dSopenharmony_cifn test_post_perioric_task() 209f857971dSopenharmony_ci{ 210f857971dSopenharmony_ci let handler: Arc<Handler> = Arc::default(); 211f857971dSopenharmony_ci let epoll = Arc::new(EpollHandler::new()); 212f857971dSopenharmony_ci let cloned_epoll = epoll.clone(); 213f857971dSopenharmony_ci assert!(handler.add_epoll_handler(epoll.clone()).is_ok()); 214f857971dSopenharmony_ci 215f857971dSopenharmony_ci let _ = handler.post_perioric_task(move || { 216f857971dSopenharmony_ci static ID_RADIX: AtomicI32 = AtomicI32::new(1); 217f857971dSopenharmony_ci cloned_epoll.signal(ID_RADIX.fetch_add(1, Ordering::Relaxed)); 218f857971dSopenharmony_ci }, None, Duration::from_millis(100), Some(10)); 219f857971dSopenharmony_ci 220f857971dSopenharmony_ci std::thread::sleep(Duration::from_secs(1)); 221f857971dSopenharmony_ci info!(LOG_LABEL, "In test_post_perioric_task, data:{}", @public(epoll.data())); 222f857971dSopenharmony_ci assert!(epoll.data() >= 10); 223f857971dSopenharmony_ci assert!(handler.remove_epoll_handler(epoll).is_ok()); 224f857971dSopenharmony_ci} 225f857971dSopenharmony_ci 226f857971dSopenharmony_ci#[test] 227f857971dSopenharmony_cifn test_post_delayed_task() 228f857971dSopenharmony_ci{ 229f857971dSopenharmony_ci let handler: Arc<Handler> = Arc::default(); 230f857971dSopenharmony_ci let epoll = Arc::new(EpollHandler::new()); 231f857971dSopenharmony_ci assert!(handler.add_epoll_handler(epoll.clone()).is_ok()); 232f857971dSopenharmony_ci let data: i32 = 13547; 233f857971dSopenharmony_ci let cloned_epoll = epoll.clone(); 234f857971dSopenharmony_ci 235f857971dSopenharmony_ci let _ = handler.post_delayed_task(move || { 236f857971dSopenharmony_ci cloned_epoll.signal(data); 237f857971dSopenharmony_ci }, Duration::from_millis(10)); 238f857971dSopenharmony_ci 239f857971dSopenharmony_ci assert!(epoll.wait(Duration::from_millis(100))); 240f857971dSopenharmony_ci info!(LOG_LABEL, "In test_post_delayed_task, data:{}", @public(epoll.data())); 241f857971dSopenharmony_ci assert_eq!(epoll.data(), data); 242f857971dSopenharmony_ci assert!(handler.remove_epoll_handler(epoll).is_ok()); 243f857971dSopenharmony_ci} 244f857971dSopenharmony_ci 245f857971dSopenharmony_ci#[test] 246f857971dSopenharmony_cifn test_post_blocking_task() 247f857971dSopenharmony_ci{ 248f857971dSopenharmony_ci let handler: Arc<Handler> = Arc::default(); 249f857971dSopenharmony_ci let param: usize = 0xAB1807; 250f857971dSopenharmony_ci 251f857971dSopenharmony_ci let mut task_handle = handler.post_blocking_task(move || { 252f857971dSopenharmony_ci std::thread::sleep(Duration::from_millis(100)); 253f857971dSopenharmony_ci hash(param) 254f857971dSopenharmony_ci }); 255f857971dSopenharmony_ci let ret = task_handle.result().unwrap(); 256f857971dSopenharmony_ci let expected = hash(param); 257f857971dSopenharmony_ci assert_eq!(ret, expected); 258f857971dSopenharmony_ci} 259