diff --git a/ylong_io/src/sys/linux/epoll.rs b/ylong_io/src/sys/linux/epoll.rs index a63a7c6bdbc28ccf4e533e6d417a8ea88d2795ca..6d7de78aec75a0269f47c63e2a35cc6d374fe4fe 100644 --- a/ylong_io/src/sys/linux/epoll.rs +++ b/ylong_io/src/sys/linux/epoll.rs @@ -103,7 +103,7 @@ impl Selector { self.ep, libc::EPOLL_CTL_DEL, fd, - std::ptr::null_mut() as *mut libc::epoll_event + std::ptr::null_mut() )) { Ok(_) => Ok(()), Err(err) => Err(err), diff --git a/ylong_runtime/src/executor/async_pool.rs b/ylong_runtime/src/executor/async_pool.rs index be68fdf3495c549a6b1573b8c9f9f80f6706397e..1ec7d035213c3a3b391a54fda58b19fcfa90b7b8 100644 --- a/ylong_runtime/src/executor/async_pool.rs +++ b/ylong_runtime/src/executor/async_pool.rs @@ -27,9 +27,9 @@ use super::worker::{get_current_ctx, run_worker, Worker}; use super::{worker, Schedule}; use crate::builder::multi_thread_builder::MultiThreadBuilder; use crate::builder::CallbackHook; +use crate::fastrand::fast_random; use crate::task::{Task, TaskBuilder, VirtualTableType}; use crate::util::core_affinity::set_current_affinity; -use crate::util::fastrand::fast_random; use crate::util::num_cpus::get_cpu_num; use crate::JoinHandle; diff --git a/ylong_runtime/src/util/fastrand.rs b/ylong_runtime/src/fastrand.rs similarity index 96% rename from ylong_runtime/src/util/fastrand.rs rename to ylong_runtime/src/fastrand.rs index 8013c0398298cab8c48f02028484e75310360804..7335650e1d742d82a7ca7805bd887b320f24118b 100644 --- a/ylong_runtime/src/util/fastrand.rs +++ b/ylong_runtime/src/fastrand.rs @@ -23,7 +23,7 @@ use std::num::Wrapping; /// /// # Examples /// ```rust -/// use ylong_runtime::util::fastrand::fast_random; +/// use ylong_runtime::fastrand::fast_random; /// let rand = fast_random(); /// assert!(rand <= u64::MAX); /// ``` diff --git a/ylong_runtime/src/fs/async_dir.rs b/ylong_runtime/src/fs/async_dir.rs index 9b31096e3bc16a115fe0a49db3626e3676e61db5..60c06a5ee346fd88f5768813c2957bef2c7a162c 100644 --- a/ylong_runtime/src/fs/async_dir.rs +++ b/ylong_runtime/src/fs/async_dir.rs @@ -613,7 +613,7 @@ impl ReadDir { } } -/// Entries returned by the [`ReadDir::next_entry`]. +/// Entries returned by the [`ReadDir::next`]. /// /// Represents an entry inside of a directory on the filesystem. /// Each entry can be inspected via methods to learn about the full path diff --git a/ylong_runtime/src/lib.rs b/ylong_runtime/src/lib.rs index b3dfd1992a153d728a534b0ec800a7ac0a3bb944..ad405f4c1267b26c41e1a83251458baf1ba3279e 100644 --- a/ylong_runtime/src/lib.rs +++ b/ylong_runtime/src/lib.rs @@ -38,14 +38,15 @@ use crate::task::{JoinHandle, Task, TaskBuilder}; pub mod builder; pub mod error; pub mod executor; +pub mod fastrand; +pub mod futures; +pub mod io; +pub mod iter; #[cfg(feature = "ffrt")] pub(crate) mod ffrt; #[cfg(feature = "fs")] pub mod fs; -pub mod futures; -pub mod io; -pub mod iter; #[cfg(feature = "macros")] mod select; #[cfg(feature = "macros")] @@ -59,7 +60,7 @@ cfg_time! { pub mod time; } -pub mod util; +mod util; cfg_metrics!( mod metrics; pub use metrics::Metrics; diff --git a/ylong_runtime/src/select.rs b/ylong_runtime/src/select.rs index 38f9c6f19595d656de17532197ec7b8ff1b7f220..0624d83d8baab6439a56a1978c8be71692e8ecef 100644 --- a/ylong_runtime/src/select.rs +++ b/ylong_runtime/src/select.rs @@ -200,7 +200,7 @@ macro_rules! select { // When a branch ready first, modify this variable to // branch's index to ensure that the branch is executed first. - use $crate::util::fastrand::fast_random; + use $crate::fastrand::fast_random; let mut random_number = fast_random() as usize; let output = { diff --git a/ylong_runtime/src/sync/mpsc/bounded/mod.rs b/ylong_runtime/src/sync/mpsc/bounded/mod.rs index 93e37b34773a39ab9ae5dc19521cabe46b6fe584..84da091417024f150183ed94c33db1391da98df4 100644 --- a/ylong_runtime/src/sync/mpsc/bounded/mod.rs +++ b/ylong_runtime/src/sync/mpsc/bounded/mod.rs @@ -391,8 +391,8 @@ impl BoundedReceiver { /// not closed. /// * `Poll::Ready(Ok(T))` if receiving a value successfully. /// * `Poll::Ready(Err(RecvError))` in the following situations: - /// 1.All senders have been dropped or the channel is closed. - /// 2.No messages remaining. + /// 1. All senders have been dropped or the channel is closed. + /// 2. No messages remaining. /// /// # Examples /// @@ -421,8 +421,8 @@ impl BoundedReceiver { /// # Return value /// * `Ok(T)` if receiving a value successfully. /// * `Err(RecvError)` in the following situations: - /// 1.All senders have been dropped or the channel is closed. - /// 2.No messages remaining. + /// 1. All senders have been dropped or the channel is closed. + /// 2. No messages remaining. /// /// # Examples /// diff --git a/ylong_runtime/src/sync/mpsc/unbounded/mod.rs b/ylong_runtime/src/sync/mpsc/unbounded/mod.rs index f3214290c01a8f0c3a9984e9749f7b0ddd4f67d3..1f96f3ef75451a88adfebaf790a6d472b45a91d5 100644 --- a/ylong_runtime/src/sync/mpsc/unbounded/mod.rs +++ b/ylong_runtime/src/sync/mpsc/unbounded/mod.rs @@ -273,8 +273,8 @@ impl UnboundedReceiver { /// not closed. /// * `Poll::Ready(Ok(T))` if receiving a value successfully. /// * `Poll::Ready(Err(RecvError))` in the following situations: - /// 1.All senders have been dropped or the channel is closed. - /// 2.No messages remaining. + /// 1. All senders have been dropped or the channel is closed. + /// 2. No messages remaining. /// /// # Examples /// @@ -302,8 +302,8 @@ impl UnboundedReceiver { /// # Return value /// * `Ok(T)` if receiving a value successfully. /// * `Err(RecvError)` in the following situations: - /// 1.All senders have been dropped or the channel is closed. - /// 2.No messages remaining. + /// 1. All senders have been dropped or the channel is closed. + /// 2. No messages remaining. /// /// # Examples /// diff --git a/ylong_runtime/src/sync/wake_list.rs b/ylong_runtime/src/sync/wake_list.rs index 283c2a9f77334837ff29b5c0c192fc91b3774612..ac5749a63247456edc03d2e8762d19b3a1769373 100644 --- a/ylong_runtime/src/sync/wake_list.rs +++ b/ylong_runtime/src/sync/wake_list.rs @@ -185,7 +185,7 @@ mod tests { let wakelist = WakerList::new(); assert_eq!(wakelist.flag.load(Ordering::SeqCst), 0); unsafe { - assert_eq!((*wakelist.inner.get()).wake_list.len(), 0); + assert_eq!((*wakelist.inner.get()).wake_list.len, 0); } } } diff --git a/ylong_runtime/src/task/raw.rs b/ylong_runtime/src/task/raw.rs index bc569c29aa5cfd434186639914bbcb8678bdfc66..bd5677fdcc71a8c7bf3532b7a07c28189d42a78b 100644 --- a/ylong_runtime/src/task/raw.rs +++ b/ylong_runtime/src/task/raw.rs @@ -55,7 +55,7 @@ pub(crate) struct Header { pub(crate) vtable: &'static TaskVirtualTable, } -#[derive(PartialEq, Eq, Hash)] +#[derive(PartialEq, Eq, Hash, Clone, Copy)] pub(crate) struct RawTask { pub(crate) ptr: NonNull
, } @@ -114,14 +114,6 @@ impl RawTask { } } -impl Copy for RawTask {} - -impl Clone for RawTask { - fn clone(&self) -> Self { - RawTask { ptr: self.ptr } - } -} - pub(crate) enum Stage { Executing(T), Executed, diff --git a/ylong_runtime/src/time/wheel.rs b/ylong_runtime/src/time/wheel.rs index 127779f4ea22fff1ff36ce340c54ffc4c9645c2e..6fa39d17f487445d5035ef040f056292e4ab6102 100644 --- a/ylong_runtime/src/time/wheel.rs +++ b/ylong_runtime/src/time/wheel.rs @@ -115,7 +115,7 @@ impl Wheel { if expiration <= self.elapsed() { // This means that the timeout period has passed, // and the time should be triggered immediately. - return Err(Error::default()); + return Err(Error); } let level = self.find_level(expiration); diff --git a/ylong_runtime/src/util/bit.rs b/ylong_runtime/src/util/bit.rs index a14a85b15bbe2e82d89a9b4e4d5cec51ac9a0fff..e418a95729d908f55b2246b8d16ff3de6898707f 100644 --- a/ylong_runtime/src/util/bit.rs +++ b/ylong_runtime/src/util/bit.rs @@ -21,7 +21,7 @@ /// For example: 0000_1111(mask) & 1010_1010(target number) = 0000_1010 /// /// # Example -/// ```rust +/// ```no run /// use ylong_runtime::util::bit::Mask; /// /// // On a 64-bit machine, you can get the mask 0xf @@ -44,7 +44,7 @@ impl Mask { /// /// # Example /// When width + shift < Machine word length time - /// ```rust + /// ```no run /// use ylong_runtime::util::bit::Mask; /// /// let width = 4; @@ -59,7 +59,7 @@ impl Mask { /// ``` /// When width >= machine word length, a mask of all 1's is returned /// regardless of the shift. - /// ```rust + /// ```no run /// use ylong_runtime::util::bit::Mask; /// /// let width = 128; @@ -68,7 +68,7 @@ impl Mask { /// // On a 64-bit machine, the mask is 0xffff_ffff_ffff_ffff /// ``` /// When width == 0, an all-0 mask is returned, regardless of the shift. - /// ```rust + /// ```no run /// use ylong_runtime::util::bit::Mask; /// /// let width = 0; @@ -79,7 +79,7 @@ impl Mask { /// When width < machine word length and width + shift > machine word /// length, it will ensure that width remains unchanged and shift becomes /// machine word length - width. - /// ```rust + /// ```no run /// use ylong_runtime::util::bit::Mask; /// /// let width = 32; @@ -152,7 +152,7 @@ impl Bit { /// Converts a usize type to a Bit type /// /// # Example - /// ```rust + /// ```no run /// use ylong_runtime::util::bit::Bit; /// /// let base = 0usize; @@ -165,7 +165,7 @@ impl Bit { /// Converts a Bit type to a usize type /// /// # Example - /// ```rust + /// ```no run /// use ylong_runtime::util::bit::Bit; /// /// let base = 0usize; @@ -184,7 +184,7 @@ impl Bit { /// /// # Example /// When Mask binary length >= val binary length (excluding leading zeros) - /// ```rust + /// ```no run /// use ylong_runtime::util::bit::{Bit, Mask}; /// /// // mask's length 16 @@ -198,7 +198,7 @@ impl Bit { /// ``` /// When Mask binary length < val binary length (excluding leading zeros), /// val is truncated and only the low bit is retained. - /// ```rust + /// ```no run /// use ylong_runtime::util::bit::{Bit, Mask}; /// /// // mask's length 16 @@ -232,754 +232,737 @@ impl Bit { pub fn get_by_mask(&self, mask: Mask) -> usize { (self.0 & mask.mask) >> mask.shift } - - /// Sets bit to a new usize value. - /// - /// # Example - /// ```not run - /// use ylong_runtime::util::bit::{Mask, Bit}; - /// - /// let base = 0x0usize; - /// let mut bits = Bit::from_usize(base); - /// bits.set(0xffff_ffff_ffff_ffff); - /// assert_eq!(bits.as_usize(), 0xffff_ffff_ffff_ffff); - /// ``` - pub fn set(&mut self, val: usize) { - self.0 = val; - } - - /// Clear bit to 0usize - /// - /// # Example - /// ```rust - /// use ylong_runtime::util::bit::{Bit, Mask}; - /// - /// let base = 0xffffusize; - /// let mut bits = Bit::from_usize(base); - /// bits.clear(); - /// assert_eq!(bits.as_usize(), 0x0); - /// ``` - pub fn clear(&mut self) { - self.0 = 0; - } } -/// UT test cases for mask new function -/// -/// # Brief -/// 1. pass in the parameters, and create the Mask. -/// 2. Check return value. -#[cfg(target_pointer_width = "32")] -#[test] -fn ut_mask_new_bit32() { - assert_eq!( - Mask::new(0, 0), - Mask { - mask: 0x0, - shift: 0 - } - ); - assert_eq!( - Mask::new(0, 16), - Mask { - mask: 0x0, - shift: 0 - } - ); - assert_eq!( - Mask::new(0, 32), - Mask { - mask: 0x0, - shift: 0 - } - ); - assert_eq!( - Mask::new(0, 64), - Mask { - mask: 0x0, - shift: 0 - } - ); - assert_eq!( - Mask::new(1, 0), - Mask { - mask: 0x1, - shift: 0 - } - ); - assert_eq!( - Mask::new(1, 16), - Mask { - mask: 0x1_0000, - shift: 16 - } - ); - assert_eq!( - Mask::new(1, 31), - Mask { - mask: 0x8000_0000, - shift: 31 - } - ); - assert_eq!( - Mask::new(1, 32), - Mask { - mask: 0x8000_0000, - shift: 31 - } - ); - assert_eq!( - Mask::new(1, 128), - Mask { - mask: 0x8000_0000, - shift: 31 - } - ); - assert_eq!( - Mask::new(4, 0), - Mask { - mask: 0xf, - shift: 0 - } - ); - assert_eq!( - Mask::new(4, 16), - Mask { - mask: 0xf_0000, - shift: 16 - } - ); - assert_eq!( - Mask::new(4, 28), - Mask { - mask: 0xf000_0000, - shift: 28 - } - ); - assert_eq!( - Mask::new(4, 32), - Mask { - mask: 0xf000_0000, - shift: 28 +#[cfg(test)] +mod test { + use super::*; + impl Bit { + fn set(&mut self, val: usize) { + self.0 = val; } - ); - assert_eq!( - Mask::new(4, 64), - Mask { - mask: 0xf000_0000, - shift: 28 - } - ); - assert_eq!( - Mask::new(16, 0), - Mask { - mask: 0xffff, - shift: 0 - } - ); - assert_eq!( - Mask::new(16, 16), - Mask { - mask: 0xffff_0000, - shift: 16 - } - ); - assert_eq!( - Mask::new(16, 32), - Mask { - mask: 0xffff_0000, - shift: 16 - } - ); - assert_eq!( - Mask::new(16, 64), - Mask { - mask: 0xffff_0000, - shift: 16 - } - ); - assert_eq!( - Mask::new(32, 0), - Mask { - mask: 0xffff_ffff, - shift: 0 - } - ); - assert_eq!( - Mask::new(32, 16), - Mask { - mask: 0xffff_ffff, - shift: 0 - } - ); - assert_eq!( - Mask::new(32, 32), - Mask { - mask: 0xffff_ffff, - shift: 0 - } - ); - assert_eq!( - Mask::new(32, 64), - Mask { - mask: 0xffff_ffff, - shift: 0 - } - ); - assert_eq!( - Mask::new(64, 0), - Mask { - mask: 0xffff_ffff, - shift: 0 - } - ); - assert_eq!( - Mask::new(64, 16), - Mask { - mask: 0xffff_ffff, - shift: 0 - } - ); - assert_eq!( - Mask::new(64, 32), - Mask { - mask: 0xffff_ffff, - shift: 0 - } - ); - assert_eq!( - Mask::new(64, 64), - Mask { - mask: 0xffff_ffff, - shift: 0 - } - ); -} - -/// UT test cases for mask new function -/// -/// # Brief -/// 1. pass in the parameters, and create the Mask. -/// 2. Check return value. -#[cfg(target_pointer_width = "64")] -#[test] -fn ut_mask_new_bit64() { - assert_eq!( - Mask::new(0, 0), - Mask { - mask: 0x0, - shift: 0 - } - ); - assert_eq!( - Mask::new(0, 32), - Mask { - mask: 0x0, - shift: 0 - } - ); - assert_eq!( - Mask::new(0, 64), - Mask { - mask: 0x0, - shift: 0 - } - ); - assert_eq!( - Mask::new(0, 128), - Mask { - mask: 0x0, - shift: 0 - } - ); - assert_eq!( - Mask::new(1, 0), - Mask { - mask: 0x1, - shift: 0 - } - ); - assert_eq!( - Mask::new(1, 32), - Mask { - mask: 0x1_0000_0000, - shift: 32 + fn clear(&mut self) { + self.0 = 0; } - ); - assert_eq!( - Mask::new(1, 63), - Mask { - mask: 0x8000_0000_0000_0000, - shift: 63 - } - ); - assert_eq!( - Mask::new(1, 64), - Mask { - mask: 0x8000_0000_0000_0000, - shift: 63 - } - ); - assert_eq!( - Mask::new(1, 128), - Mask { - mask: 0x8000_0000_0000_0000, - shift: 63 - } - ); - - assert_eq!( - Mask::new(4, 0), - Mask { - mask: 0xf, - shift: 0 - } - ); - assert_eq!( - Mask::new(4, 32), - Mask { - mask: 0xf_0000_0000, - shift: 32 - } - ); - assert_eq!( - Mask::new(4, 60), - Mask { - mask: 0xf000_0000_0000_0000, - shift: 60 - } - ); - assert_eq!( - Mask::new(4, 64), - Mask { - mask: 0xf000_0000_0000_0000, - shift: 60 - } - ); - assert_eq!( - Mask::new(4, 128), - Mask { - mask: 0xf000_0000_0000_0000, - shift: 60 - } - ); - - assert_eq!( - Mask::new(32, 0), - Mask { - mask: 0xffff_ffff, - shift: 0 - } - ); - assert_eq!( - Mask::new(32, 32), - Mask { - mask: 0xffff_ffff_0000_0000, - shift: 32 - } - ); - assert_eq!( - Mask::new(32, 64), - Mask { - mask: 0xffff_ffff_0000_0000, - shift: 32 - } - ); - assert_eq!( - Mask::new(32, 128), - Mask { - mask: 0xffff_ffff_0000_0000, - shift: 32 - } - ); - - assert_eq!( - Mask::new(64, 0), - Mask { - mask: 0xffff_ffff_ffff_ffff, - shift: 0 - } - ); - assert_eq!( - Mask::new(64, 32), - Mask { - mask: 0xffff_ffff_ffff_ffff, - shift: 0 - } - ); - assert_eq!( - Mask::new(64, 64), - Mask { - mask: 0xffff_ffff_ffff_ffff, - shift: 0 - } - ); - assert_eq!( - Mask::new(64, 128), - Mask { - mask: 0xffff_ffff_ffff_ffff, - shift: 0 - } - ); + } + /// UT test cases for mask new function + /// + /// # Brief + /// 1. pass in the parameters, and create the Mask. + /// 2. Check return value. + #[cfg(target_pointer_width = "32")] + #[test] + fn ut_mask_new_bit32() { + assert_eq!( + Mask::new(0, 0), + Mask { + mask: 0x0, + shift: 0 + } + ); + assert_eq!( + Mask::new(0, 16), + Mask { + mask: 0x0, + shift: 0 + } + ); + assert_eq!( + Mask::new(0, 32), + Mask { + mask: 0x0, + shift: 0 + } + ); + assert_eq!( + Mask::new(0, 64), + Mask { + mask: 0x0, + shift: 0 + } + ); + assert_eq!( + Mask::new(1, 0), + Mask { + mask: 0x1, + shift: 0 + } + ); + assert_eq!( + Mask::new(1, 16), + Mask { + mask: 0x1_0000, + shift: 16 + } + ); + assert_eq!( + Mask::new(1, 31), + Mask { + mask: 0x8000_0000, + shift: 31 + } + ); + assert_eq!( + Mask::new(1, 32), + Mask { + mask: 0x8000_0000, + shift: 31 + } + ); + assert_eq!( + Mask::new(1, 128), + Mask { + mask: 0x8000_0000, + shift: 31 + } + ); + assert_eq!( + Mask::new(4, 0), + Mask { + mask: 0xf, + shift: 0 + } + ); + assert_eq!( + Mask::new(4, 16), + Mask { + mask: 0xf_0000, + shift: 16 + } + ); + assert_eq!( + Mask::new(4, 28), + Mask { + mask: 0xf000_0000, + shift: 28 + } + ); + assert_eq!( + Mask::new(4, 32), + Mask { + mask: 0xf000_0000, + shift: 28 + } + ); + assert_eq!( + Mask::new(4, 64), + Mask { + mask: 0xf000_0000, + shift: 28 + } + ); + assert_eq!( + Mask::new(16, 0), + Mask { + mask: 0xffff, + shift: 0 + } + ); + assert_eq!( + Mask::new(16, 16), + Mask { + mask: 0xffff_0000, + shift: 16 + } + ); + assert_eq!( + Mask::new(16, 32), + Mask { + mask: 0xffff_0000, + shift: 16 + } + ); + assert_eq!( + Mask::new(16, 64), + Mask { + mask: 0xffff_0000, + shift: 16 + } + ); + assert_eq!( + Mask::new(32, 0), + Mask { + mask: 0xffff_ffff, + shift: 0 + } + ); + assert_eq!( + Mask::new(32, 16), + Mask { + mask: 0xffff_ffff, + shift: 0 + } + ); + assert_eq!( + Mask::new(32, 32), + Mask { + mask: 0xffff_ffff, + shift: 0 + } + ); + assert_eq!( + Mask::new(32, 64), + Mask { + mask: 0xffff_ffff, + shift: 0 + } + ); + assert_eq!( + Mask::new(64, 0), + Mask { + mask: 0xffff_ffff, + shift: 0 + } + ); + assert_eq!( + Mask::new(64, 16), + Mask { + mask: 0xffff_ffff, + shift: 0 + } + ); + assert_eq!( + Mask::new(64, 32), + Mask { + mask: 0xffff_ffff, + shift: 0 + } + ); + assert_eq!( + Mask::new(64, 64), + Mask { + mask: 0xffff_ffff, + shift: 0 + } + ); + } - assert_eq!( - Mask::new(128, 0), - Mask { - mask: 0xffff_ffff_ffff_ffff, - shift: 0 - } - ); - assert_eq!( - Mask::new(128, 32), - Mask { - mask: 0xffff_ffff_ffff_ffff, - shift: 0 - } - ); - assert_eq!( - Mask::new(128, 64), - Mask { - mask: 0xffff_ffff_ffff_ffff, - shift: 0 - } - ); - assert_eq!( - Mask::new(128, 128), - Mask { - mask: 0xffff_ffff_ffff_ffff, - shift: 0 - } - ); -} + /// UT test cases for mask new function + /// + /// # Brief + /// 1. pass in the parameters, and create the Mask. + /// 2. Check return value. + #[cfg(target_pointer_width = "64")] + #[test] + fn ut_mask_new_bit64() { + assert_eq!( + Mask::new(0, 0), + Mask { + mask: 0x0, + shift: 0 + } + ); + assert_eq!( + Mask::new(0, 32), + Mask { + mask: 0x0, + shift: 0 + } + ); + assert_eq!( + Mask::new(0, 64), + Mask { + mask: 0x0, + shift: 0 + } + ); + assert_eq!( + Mask::new(0, 128), + Mask { + mask: 0x0, + shift: 0 + } + ); + + assert_eq!( + Mask::new(1, 0), + Mask { + mask: 0x1, + shift: 0 + } + ); + assert_eq!( + Mask::new(1, 32), + Mask { + mask: 0x1_0000_0000, + shift: 32 + } + ); + assert_eq!( + Mask::new(1, 63), + Mask { + mask: 0x8000_0000_0000_0000, + shift: 63 + } + ); + assert_eq!( + Mask::new(1, 64), + Mask { + mask: 0x8000_0000_0000_0000, + shift: 63 + } + ); + assert_eq!( + Mask::new(1, 128), + Mask { + mask: 0x8000_0000_0000_0000, + shift: 63 + } + ); + + assert_eq!( + Mask::new(4, 0), + Mask { + mask: 0xf, + shift: 0 + } + ); + assert_eq!( + Mask::new(4, 32), + Mask { + mask: 0xf_0000_0000, + shift: 32 + } + ); + assert_eq!( + Mask::new(4, 60), + Mask { + mask: 0xf000_0000_0000_0000, + shift: 60 + } + ); + assert_eq!( + Mask::new(4, 64), + Mask { + mask: 0xf000_0000_0000_0000, + shift: 60 + } + ); + assert_eq!( + Mask::new(4, 128), + Mask { + mask: 0xf000_0000_0000_0000, + shift: 60 + } + ); + + assert_eq!( + Mask::new(32, 0), + Mask { + mask: 0xffff_ffff, + shift: 0 + } + ); + assert_eq!( + Mask::new(32, 32), + Mask { + mask: 0xffff_ffff_0000_0000, + shift: 32 + } + ); + assert_eq!( + Mask::new(32, 64), + Mask { + mask: 0xffff_ffff_0000_0000, + shift: 32 + } + ); + assert_eq!( + Mask::new(32, 128), + Mask { + mask: 0xffff_ffff_0000_0000, + shift: 32 + } + ); + + assert_eq!( + Mask::new(64, 0), + Mask { + mask: 0xffff_ffff_ffff_ffff, + shift: 0 + } + ); + assert_eq!( + Mask::new(64, 32), + Mask { + mask: 0xffff_ffff_ffff_ffff, + shift: 0 + } + ); + assert_eq!( + Mask::new(64, 64), + Mask { + mask: 0xffff_ffff_ffff_ffff, + shift: 0 + } + ); + assert_eq!( + Mask::new(64, 128), + Mask { + mask: 0xffff_ffff_ffff_ffff, + shift: 0 + } + ); + + assert_eq!( + Mask::new(128, 0), + Mask { + mask: 0xffff_ffff_ffff_ffff, + shift: 0 + } + ); + assert_eq!( + Mask::new(128, 32), + Mask { + mask: 0xffff_ffff_ffff_ffff, + shift: 0 + } + ); + assert_eq!( + Mask::new(128, 64), + Mask { + mask: 0xffff_ffff_ffff_ffff, + shift: 0 + } + ); + assert_eq!( + Mask::new(128, 128), + Mask { + mask: 0xffff_ffff_ffff_ffff, + shift: 0 + } + ); + } -/// UT test cases for bit from_usize function -/// -/// # Brief -/// 1. Pass in any usize, call from_usize, and check the return value. -#[test] -fn ut_bit_from_usize() { - const USIZE_MAX: usize = 0usize.wrapping_sub(1); - const USIZE_MAX_HALF: usize = 0usize.wrapping_sub(1) / 2; - - assert_eq!(Bit::from_usize(0), Bit(0)); - assert_eq!(Bit::from_usize(USIZE_MAX_HALF), Bit(USIZE_MAX_HALF)); - assert_eq!(Bit::from_usize(USIZE_MAX), Bit(USIZE_MAX)); -} + /// UT test cases for bit from_usize function + /// + /// # Brief + /// 1. Pass in any usize, call from_usize, and check the return value. + #[test] + fn ut_bit_from_usize() { + const USIZE_MAX: usize = 0usize.wrapping_sub(1); + const USIZE_MAX_HALF: usize = 0usize.wrapping_sub(1) / 2; + + assert_eq!(Bit::from_usize(0), Bit(0)); + assert_eq!(Bit::from_usize(USIZE_MAX_HALF), Bit(USIZE_MAX_HALF)); + assert_eq!(Bit::from_usize(USIZE_MAX), Bit(USIZE_MAX)); + } -/// UT test cases for bit as_usize function -/// -/// # Brief -/// 1. Creating a Bit Instance. -/// 2. Call as_usize. -/// 3. Check return value. -#[test] -fn ut_bit_as_usize() { - const USIZE_MAX: usize = 0usize.wrapping_sub(1); - const USIZE_MAX_HALF: usize = 0usize.wrapping_sub(1) / 2; - - assert_eq!(Bit::from_usize(0).as_usize(), 0); - assert_eq!(Bit::from_usize(USIZE_MAX_HALF).as_usize(), USIZE_MAX_HALF); - assert_eq!(Bit::from_usize(USIZE_MAX).as_usize(), USIZE_MAX); -} + /// UT test cases for bit as_usize function + /// + /// # Brief + /// 1. Creating a Bit Instance. + /// 2. Call as_usize. + /// 3. Check return value. + #[test] + fn ut_bit_as_usize() { + const USIZE_MAX: usize = 0usize.wrapping_sub(1); + const USIZE_MAX_HALF: usize = 0usize.wrapping_sub(1) / 2; + + assert_eq!(Bit::from_usize(0).as_usize(), 0); + assert_eq!(Bit::from_usize(USIZE_MAX_HALF).as_usize(), USIZE_MAX_HALF); + assert_eq!(Bit::from_usize(USIZE_MAX).as_usize(), USIZE_MAX); + } -/// UT test cases for bit set function -/// -/// # Brief -/// 1. Creating a Bit Instance. -/// 2. Call the set function and pass in a new usize. -/// 3. Check return value. -#[test] -fn ut_bit_set() { - const USIZE_MAX: usize = 0usize.wrapping_sub(1); - const USIZE_MAX_HALF: usize = 0usize.wrapping_sub(1) / 2; - - let mut b = Bit::from_usize(0); - b.set(0xf0f0); - assert_eq!(b.as_usize(), 0xf0f0); - - let mut b = Bit::from_usize(USIZE_MAX_HALF); - b.set(0xf0f0); - assert_eq!(b.as_usize(), 0xf0f0); - - let mut b = Bit::from_usize(USIZE_MAX); - b.set(0xf0f0); - assert_eq!(b.as_usize(), 0xf0f0); -} + /// UT test cases for bit set function + /// + /// # Brief + /// 1. Creating a Bit Instance. + /// 2. Call the set function and pass in a new usize. + /// 3. Check return value. + #[test] + fn ut_bit_set() { + const USIZE_MAX: usize = 0usize.wrapping_sub(1); + const USIZE_MAX_HALF: usize = 0usize.wrapping_sub(1) / 2; + + let mut b = Bit::from_usize(0); + b.set(0xf0f0); + assert_eq!(b.as_usize(), 0xf0f0); + + let mut b = Bit::from_usize(USIZE_MAX_HALF); + b.set(0xf0f0); + assert_eq!(b.as_usize(), 0xf0f0); + + let mut b = Bit::from_usize(USIZE_MAX); + b.set(0xf0f0); + assert_eq!(b.as_usize(), 0xf0f0); + } -/// UT test cases for bit clear function -/// -/// # Brief -/// 1. Creating a Bit Instance. -/// 2. Call clear(). -/// 3. Calibrate the instance. -#[test] -fn ut_bit_clear() { - const USIZE_MAX: usize = 0usize.wrapping_sub(1); - const USIZE_MAX_HALF: usize = 0usize.wrapping_sub(1) / 2; - - let mut b = Bit::from_usize(0); - b.clear(); - assert_eq!(b.as_usize(), 0); - - let mut b = Bit::from_usize(USIZE_MAX_HALF); - b.clear(); - assert_eq!(b.as_usize(), 0); - - let mut b = Bit::from_usize(USIZE_MAX); - b.clear(); - assert_eq!(b.as_usize(), 0); -} + /// UT test cases for bit clear function + /// + /// # Brief + /// 1. Creating a Bit Instance. + /// 2. Call clear(). + /// 3. Calibrate the instance. + #[test] + fn ut_bit_clear() { + const USIZE_MAX: usize = 0usize.wrapping_sub(1); + const USIZE_MAX_HALF: usize = 0usize.wrapping_sub(1) / 2; + + let mut b = Bit::from_usize(0); + b.clear(); + assert_eq!(b.as_usize(), 0); + + let mut b = Bit::from_usize(USIZE_MAX_HALF); + b.clear(); + assert_eq!(b.as_usize(), 0); + + let mut b = Bit::from_usize(USIZE_MAX); + b.clear(); + assert_eq!(b.as_usize(), 0); + } -/// UT test cases for bit set_by_mask function -/// -/// # Brief -/// 1. Create a Bit instance, create a Mask instance. -/// 2. Call set_by_mask(). -/// 3. Verify the Bit instance. -#[cfg(target_pointer_width = "32")] -#[test] -fn ut_bit_set_by_mask_bit32() { - let val = 0x0usize; - let mut bit = Bit::from_usize(val); - bit.set_by_mask(Mask::new(0, 0), 0x0); - assert_eq!(bit, Bit::from_usize(0x0)); - - bit.clear(); - bit.set_by_mask(Mask::new(4, 0), 0xf); - assert_eq!(bit, Bit::from_usize(0xf)); - - bit.clear(); - bit.set_by_mask(Mask::new(8, 0), 0xff); - assert_eq!(bit, Bit::from_usize(0xff)); - - bit.clear(); - bit.set_by_mask(Mask::new(4, 4), 0xf); - assert_eq!(bit, Bit::from_usize(0xf0)); - - bit.clear(); - bit.set_by_mask(Mask::new(4, 28), 0xf); - assert_eq!(bit, Bit::from_usize(0xf000_0000)); - - bit.clear(); - bit.set_by_mask(Mask::new(0, 0), 0xffff_ffff); - assert_eq!(bit, Bit::from_usize(0x0)); - - bit.clear(); - bit.set_by_mask(Mask::new(4, 0), 0xffff_ffff); - assert_eq!(bit, Bit::from_usize(0xf)); - - bit.clear(); - bit.set_by_mask(Mask::new(4, 4), 0xffff_ffff); - assert_eq!(bit, Bit::from_usize(0xf0)); - - let val = 0xffff_ffff; - let mut bit = Bit::from_usize(val); - bit.set_by_mask(Mask::new(0, 0), 0x0); - assert_eq!(bit, Bit::from_usize(0xffff_ffff)); - - bit.set(val); - bit.set_by_mask(Mask::new(4, 0), 0x0); - assert_eq!(bit, Bit::from_usize(0xffff_fff0)); - - bit.set(val); - bit.set_by_mask(Mask::new(4, 4), 0x0); - assert_eq!(bit, Bit::from_usize(0xffff_ff0f)); - - bit.set(val); - bit.set_by_mask(Mask::new(4, 8), 0x0); - assert_eq!(bit, Bit::from_usize(0xffff_f0ff)); - - bit.set(val); - bit.set_by_mask(Mask::new(4, 0), 0xabcd); - assert_eq!(bit, Bit::from_usize(0xffff_fffd)); - - bit.set(val); - bit.set_by_mask(Mask::new(8, 0), 0xabcd); - assert_eq!(bit, Bit::from_usize(0xffff_ffcd)); - - bit.set(val); - bit.set_by_mask(Mask::new(16, 0), 0xabcd); - assert_eq!(bit, Bit::from_usize(0xffff_abcd)); - - bit.set(val); - bit.set_by_mask(Mask::new(16, 16), 0xabcd); - assert_eq!(bit, Bit::from_usize(0xabcd_ffff)); - - bit.set(val); - bit.set_by_mask(Mask::new(32, 0), 0xabcd); - assert_eq!(bit, Bit::from_usize(0x0000_abcd)); -} + /// UT test cases for bit set_by_mask function + /// + /// # Brief + /// 1. Create a Bit instance, create a Mask instance. + /// 2. Call set_by_mask(). + /// 3. Verify the Bit instance. + #[cfg(target_pointer_width = "32")] + #[test] + fn ut_bit_set_by_mask_bit32() { + let val = 0x0usize; + let mut bit = Bit::from_usize(val); + bit.set_by_mask(Mask::new(0, 0), 0x0); + assert_eq!(bit, Bit::from_usize(0x0)); + + bit.clear(); + bit.set_by_mask(Mask::new(4, 0), 0xf); + assert_eq!(bit, Bit::from_usize(0xf)); + + bit.clear(); + bit.set_by_mask(Mask::new(8, 0), 0xff); + assert_eq!(bit, Bit::from_usize(0xff)); + + bit.clear(); + bit.set_by_mask(Mask::new(4, 4), 0xf); + assert_eq!(bit, Bit::from_usize(0xf0)); + + bit.clear(); + bit.set_by_mask(Mask::new(4, 28), 0xf); + assert_eq!(bit, Bit::from_usize(0xf000_0000)); + + bit.clear(); + bit.set_by_mask(Mask::new(0, 0), 0xffff_ffff); + assert_eq!(bit, Bit::from_usize(0x0)); + + bit.clear(); + bit.set_by_mask(Mask::new(4, 0), 0xffff_ffff); + assert_eq!(bit, Bit::from_usize(0xf)); + + bit.clear(); + bit.set_by_mask(Mask::new(4, 4), 0xffff_ffff); + assert_eq!(bit, Bit::from_usize(0xf0)); + + let val = 0xffff_ffff; + let mut bit = Bit::from_usize(val); + bit.set_by_mask(Mask::new(0, 0), 0x0); + assert_eq!(bit, Bit::from_usize(0xffff_ffff)); + + bit.set(val); + bit.set_by_mask(Mask::new(4, 0), 0x0); + assert_eq!(bit, Bit::from_usize(0xffff_fff0)); + + bit.set(val); + bit.set_by_mask(Mask::new(4, 4), 0x0); + assert_eq!(bit, Bit::from_usize(0xffff_ff0f)); + + bit.set(val); + bit.set_by_mask(Mask::new(4, 8), 0x0); + assert_eq!(bit, Bit::from_usize(0xffff_f0ff)); + + bit.set(val); + bit.set_by_mask(Mask::new(4, 0), 0xabcd); + assert_eq!(bit, Bit::from_usize(0xffff_fffd)); + + bit.set(val); + bit.set_by_mask(Mask::new(8, 0), 0xabcd); + assert_eq!(bit, Bit::from_usize(0xffff_ffcd)); + + bit.set(val); + bit.set_by_mask(Mask::new(16, 0), 0xabcd); + assert_eq!(bit, Bit::from_usize(0xffff_abcd)); + + bit.set(val); + bit.set_by_mask(Mask::new(16, 16), 0xabcd); + assert_eq!(bit, Bit::from_usize(0xabcd_ffff)); + + bit.set(val); + bit.set_by_mask(Mask::new(32, 0), 0xabcd); + assert_eq!(bit, Bit::from_usize(0x0000_abcd)); + } -/// UT test cases for bit set_by_mask function -/// -/// # Brief -/// 1. Create a Bit instance, create a Mask instance. -/// 2. Call set_by_mask(). -/// 3. Verify the Bit instance. -#[cfg(target_pointer_width = "64")] -#[test] -fn ut_bit_set_by_mask_bit64() { - let val = 0x0usize; - let mut bit = Bit::from_usize(val); - bit.set_by_mask(Mask::new(0, 0), 0x0); - assert_eq!(bit, Bit::from_usize(0x0)); - - bit.clear(); - bit.set_by_mask(Mask::new(4, 0), 0xf); - assert_eq!(bit, Bit::from_usize(0xf)); - - bit.clear(); - bit.set_by_mask(Mask::new(8, 0), 0xff); - assert_eq!(bit, Bit::from_usize(0xff)); - - bit.clear(); - bit.set_by_mask(Mask::new(4, 4), 0xf); - assert_eq!(bit, Bit::from_usize(0xf0)); - - bit.clear(); - bit.set_by_mask(Mask::new(4, 32), 0xf); - assert_eq!(bit, Bit::from_usize(0xf_0000_0000)); - - bit.clear(); - bit.set_by_mask(Mask::new(4, 0), 0xffff_ffff_ffff_ffff); - assert_eq!(bit, Bit::from_usize(0xf)); - - bit.clear(); - bit.set_by_mask(Mask::new(4, 4), 0xffff_ffff_ffff_ffff); - assert_eq!(bit, Bit::from_usize(0xf0)); - - bit.clear(); - bit.set_by_mask(Mask::new(0, 0), 0xffff_ffff_ffff_ffff); - assert_eq!(bit, Bit::from_usize(0)); - - let val = 0xffff_ffff_ffff_ffffusize; - let mut bit = Bit::from_usize(val); - bit.set_by_mask(Mask::new(0, 0), 0x0); - assert_eq!(bit, Bit::from_usize(0xffff_ffff_ffff_ffff)); - - bit.set(0xffff_ffff_ffff_ffff); - bit.set_by_mask(Mask::new(4, 0), 0x0); - assert_eq!(bit, Bit::from_usize(0xffff_ffff_ffff_fff0)); - - bit.set(0xffff_ffff_ffff_ffff); - bit.set_by_mask(Mask::new(4, 4), 0x0); - assert_eq!(bit, Bit::from_usize(0xffff_ffff_ffff_ff0f)); - - bit.set(0xffff_ffff_ffff_ffff); - bit.set_by_mask(Mask::new(4, 32), 0x0); - assert_eq!(bit, Bit::from_usize(0xffff_fff0_ffff_ffff)); - - bit.set(0xffff_ffff_ffff_ffff); - bit.set_by_mask(Mask::new(4, 60), 0x0); - assert_eq!(bit, Bit::from_usize(0x0fff_ffff_ffff_ffff)); - - bit.set(0xffff_ffff_ffff_ffff); - bit.set_by_mask(Mask::new(16, 0), 0xabcd); - assert_eq!(bit, Bit::from_usize(0xffff_ffff_ffff_abcd)); - - bit.set(0xffff_ffff_ffff_ffff); - bit.set_by_mask(Mask::new(32, 0), 0xabcd); - assert_eq!(bit, Bit::from_usize(0xffff_ffff_0000_abcd)); - - bit.set(0xffff_ffff_ffff_ffff); - bit.set_by_mask(Mask::new(12, 0), 0xabcd); - assert_eq!(bit, Bit::from_usize(0xffff_ffff_ffff_fbcd)); - - bit.set(0xffff_ffff_ffff_ffff); - bit.set_by_mask(Mask::new(16, 8), 0xabcd); - assert_eq!(bit, Bit::from_usize(0xffff_ffff_ffab_cdff)); -} + /// UT test cases for bit set_by_mask function + /// + /// # Brief + /// 1. Create a Bit instance, create a Mask instance. + /// 2. Call set_by_mask(). + /// 3. Verify the Bit instance. + #[cfg(target_pointer_width = "64")] + #[test] + fn ut_bit_set_by_mask_bit64() { + let val = 0x0usize; + let mut bit = Bit::from_usize(val); + bit.set_by_mask(Mask::new(0, 0), 0x0); + assert_eq!(bit, Bit::from_usize(0x0)); + + bit.clear(); + bit.set_by_mask(Mask::new(4, 0), 0xf); + assert_eq!(bit, Bit::from_usize(0xf)); + + bit.clear(); + bit.set_by_mask(Mask::new(8, 0), 0xff); + assert_eq!(bit, Bit::from_usize(0xff)); + + bit.clear(); + bit.set_by_mask(Mask::new(4, 4), 0xf); + assert_eq!(bit, Bit::from_usize(0xf0)); + + bit.clear(); + bit.set_by_mask(Mask::new(4, 32), 0xf); + assert_eq!(bit, Bit::from_usize(0xf_0000_0000)); + + bit.clear(); + bit.set_by_mask(Mask::new(4, 0), 0xffff_ffff_ffff_ffff); + assert_eq!(bit, Bit::from_usize(0xf)); + + bit.clear(); + bit.set_by_mask(Mask::new(4, 4), 0xffff_ffff_ffff_ffff); + assert_eq!(bit, Bit::from_usize(0xf0)); + + bit.clear(); + bit.set_by_mask(Mask::new(0, 0), 0xffff_ffff_ffff_ffff); + assert_eq!(bit, Bit::from_usize(0)); + + let val = 0xffff_ffff_ffff_ffffusize; + let mut bit = Bit::from_usize(val); + bit.set_by_mask(Mask::new(0, 0), 0x0); + assert_eq!(bit, Bit::from_usize(0xffff_ffff_ffff_ffff)); + + bit.set(0xffff_ffff_ffff_ffff); + bit.set_by_mask(Mask::new(4, 0), 0x0); + assert_eq!(bit, Bit::from_usize(0xffff_ffff_ffff_fff0)); + + bit.set(0xffff_ffff_ffff_ffff); + bit.set_by_mask(Mask::new(4, 4), 0x0); + assert_eq!(bit, Bit::from_usize(0xffff_ffff_ffff_ff0f)); + + bit.set(0xffff_ffff_ffff_ffff); + bit.set_by_mask(Mask::new(4, 32), 0x0); + assert_eq!(bit, Bit::from_usize(0xffff_fff0_ffff_ffff)); + + bit.set(0xffff_ffff_ffff_ffff); + bit.set_by_mask(Mask::new(4, 60), 0x0); + assert_eq!(bit, Bit::from_usize(0x0fff_ffff_ffff_ffff)); + + bit.set(0xffff_ffff_ffff_ffff); + bit.set_by_mask(Mask::new(16, 0), 0xabcd); + assert_eq!(bit, Bit::from_usize(0xffff_ffff_ffff_abcd)); + + bit.set(0xffff_ffff_ffff_ffff); + bit.set_by_mask(Mask::new(32, 0), 0xabcd); + assert_eq!(bit, Bit::from_usize(0xffff_ffff_0000_abcd)); + + bit.set(0xffff_ffff_ffff_ffff); + bit.set_by_mask(Mask::new(12, 0), 0xabcd); + assert_eq!(bit, Bit::from_usize(0xffff_ffff_ffff_fbcd)); + + bit.set(0xffff_ffff_ffff_ffff); + bit.set_by_mask(Mask::new(16, 8), 0xabcd); + assert_eq!(bit, Bit::from_usize(0xffff_ffff_ffab_cdff)); + } -/// UT test cases for bit get_by_mask function -/// -/// # Brief -/// 1. Create a Bit instance, create a Mask instance. -/// 2. Call get_by_mask(). -/// 3. Check return value. -#[cfg(target_pointer_width = "32")] -#[test] -fn ut_bit_get_by_mask_bit32() { - let val = 0x0usize; - let bit = Bit::from_usize(val); - assert_eq!(bit.get_by_mask(Mask::new(0, 0)), 0x0); - assert_eq!(bit.get_by_mask(Mask::new(1, 0)), 0x0); - assert_eq!(bit.get_by_mask(Mask::new(16, 0)), 0x0); - assert_eq!(bit.get_by_mask(Mask::new(32, 0)), 0x0); - - let val = 0xffff_ffffusize; - let bit = Bit::from_usize(val); - assert_eq!(bit.get_by_mask(Mask::new(0, 0)), 0x0); - assert_eq!(bit.get_by_mask(Mask::new(1, 0)), 0x1); - assert_eq!(bit.get_by_mask(Mask::new(16, 0)), 0xffff); - assert_eq!(bit.get_by_mask(Mask::new(32, 0)), 0xffff_ffff); - - let val = 0x1234_cdefusize; - let bit = Bit::from_usize(val); - assert_eq!(bit.get_by_mask(Mask::new(0, 0)), 0x0); - assert_eq!(bit.get_by_mask(Mask::new(4, 0)), 0xf); - assert_eq!(bit.get_by_mask(Mask::new(8, 0)), 0xef); - assert_eq!(bit.get_by_mask(Mask::new(12, 0)), 0xdef); - assert_eq!(bit.get_by_mask(Mask::new(16, 0)), 0xcdef); - assert_eq!(bit.get_by_mask(Mask::new(32, 0)), 0x1234_cdef); - assert_eq!(bit.get_by_mask(Mask::new(4, 4)), 0xe); - assert_eq!(bit.get_by_mask(Mask::new(8, 4)), 0xde); - assert_eq!(bit.get_by_mask(Mask::new(12, 4)), 0xcde); - assert_eq!(bit.get_by_mask(Mask::new(4, 16)), 0x4); - assert_eq!(bit.get_by_mask(Mask::new(8, 16)), 0x34); - assert_eq!(bit.get_by_mask(Mask::new(12, 16)), 0x234); - assert_eq!(bit.get_by_mask(Mask::new(3, 0)), 0x7); - assert_eq!(bit.get_by_mask(Mask::new(3, 4)), 0x6); - assert_eq!(bit.get_by_mask(Mask::new(3, 8)), 0x5); - assert_eq!(bit.get_by_mask(Mask::new(3, 16)), 0x4); - assert_eq!(bit.get_by_mask(Mask::new(3, 20)), 0x3); - assert_eq!(bit.get_by_mask(Mask::new(3, 24)), 0x2); - assert_eq!(bit.get_by_mask(Mask::new(3, 1)), 0x7); - assert_eq!(bit.get_by_mask(Mask::new(3, 5)), 0x7); - assert_eq!(bit.get_by_mask(Mask::new(3, 9)), 0x6); -} + /// UT test cases for bit get_by_mask function + /// + /// # Brief + /// 1. Create a Bit instance, create a Mask instance. + /// 2. Call get_by_mask(). + /// 3. Check return value. + #[cfg(target_pointer_width = "32")] + #[test] + fn ut_bit_get_by_mask_bit32() { + let val = 0x0usize; + let bit = Bit::from_usize(val); + assert_eq!(bit.get_by_mask(Mask::new(0, 0)), 0x0); + assert_eq!(bit.get_by_mask(Mask::new(1, 0)), 0x0); + assert_eq!(bit.get_by_mask(Mask::new(16, 0)), 0x0); + assert_eq!(bit.get_by_mask(Mask::new(32, 0)), 0x0); + + let val = 0xffff_ffffusize; + let bit = Bit::from_usize(val); + assert_eq!(bit.get_by_mask(Mask::new(0, 0)), 0x0); + assert_eq!(bit.get_by_mask(Mask::new(1, 0)), 0x1); + assert_eq!(bit.get_by_mask(Mask::new(16, 0)), 0xffff); + assert_eq!(bit.get_by_mask(Mask::new(32, 0)), 0xffff_ffff); + + let val = 0x1234_cdefusize; + let bit = Bit::from_usize(val); + assert_eq!(bit.get_by_mask(Mask::new(0, 0)), 0x0); + assert_eq!(bit.get_by_mask(Mask::new(4, 0)), 0xf); + assert_eq!(bit.get_by_mask(Mask::new(8, 0)), 0xef); + assert_eq!(bit.get_by_mask(Mask::new(12, 0)), 0xdef); + assert_eq!(bit.get_by_mask(Mask::new(16, 0)), 0xcdef); + assert_eq!(bit.get_by_mask(Mask::new(32, 0)), 0x1234_cdef); + assert_eq!(bit.get_by_mask(Mask::new(4, 4)), 0xe); + assert_eq!(bit.get_by_mask(Mask::new(8, 4)), 0xde); + assert_eq!(bit.get_by_mask(Mask::new(12, 4)), 0xcde); + assert_eq!(bit.get_by_mask(Mask::new(4, 16)), 0x4); + assert_eq!(bit.get_by_mask(Mask::new(8, 16)), 0x34); + assert_eq!(bit.get_by_mask(Mask::new(12, 16)), 0x234); + assert_eq!(bit.get_by_mask(Mask::new(3, 0)), 0x7); + assert_eq!(bit.get_by_mask(Mask::new(3, 4)), 0x6); + assert_eq!(bit.get_by_mask(Mask::new(3, 8)), 0x5); + assert_eq!(bit.get_by_mask(Mask::new(3, 16)), 0x4); + assert_eq!(bit.get_by_mask(Mask::new(3, 20)), 0x3); + assert_eq!(bit.get_by_mask(Mask::new(3, 24)), 0x2); + assert_eq!(bit.get_by_mask(Mask::new(3, 1)), 0x7); + assert_eq!(bit.get_by_mask(Mask::new(3, 5)), 0x7); + assert_eq!(bit.get_by_mask(Mask::new(3, 9)), 0x6); + } -/// UT test cases for bit get_by_mask function -/// -/// # Brief -/// 1. Create a Bit instance, create a Mask instance. -/// 2. Call get_by_mask(). -/// 3. Check return value. -#[cfg(target_pointer_width = "64")] -#[test] -fn ut_bit_get_by_mask_bit64() { - let val = 0x0usize; - let bit = Bit::from_usize(val); - assert_eq!(bit.get_by_mask(Mask::new(0, 0)), 0x0); - assert_eq!(bit.get_by_mask(Mask::new(1, 0)), 0x0); - assert_eq!(bit.get_by_mask(Mask::new(32, 0)), 0x0); - assert_eq!(bit.get_by_mask(Mask::new(64, 0)), 0x0); - - let val = 0xffff_ffff_ffff_ffffusize; - let bit = Bit::from_usize(val); - assert_eq!(bit.get_by_mask(Mask::new(0, 0)), 0x0); - assert_eq!(bit.get_by_mask(Mask::new(1, 0)), 0x1); - assert_eq!(bit.get_by_mask(Mask::new(32, 0)), 0xffff_ffff); - assert_eq!(bit.get_by_mask(Mask::new(64, 0)), 0xffff_ffff_ffff_ffff); - - let val = 0x0123_4567_89ab_cdefusize; - let bit = Bit::from_usize(val); - assert_eq!(bit.get_by_mask(Mask::new(0, 0)), 0x0); - assert_eq!(bit.get_by_mask(Mask::new(4, 0)), 0xf); - assert_eq!(bit.get_by_mask(Mask::new(8, 0)), 0xef); - assert_eq!(bit.get_by_mask(Mask::new(32, 0)), 0x89ab_cdef); - assert_eq!(bit.get_by_mask(Mask::new(64, 0)), 0x0123_4567_89ab_cdef); - assert_eq!(bit.get_by_mask(Mask::new(4, 4)), 0xe); - assert_eq!(bit.get_by_mask(Mask::new(8, 4)), 0xde); - assert_eq!(bit.get_by_mask(Mask::new(12, 4)), 0xcde); - assert_eq!(bit.get_by_mask(Mask::new(60, 4)), 0x0012_3456_789a_bcde); - assert_eq!(bit.get_by_mask(Mask::new(4, 32)), 0x7); - assert_eq!(bit.get_by_mask(Mask::new(8, 32)), 0x67); - assert_eq!(bit.get_by_mask(Mask::new(12, 32)), 0x567); - assert_eq!(bit.get_by_mask(Mask::new(3, 0)), 0x7); - assert_eq!(bit.get_by_mask(Mask::new(3, 4)), 0x6); - assert_eq!(bit.get_by_mask(Mask::new(3, 8)), 0x5); - assert_eq!(bit.get_by_mask(Mask::new(3, 1)), 0x7); - assert_eq!(bit.get_by_mask(Mask::new(3, 5)), 0x7); - assert_eq!(bit.get_by_mask(Mask::new(3, 9)), 0x6); + /// UT test cases for bit get_by_mask function + /// + /// # Brief + /// 1. Create a Bit instance, create a Mask instance. + /// 2. Call get_by_mask(). + /// 3. Check return value. + #[cfg(target_pointer_width = "64")] + #[test] + fn ut_bit_get_by_mask_bit64() { + let val = 0x0usize; + let bit = Bit::from_usize(val); + assert_eq!(bit.get_by_mask(Mask::new(0, 0)), 0x0); + assert_eq!(bit.get_by_mask(Mask::new(1, 0)), 0x0); + assert_eq!(bit.get_by_mask(Mask::new(32, 0)), 0x0); + assert_eq!(bit.get_by_mask(Mask::new(64, 0)), 0x0); + + let val = 0xffff_ffff_ffff_ffffusize; + let bit = Bit::from_usize(val); + assert_eq!(bit.get_by_mask(Mask::new(0, 0)), 0x0); + assert_eq!(bit.get_by_mask(Mask::new(1, 0)), 0x1); + assert_eq!(bit.get_by_mask(Mask::new(32, 0)), 0xffff_ffff); + assert_eq!(bit.get_by_mask(Mask::new(64, 0)), 0xffff_ffff_ffff_ffff); + + let val = 0x0123_4567_89ab_cdefusize; + let bit = Bit::from_usize(val); + assert_eq!(bit.get_by_mask(Mask::new(0, 0)), 0x0); + assert_eq!(bit.get_by_mask(Mask::new(4, 0)), 0xf); + assert_eq!(bit.get_by_mask(Mask::new(8, 0)), 0xef); + assert_eq!(bit.get_by_mask(Mask::new(32, 0)), 0x89ab_cdef); + assert_eq!(bit.get_by_mask(Mask::new(64, 0)), 0x0123_4567_89ab_cdef); + assert_eq!(bit.get_by_mask(Mask::new(4, 4)), 0xe); + assert_eq!(bit.get_by_mask(Mask::new(8, 4)), 0xde); + assert_eq!(bit.get_by_mask(Mask::new(12, 4)), 0xcde); + assert_eq!(bit.get_by_mask(Mask::new(60, 4)), 0x0012_3456_789a_bcde); + assert_eq!(bit.get_by_mask(Mask::new(4, 32)), 0x7); + assert_eq!(bit.get_by_mask(Mask::new(8, 32)), 0x67); + assert_eq!(bit.get_by_mask(Mask::new(12, 32)), 0x567); + assert_eq!(bit.get_by_mask(Mask::new(3, 0)), 0x7); + assert_eq!(bit.get_by_mask(Mask::new(3, 4)), 0x6); + assert_eq!(bit.get_by_mask(Mask::new(3, 8)), 0x5); + assert_eq!(bit.get_by_mask(Mask::new(3, 1)), 0x7); + assert_eq!(bit.get_by_mask(Mask::new(3, 5)), 0x7); + assert_eq!(bit.get_by_mask(Mask::new(3, 9)), 0x6); + } } diff --git a/ylong_runtime/src/util/core_affinity/linux.rs b/ylong_runtime/src/util/core_affinity/linux.rs index 2f703aba4bc536b7a7ea2ff92b9a052f18cff7d6..7032f485ccd84fc5a64287322c08ff0c91ca786d 100644 --- a/ylong_runtime/src/util/core_affinity/linux.rs +++ b/ylong_runtime/src/util/core_affinity/linux.rs @@ -16,16 +16,14 @@ use std::io::{Error, Result}; use std::mem::{size_of, zeroed}; -use libc::{cpu_set_t, sched_getaffinity, sched_setaffinity, CPU_ISSET, CPU_SET}; - -use crate::util::num_cpus::get_cpu_num; +use libc::{cpu_set_t, sched_setaffinity, CPU_SET}; /// Sets the tied core cpu of the current thread. /// /// sched_setaffinity function under linux /// # Example /// -/// ```rust +/// ```no run /// use ylong_runtime::util::core_affinity; /// /// let ret = core_affinity::set_current_affinity(0).is_ok(); @@ -42,77 +40,7 @@ pub fn set_current_affinity(cpu: usize) -> Result<()> { } } -/// Gets the cores tied to the current thread, -/// or returns all available cpu's if no cores have been tied. -/// -/// sched_setaffinity function under linux -/// # Example 1 -/// -/// ```rust -/// use ylong_runtime::util::core_affinity; -/// -/// let cpus: Vec = core_affinity::get_current_affinity(); -/// assert!(cpus.len() > 0); -/// ``` -/// # Example 2 -/// -/// ```rust -/// use ylong_runtime::util::core_affinity; -/// -/// let ret = core_affinity::set_current_affinity(0).is_ok(); -/// assert!(ret); -/// let cpus: Vec = core_affinity::get_current_affinity(); -/// assert_eq!(cpus.len(), 1); -/// ``` -pub fn get_current_affinity() -> Vec { - unsafe { - let mut vec = vec![]; - let cpus = get_cpu_num() as usize; - let mut set = new_cpu_set(); - sched_getaffinity(0, size_of::(), &mut set); - for i in 0..cpus { - if CPU_ISSET(i, &set) { - vec.push(i); - } - } - vec - } -} - -/// Gets the cores bound to the specified thread, or return all available cpu's -/// if no cores are bound -/// -/// sched_setaffinity function under linux -pub fn get_other_thread_affinity(pid: i32) -> Vec { - unsafe { - let mut vec = vec![]; - let cpus = get_cpu_num() as usize; - let mut set = new_cpu_set(); - sched_getaffinity(pid, size_of::(), &mut set); - for i in 0..cpus { - if CPU_ISSET(i, &set) { - vec.push(i); - } - } - vec - } -} - /// Returns an empty cpu set fn new_cpu_set() -> cpu_set_t { unsafe { zeroed::() } } - -#[cfg(test)] -mod test { - /// UT test cases for get_other_thread_affinity usage - /// - /// # Brief - /// 1. Uses get_other_thread_affinity() to get thread affinity. - /// 2. Returns all available cpu's because no cores are bound. - #[test] - fn ut_core_affinity_other_thread() { - let cpus: Vec = crate::util::core_affinity::get_other_thread_affinity(0); - assert!(!cpus.is_empty()); - } -} diff --git a/ylong_runtime/src/util/core_affinity/windows.rs b/ylong_runtime/src/util/core_affinity/windows.rs index 577a548910a0e3db4b6d2ee1a0cef8dbbbdaa790..41ddc67a1c0f0515c477cf9bb3aec91174efdd6e 100644 --- a/ylong_runtime/src/util/core_affinity/windows.rs +++ b/ylong_runtime/src/util/core_affinity/windows.rs @@ -30,7 +30,7 @@ extern "system" { /// /// # Example /// -/// ```rust +/// ```no run /// use ylong_runtime::util::core_affinity; /// /// let ret = core_affinity::set_current_affinity(0).is_ok(); diff --git a/ylong_runtime/src/util/mod.rs b/ylong_runtime/src/util/mod.rs index a69b441dfa182df15148c07d1e8928200f9d5384..6f3e9d3f29f40a518ada6853ce506b1aeb85e2c4 100644 --- a/ylong_runtime/src/util/mod.rs +++ b/ylong_runtime/src/util/mod.rs @@ -13,11 +13,16 @@ //! Utilities for runtime. -pub mod bit; -pub mod core_affinity; -pub mod fastrand; +cfg_net! { + pub(crate) mod bit; + pub(crate) mod slab; +} + #[cfg(any(feature = "time", feature = "net"))] pub(crate) mod linked_list; -pub mod num_cpus; -pub mod slab; -pub mod slots; + +#[cfg(feature = "sync")] +pub(crate) mod slots; + +pub(crate) mod core_affinity; +pub(crate) mod num_cpus; diff --git a/ylong_runtime/src/util/num_cpus/linux.rs b/ylong_runtime/src/util/num_cpus/linux.rs index dd61065b92efcfeef70c2e17ba806ac418a03821..e4c97f6b17b21aa758443e2055d6c3378fdef136 100644 --- a/ylong_runtime/src/util/num_cpus/linux.rs +++ b/ylong_runtime/src/util/num_cpus/linux.rs @@ -15,33 +15,8 @@ use std::os::raw::c_long; -use libc::{sysconf, _SC_NPROCESSORS_CONF, _SC_NPROCESSORS_ONLN}; +use libc::{sysconf, _SC_NPROCESSORS_ONLN}; -/// Gets the number of CPU cores via linux syscall -/// -/// # Example 2 -/// -/// ```rust -/// use ylong_runtime::util::num_cpus; -/// -/// #[cfg(target_os = "linux")] -/// let cpus = num_cpus::linux::get_cpu_num_online(); -/// ``` pub fn get_cpu_num_online() -> c_long { unsafe { sysconf(_SC_NPROCESSORS_ONLN) } } - -/// Gets the number of CPU cores via linux syscall, including disabled cpu -/// states -/// -/// # Example 2 -/// -/// ```rust -/// use ylong_runtime::util::num_cpus; -/// -/// #[cfg(target_os = "linux")] -/// let cpus = num_cpus::linux::get_cpu_num_configured(); -/// ``` -pub fn get_cpu_num_configured() -> c_long { - unsafe { sysconf(_SC_NPROCESSORS_CONF) } -} diff --git a/ylong_runtime/src/util/num_cpus/mod.rs b/ylong_runtime/src/util/num_cpus/mod.rs index fa82caa241976344fef348aa18a876eb403cbef2..8bba81081f646b9c47555fbaf23fc5bb29d40c26 100644 --- a/ylong_runtime/src/util/num_cpus/mod.rs +++ b/ylong_runtime/src/util/num_cpus/mod.rs @@ -34,7 +34,7 @@ use crate::util::num_cpus::windows::get_cpu_num_online; /// state by default. Windows, using GetSystemInfo() function, which gets the /// number of cpu cores in the available state by default. # Example /// -/// ```rust +/// ```no run /// use ylong_runtime::util::num_cpus; /// /// let cpus = num_cpus::get_cpu_num(); @@ -42,3 +42,18 @@ use crate::util::num_cpus::windows::get_cpu_num_online; pub fn get_cpu_num() -> c_long { get_cpu_num_online() } + +#[cfg(test)] +mod test { + use super::*; + + /// UT test cases for num_cpus. + /// + /// # Brief + /// 1. call get_cpu_num and check it greater than zero + #[test] + fn ut_num_cpus_test() { + let cpus = get_cpu_num(); + assert!(cpus > 0); + } +} diff --git a/ylong_runtime/src/util/slab.rs b/ylong_runtime/src/util/slab.rs index a1562a926b8bcde7df7282332e92a7f55aa9928e..13c81deba30429b30ae54d6980f98a2cbc818b63 100644 --- a/ylong_runtime/src/util/slab.rs +++ b/ylong_runtime/src/util/slab.rs @@ -464,9 +464,30 @@ impl Value { mod test { use std::sync::atomic::AtomicUsize; use std::sync::atomic::Ordering::SeqCst; + use std::sync::{Arc, Mutex}; + use std::thread; - use crate::util::slab::{Address, Entry, Slab, NUM_PAGES, PAGE_INITIAL_SIZE}; + use super::*; + struct TestEntry { + cnt: AtomicUsize, + id: AtomicUsize, + } + + impl Default for TestEntry { + fn default() -> TestEntry { + TestEntry { + cnt: AtomicUsize::new(0), + id: AtomicUsize::new(0), + } + } + } + + impl Entry for TestEntry { + fn reset(&self) { + self.cnt.fetch_add(1, SeqCst); + } + } struct Foo { cnt: AtomicUsize, id: AtomicUsize, @@ -593,4 +614,254 @@ mod test { assert!(!slab.pages[1].allocated.load(SeqCst)); } } + + /// UT test cases for Slab + /// + /// # Brief + /// 1. Inserting large amounts of data into a container. + /// 2. Make changes to these inserted data. + /// 3. Modified data by address verification. + /// 4. Multiplexing mechanism after calibration is released. + #[test] + fn ut_slab_insert_move() { + let mut slab = Slab::::new(); + let alloc = slab.handle(); + + unsafe { + // Find the first available `slot` and return its `addr` and `Ref` + let (addr1, test_entry1) = alloc.allocate().unwrap(); + // Modify the current `id` + slab.get(addr1).unwrap().id.store(1, SeqCst); + // The `reset` function has not been called yet, so `cnt` remains unchanged + assert_eq!(0, slab.get(addr1).unwrap().cnt.load(SeqCst)); + + // Find the second available `slot` and return its `addr` and `Ref` + let (addr2, test_entry2) = alloc.allocate().unwrap(); + slab.get(addr2).unwrap().id.store(2, SeqCst); + assert_eq!(0, slab.get(addr2).unwrap().cnt.load(SeqCst)); + + // This verifies that the function of finding data based on `addr` is working + assert_eq!(1, slab.get(addr1).unwrap().id.load(SeqCst)); + assert_eq!(2, slab.get(addr2).unwrap().id.load(SeqCst)); + + // Active destruct, the `slot` will be reused + drop(test_entry1); + + assert_eq!(1, slab.get(addr1).unwrap().id.load(SeqCst)); + + // Allocate again, but then the allocated `slot` should use the previously + // destructured `slot` + let (addr3, test_entry3) = alloc.allocate().unwrap(); + // Comparison, equal is successful + assert_eq!(addr3, addr1); + assert_eq!(1, slab.get(addr3).unwrap().cnt.load(SeqCst)); + slab.get(addr3).unwrap().id.store(3, SeqCst); + assert_eq!(3, slab.get(addr3).unwrap().id.load(SeqCst)); + + drop(test_entry2); + drop(test_entry3); + + // Cleaned regularly, but the first `page` is never cleaned + slab.compact(); + assert!(slab.get(addr1).is_some()); + assert!(slab.get(addr2).is_some()); + assert!(slab.get(addr3).is_some()); + } + } + + /// UT test cases for Slab + /// + /// # Brief + /// 1. Inserting large amounts of data into a container + /// 2. Verify by address that the data is in the correct location + #[test] + fn ut_slab_insert_many() { + unsafe { + // Verify that `page` is being allocated properly in the case of a large number + // of inserts. + let mut slab = Slab::::new(); + let alloc = slab.handle(); + let mut entries = vec![]; + + for i in 0..10_000 { + let (addr, val) = alloc.allocate().unwrap(); + val.id.store(i, SeqCst); + entries.push((addr, val)); + } + + for (i, (addr, v)) in entries.iter().enumerate() { + assert_eq!(i, v.id.load(SeqCst)); + assert_eq!(i, slab.get(*addr).unwrap().id.load(SeqCst)); + } + + entries.clear(); + + for i in 0..10_000 { + let (addr, val) = alloc.allocate().unwrap(); + val.id.store(10_000 - i, SeqCst); + entries.push((addr, val)); + } + + for (i, (addr, v)) in entries.iter().enumerate() { + assert_eq!(10_000 - i, v.id.load(SeqCst)); + assert_eq!(10_000 - i, slab.get(*addr).unwrap().id.load(SeqCst)); + } + } + } + + /// UT test cases for Slab + /// + /// # Brief + /// 1. Inserting large amounts of data into a container + /// 2. Verify by address that the data is in the correct location + #[test] + fn ut_slab_insert_drop_reverse() { + unsafe { + let mut slab = Slab::::new(); + let alloc = slab.handle(); + let mut entries = vec![]; + + for i in 0..10_000 { + let (addr, val) = alloc.allocate().unwrap(); + val.id.store(i, SeqCst); + entries.push((addr, val)); + } + + for _ in 0..10 { + for _ in 0..1_000 { + entries.pop(); + } + + for (i, (addr, v)) in entries.iter().enumerate() { + assert_eq!(i, v.id.load(SeqCst)); + assert_eq!(i, slab.get(*addr).unwrap().id.load(SeqCst)); + } + } + } + } + + /// UT test cases for Slab + /// + /// # Brief + /// 1. Multi-threaded allocation of container space, inserting data into it, + /// and verifying that the function is correct + #[test] + fn ut_slab_multi_allocate() { + // Multi-threaded either allocating space, or modifying values. + // finally comparing the values given by the acquired address to be equal. + let mut slab = Slab::::new(); + let thread_one_alloc = slab.handle(); + let thread_two_alloc = slab.handle(); + let thread_three_alloc = slab.handle(); + + let capacity = 3001; + let free_queue = Arc::new(Mutex::new(Vec::with_capacity(capacity))); + let free_queue_2 = free_queue.clone(); + let free_queue_3 = free_queue.clone(); + let free_queue_4 = free_queue.clone(); + + unsafe { + let thread_one = thread::spawn(move || { + for i in 0..10_00 { + let (addr, test_entry) = thread_one_alloc.allocate().unwrap(); + test_entry.id.store(i, SeqCst); + free_queue.lock().unwrap().push((addr, test_entry, i)); + } + }); + + let thread_two = thread::spawn(move || { + for i in 10_00..20_00 { + let (addr, test_entry) = thread_two_alloc.allocate().unwrap(); + test_entry.id.store(i, SeqCst); + free_queue_2.lock().unwrap().push((addr, test_entry, i)); + } + }); + + let thread_three = thread::spawn(move || { + for i in 20_00..30_00 { + let (addr, test_entry) = thread_three_alloc.allocate().unwrap(); + test_entry.id.store(i, SeqCst); + free_queue_3.lock().unwrap().push((addr, test_entry, i)); + } + }); + + thread_one + .join() + .expect("Couldn't join on the associated thread"); + thread_two + .join() + .expect("Couldn't join on the associated thread"); + thread_three + .join() + .expect("Couldn't join on the associated thread"); + } + + for _ in 0..30_00 { + let temp = free_queue_4.clone().lock().unwrap().pop().unwrap(); + assert_eq!(slab.get(temp.0).unwrap().id.load(SeqCst), temp.2); + } + } + + /// UT test cases for Slab + /// + /// # Brief + /// 1. Multi-threaded allocation of container space, inserting data into it, + /// and verifying that the function is correct + /// 2. Free up some of the data space and check if the data is reused in the + /// multi-threaded case + #[test] + fn ut_slab_multi_allocate_drop() { + // allocate space and free the used `slot` in the multi-threaded case. + // retaining the address of the freed `slot` and allocating it again. + // the address after reallocation is the same as the address of the previously + // freed `slot`. + let slab = Slab::::new(); + let thread_one_alloc = slab.handle(); + let thread_two_alloc = slab.handle(); + + let capacity = 2001; + let free_queue_one = Arc::new(Mutex::new(Vec::with_capacity(capacity))); + let free_queue_one_2 = free_queue_one.clone(); + + let free_queue_two = Arc::new(Mutex::new(Vec::with_capacity(capacity))); + let free_queue_two_2 = free_queue_two.clone(); + + unsafe { + let thread_one = thread::spawn(move || { + for i in 0..1000 { + let (addr, test_entry) = thread_one_alloc.allocate().unwrap(); + test_entry.id.store(i, SeqCst); + drop(test_entry); + + free_queue_one.lock().unwrap().push(addr); + } + }); + + thread_one + .join() + .expect("Couldn't join on the associated thread"); + + let thread_two = thread::spawn(move || { + thread::park(); + for i in 0..1000 { + let (addr, test_entry) = thread_two_alloc.allocate().unwrap(); + test_entry.id.store(i, SeqCst); + + free_queue_two.lock().unwrap().push(addr); + } + }); + + thread_two.thread().unpark(); + thread_two + .join() + .expect("Couldn't join on the associated thread"); + + for _ in 0..1000 { + assert_eq!( + free_queue_one_2.clone().lock().unwrap().pop().unwrap(), + free_queue_two_2.lock().unwrap().pop().unwrap() + ); + } + } + } } diff --git a/ylong_runtime/src/util/slots.rs b/ylong_runtime/src/util/slots.rs index f60c276ad9cdb8fb732e91ed4649e1e444241618..29f11d496680f4f4e6298cecea23266160fc6a80 100644 --- a/ylong_runtime/src/util/slots.rs +++ b/ylong_runtime/src/util/slots.rs @@ -50,7 +50,7 @@ pub struct SlotsIter<'a, T: 'a> { #[derive(Eq, PartialEq)] pub struct Slots { entries: Vec>, - len: usize, + pub len: usize, head: usize, tail: usize, next: usize, @@ -73,7 +73,7 @@ impl Slots { /// /// # Examples /// - /// ``` + /// ```no run /// use ylong_runtime::util::slots::Slots; /// /// let slots: Slots = Slots::new(); @@ -82,71 +82,6 @@ impl Slots { Slots::with_capacity(0) } - /// Returns the current number of elements in the container. - /// - /// # Examples - /// - /// ``` - /// use ylong_runtime::util::slots::Slots; - /// - /// let mut slots = Slots::new(); - /// for i in 0..3 { - /// slots.push_back(i); - /// } - /// assert_eq!(3, slots.len()); - /// ``` - pub fn len(&self) -> usize { - self.len - } - - /// Empty the container. - /// - /// # Examples - /// ``` - /// use ylong_runtime::util::slots::Slots; - /// - /// let mut slots = Slots::new(); - /// for i in 0..3 { - /// slots.push_back(i); - /// } - /// slots.clear(); - /// assert_eq!(slots.len(), 0); - /// ``` - pub fn clear(&mut self) { - self.entries.clear(); - self.len = 0; - self.head = NULL; - self.tail = NULL; - self.next = 0; - } - - /// Insert an element to the end of the list of container. - /// - /// Two situations: - /// - /// 1. The next slot is exactly the next position of the array. Insert the - /// data into the vector, increase the length, and calculate the next - /// insertion position. - /// 2. The next slot is the recycled slot. Update the index of `next` and - /// then insert the data. - /// - /// # Examples - /// - /// ``` - /// use ylong_runtime::util::slots::Slots; - /// - /// let mut slots = Slots::new(); - /// let zero = slots.push_back("zero"); - /// let one = slots.push_back("one"); - /// assert_eq!(zero, 0); - /// assert_eq!(one, 1); - /// - /// let temp = slots.remove(zero); - /// assert_eq!(temp, Ok("zero")); - /// - /// let two = slots.push_back("two"); - /// assert_eq!(two, zero); - /// ``` pub fn push_back(&mut self, val: T) -> usize { let key = self.next; let tail = self.tail; @@ -183,7 +118,7 @@ impl Slots { /// /// # Examples /// - /// ``` + /// ```no run /// use ylong_runtime::util::slots::Slots; /// /// let mut slots = Slots::new(); @@ -220,7 +155,7 @@ impl Slots { /// /// # Examples /// - /// ``` + /// ```no run /// use ylong_runtime::util::slots::Slots; /// /// let mut slots = Slots::new(); @@ -266,106 +201,11 @@ impl Slots { Err(SlotsError) } - /// Get the reference of the element in the container according to the - /// index. - /// - /// # Examples - /// - /// ``` - /// use ylong_runtime::util::slots::Slots; - /// - /// let mut slots = Slots::new(); - /// let key = slots.push_back("key"); - /// - /// assert_eq!(slots.get(key), Some(&"key")); - /// assert_eq!(slots.get(123), None); - /// ``` - pub fn get(&self, key: usize) -> Option<&T> { - match self.entries.get(key) { - Some(entry) => match entry.data.as_ref() { - Some(val) => Some(val), - None => None, - }, - None => None, - } - } - - /// Get the mutable reference of the element in the container according to - /// the index. - /// - /// # Examples - /// - /// ``` - /// use ylong_runtime::util::slots::Slots; - /// - /// let mut slots = Slots::new(); - /// let key = slots.push_back("key"); - /// - /// *slots.get_mut(key).unwrap() = "change_key"; - /// assert_eq!(*slots.get(key).unwrap(), "change_key"); - /// assert_eq!(slots.get(123), None); - /// ``` - pub fn get_mut(&mut self, key: usize) -> Option<&mut T> { - match self.entries.get_mut(key) { - Some(entry) => match entry.data.as_mut() { - Some(val) => Some(val), - None => None, - }, - None => None, - } - } - - /// Check whether the index is valid and whether there is an element at the - /// index in the container. - /// - /// # Examples - /// - /// ``` - /// use ylong_runtime::util::slots::Slots; - /// - /// let mut slots = Slots::new(); - /// let key = slots.push_back("key"); - /// - /// assert!(slots.contains(key)); - /// assert!(!slots.contains(123)); - /// ``` - pub fn contains(&self, key: usize) -> bool { - match self.entries.get(key) { - Some(entry) => entry.data.is_some(), - None => false, - } - } - - /// Create an immutable iterator for the container to poll all elements int - /// the order of insertion. - /// - /// # Examples - /// - /// ``` - /// use ylong_runtime::util::slots::Slots; - /// - /// let mut slots = Slots::new(); - /// for i in 0..3 { - /// slots.push_back(i); - /// } - /// - /// for (key, element) in slots.iter() { - /// assert_eq!(slots.get(key).unwrap(), element); - /// } - /// ``` - pub fn iter(&self) -> SlotsIter { - SlotsIter { - entries: &self.entries, - len: self.len, - head: self.head, - } - } - /// Check whether the container is empty. /// /// # Examples /// - /// ``` + /// ```no run /// use ylong_runtime::util::slots::Slots; /// /// let mut slots = Slots::new(); @@ -382,7 +222,7 @@ impl Slots { /// /// # Examples /// - /// ``` + /// ```no run /// use ylong_runtime::util::slots::Slots; /// /// let slots: Slots = Slots::with_capacity(0); @@ -396,20 +236,6 @@ impl Slots { len: 0, } } - - /// Get the capacity of the container. - /// - /// # Examples - /// - /// ``` - /// use ylong_runtime::util::slots::Slots; - /// - /// let mut slots: Slots = Slots::new(); - /// assert_eq!(slots.capacity(), 0); - /// ``` - pub fn capacity(&self) -> usize { - self.entries.capacity() - } } impl Default for Slots { @@ -483,7 +309,17 @@ impl<'a, T> Iterator for SlotsIter<'a, T> { #[cfg(test)] mod test { use crate::util::slots::Slots; - + impl Slots { + fn get(&self, key: usize) -> Option<&T> { + match self.entries.get(key) { + Some(entry) => match entry.data.as_ref() { + Some(val) => Some(val), + None => None, + }, + None => None, + } + } + } #[derive(Debug, Eq, PartialEq)] struct Data { inner: i32, @@ -495,63 +331,6 @@ mod test { } } - /// UT test cases for Slots::new(). - /// - /// # Brief - /// 1. Verify the parameters after initialization, which should be - /// consistent with the initial value. - #[test] - fn ut_slots_new() { - let slots: Slots = Slots::new(); - assert_eq!(slots.len, 0); - assert_eq!(slots.next, 0); - assert_eq!(slots.entries, Vec::with_capacity(0)); - } - - /// UT test cases for Slots::with_capacity(). - /// - /// # Brief - /// 1. Verify the parameters after initialization, which should be - /// consistent with the initial value. - #[test] - fn ut_slots_with_capacity() { - let slots_new: Slots = Slots::new(); - let slots_with_capacity: Slots = Slots::with_capacity(0); - assert_eq!(slots_new, slots_with_capacity); - } - - /// UT test cases for Slots::len(). - /// - /// # Brief - /// 1. Inserting a certain number of data into the container. - #[test] - fn ut_slots_len() { - let mut slots = Slots::new(); - assert_eq!(slots.len(), 0_usize); - - for i in 0..1000 { - slots.push_back(i); - } - assert_eq!(slots.len(), 1000); - } - - /// UT test cases for Slots::clear(). - /// - /// # Brief - /// 1. Empty the container to make it exactly the same as the initialized - /// container. - #[test] - fn ut_slots_clear() { - let mut slots = Slots::new(); - for i in 0..1000 { - slots.push_back(i); - } - assert_ne!(slots, Slots::new()); - - slots.clear(); - assert_eq!(slots, Slots::new()); - } - /// UT test cases for Slots::insert(). /// /// # Brief @@ -628,7 +407,7 @@ mod test { assert_eq!(slots.pop_front(), Some(index)); assert_eq!(slots.get(index), None); } - assert_eq!(slots.len(), 50); + assert_eq!(slots.len, 50); for data in 100..150 { slots.push_back(data); @@ -637,7 +416,7 @@ mod test { assert_eq!(slots.pop_front(), Some(target)); } assert_eq!(slots.pop_front(), None); - assert_eq!(slots.len(), 0); + assert_eq!(slots.len, 0); } /// UT test cases for Slots::remove(). @@ -658,98 +437,158 @@ mod test { assert_eq!(slots.remove(0), Ok(0)); } - /// UT test cases for Slots::get(). + /// UT test cases for Slots::is_empty(). /// /// # Brief - /// 1. Enter the location that stores data. - /// 2. Enter the location that doesn't store data. + /// 1. Verify empty container, the result is true. + /// 2. Verify non-empty container, the result is false. #[test] - fn ut_slots_get() { + fn ut_slots_is_empty() { let mut slots = Slots::new(); - let key = slots.push_back("key"); + assert!(slots.is_empty()); - assert_eq!(slots.get(key), Some(&"key")); - assert_eq!(slots.get(123), None); + slots.push_back(1); + assert!(!slots.is_empty()); } - /// UT test cases for Slots::get_mut(). + /// UT test cases for Slots /// /// # Brief - /// 1. Enter the location that stores data. - /// 2. Enter the location that doesn't store data. + /// 1. Push a large amount of data into the initialized container. + /// 2. Check the correctness of inserted data iteratively. #[test] - fn ut_slots_get_mut() { + fn ut_slots_huge_data_push_back() { let mut slots = Slots::new(); - let key = slots.push_back("key"); + let mut keys = Vec::new(); + + for data in 0..10000 { + let key = slots.push_back(data); + keys.push(key); + } - *slots.get_mut(key).unwrap() = "change_key"; - assert_eq!(*slots.get(key).unwrap(), "change_key"); - assert_eq!(slots.get(123), None); + for (index, key) in keys.iter().enumerate() { + assert_eq!(slots[*key], index); + } } - /// UT test cases for Slots::contains(). + /// UT test cases for Slots /// /// # Brief - /// 1. The container exists the location and there are data at that - /// location. - /// 2. The container exists the location and there are no data at that - /// location. - /// 3. The container doesn't exist the location. + /// 1. Push a large amount of data into the initialized container. + /// 2. Remove the first half of the container. + /// 3. Push new data into the container again. + /// 4. Check the correctness of data sequence and values. #[test] - fn ut_slots_contains() { + fn ut_slots_huge_data_remove() { let mut slots = Slots::new(); - let key = slots.push_back("key"); + let mut keys = Vec::new(); - assert!(slots.contains(key)); - assert!(!slots.contains(123)); + for data in 0..10000 { + let key = slots.push_back(data); + keys.push(key); + } - let res = slots.remove(key); - assert!(res.is_ok()); - assert!(!slots.contains(key)); + for remove_index in 0..5000 { + let res = slots.remove(remove_index); + assert!(res.is_ok()); + } + + for data in 10000..15000 { + slots.push_back(data); + } + + let mut cnt = 14999; + for key in 0..5000 { + assert_eq!(slots[key], cnt); + cnt -= 1; + } } - /// UT test cases for Slots::iter(). + /// UT test cases for Slots /// /// # Brief - /// 1. Validate elements through iterators. + /// 1. Push data into the initialized container. + /// 2. Remove slots that have been popped. + /// 3. Remove slots at wrong index. + /// 4. Pop the remaining data. #[test] - fn ut_slots_iter() { + fn ut_slots_remove_and_pop() { let mut slots = Slots::new(); - for i in 0..3 { - slots.push_back(i); + for data in 0..100 { + slots.push_back(data); + } + + for index in 0..10 { + slots.pop_front(); + let res = slots.remove(index); + assert!(res.is_err()); + } + + for remove_index in 100..150 { + let res = slots.remove(remove_index); + assert!(res.is_err()); + } + + for remove_index in 10..20 { + let res = slots.remove(remove_index); + assert!(res.is_ok()); } - for (key, element) in slots.iter() { - assert_eq!(slots.get(key).unwrap(), element); + for index in 20..100 { + assert_eq!(slots.pop_front(), Some(index)); } + assert!(slots.pop_front().is_none()); } - /// UT test cases for Slots::is_empty(). + /// UT test cases for Slots /// /// # Brief - /// 1. Verify empty container, the result is true. - /// 2. Verify non-empty container, the result is false. + /// 1. Push a large amount of data into the initialized container. + /// 2. Find data through key-value pairs. #[test] - fn ut_slots_is_empty() { + fn ut_slots_huge_data_find() { let mut slots = Slots::new(); - assert!(slots.is_empty()); + let mut keys = Vec::new(); - slots.push_back(1); - assert!(!slots.is_empty()); + for data in 0..10000 { + let key = slots.push_back(data); + keys.push(key); + } + + for key in keys { + assert_eq!(slots[key], key); + } } - /// UT test cases for Slots::capacity(). + /// UT test cases for Slots /// /// # Brief - /// 1. Verify the container that is initialized. - /// 2. Verify the container that is initialized with specific capacity. + /// 1. Push a large amount of data into the initialized container. + /// 2. Pop the first half of the container. + /// 3. Push new data into the container again. + /// 4. Pop all of the data and check correctness of data sequence and + /// values. #[test] - fn ut_slots_capacity() { - let slots: Slots = Slots::new(); - assert_eq!(slots.capacity(), 0); + fn ut_slots_huge_data_pop_front() { + let mut slots = Slots::new(); + + for data in 0..10000 { + slots.push_back(data); + } + + for _ in 0..5000 { + slots.pop_front(); + } + + for data in 10000..15000 { + slots.push_back(data); + } - let slots: Slots = Slots::with_capacity(10); - assert_eq!(slots.capacity(), 10); + let mut cnt = 14999; + for key in 0..5000 { + assert_eq!(slots[key], cnt); + cnt -= 1; + } } } diff --git a/ylong_runtime/tests/async_pool.rs b/ylong_runtime/tests/async_pool.rs index 34ab705b20bddda7698361620c290528b4f98548..524b2b45318d5eb873ccc70372097d5d1bf25177 100644 --- a/ylong_runtime/tests/async_pool.rs +++ b/ylong_runtime/tests/async_pool.rs @@ -19,13 +19,12 @@ use std::ffi::OsString; use std::fs; +use std::mem::{size_of, zeroed}; -use libc::getpid; +use libc::{ + c_long, cpu_set_t, getpid, sched_getaffinity, sysconf, CPU_ISSET, _SC_NPROCESSORS_ONLN, +}; use ylong_runtime::builder::RuntimeBuilder; -#[cfg(target_os = "linux")] -use ylong_runtime::util::core_affinity::linux::get_other_thread_affinity; -#[cfg(target_os = "linux")] -use ylong_runtime::util::num_cpus::get_cpu_num; // Simple asynchronous tasks async fn test_future(num: usize) -> usize { @@ -77,6 +76,30 @@ unsafe fn name_of_pid(pid: &str) -> Option { } } +fn get_other_thread_affinity(pid: i32) -> Vec { + unsafe { + let mut vec = vec![]; + let cpus = get_cpu_num() as usize; + let mut set = new_cpu_set(); + sched_getaffinity(pid, size_of::(), &mut set); + for i in 0..cpus { + if CPU_ISSET(i, &set) { + vec.push(i); + } + } + vec + } +} + +/// Returns an empty cpu set +fn new_cpu_set() -> cpu_set_t { + unsafe { zeroed::() } +} + +fn get_cpu_num() -> c_long { + unsafe { sysconf(_SC_NPROCESSORS_ONLN) } +} + /// SDV test cases for asynchronous thread pool /// /// # Brief diff --git a/ylong_runtime/tests/core_affinity.rs b/ylong_runtime/tests/core_affinity.rs deleted file mode 100644 index 78bc0e1d7b0b53acbf1f7be4097b06f7acb4fac7..0000000000000000000000000000000000000000 --- a/ylong_runtime/tests/core_affinity.rs +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) 2023 Huawei Device Co., Ltd. -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#![cfg(target_os = "linux")] -use std::thread; - -use ylong_runtime::util::core_affinity::linux::{get_current_affinity, set_current_affinity}; -use ylong_runtime::util::num_cpus::get_cpu_num; - -#[test] -fn sdv_affinity_set() { - let cpus = get_current_affinity(); - assert!(!cpus.is_empty()); - - let ret = set_current_affinity(0).is_ok(); - assert!(ret); - - let cpus = get_current_affinity(); - assert_eq!(cpus.len(), 1); -} - -#[test] -fn sdv_affinity_core() { - let cpus = get_cpu_num() as usize; - let handle = thread::spawn(move || { - set_current_affinity(0 % cpus).unwrap(); - let core_ids = get_current_affinity(); - for coreid in core_ids.iter() { - assert_eq!(*coreid, 0_usize); - } - }); - let _ = handle.join(); - thread::spawn(move || { - set_current_affinity(1 % cpus).unwrap(); - let core_ids = get_current_affinity(); - for coreid in core_ids.iter() { - assert_eq!(*coreid, 1_usize); - } - }); -} diff --git a/ylong_runtime/tests/entry.rs b/ylong_runtime/tests/entry.rs index 7142db3939596c898285872ae57b069e131ceccd..edef8bfe074583ed36e69fc7ba2223ff2ba9bdf8 100644 --- a/ylong_runtime/tests/entry.rs +++ b/ylong_runtime/tests/entry.rs @@ -21,16 +21,12 @@ mod async_pool; mod async_read; mod block_on; mod builder; -mod core_affinity; mod join_set; mod mpsc_test; mod mutex; -mod num_cpus; mod par_iter; mod semaphore_test; mod singleton_runtime; -mod slab; -mod slots; mod spawn; mod spawn_blocking; mod sync; diff --git a/ylong_runtime/tests/num_cpus.rs b/ylong_runtime/tests/num_cpus.rs deleted file mode 100644 index 31829617d8655932dc77e52c1f81818babd17b24..0000000000000000000000000000000000000000 --- a/ylong_runtime/tests/num_cpus.rs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) 2023 Huawei Device Co., Ltd. -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -use ylong_runtime::util::num_cpus::get_cpu_num; - -#[cfg(target_os = "linux")] -#[test] -fn sdv_num_cpus_linux_test() { - use ylong_runtime::util::num_cpus::linux::get_cpu_num_configured; - - let cpus = get_cpu_num(); - assert!(cpus > 0); - let cpus = get_cpu_num_configured(); - assert!(cpus > 0); -} - -#[cfg(target_os = "windows")] -#[test] -fn sdv_num_cpus_windows_test() { - let cpus = get_cpu_num(); - assert!(cpus > 0); -} diff --git a/ylong_runtime/tests/slab.rs b/ylong_runtime/tests/slab.rs deleted file mode 100644 index 2aa329b4a8133a4300b21895209cef90a1f0578b..0000000000000000000000000000000000000000 --- a/ylong_runtime/tests/slab.rs +++ /dev/null @@ -1,289 +0,0 @@ -// Copyright (c) 2023 Huawei Device Co., Ltd. -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -use std::sync::atomic::AtomicUsize; -use std::sync::atomic::Ordering::SeqCst; -use std::sync::{Arc, Mutex}; -use std::thread; - -use ylong_runtime::util::slab::{Entry, Slab}; - -struct TestEntry { - cnt: AtomicUsize, - id: AtomicUsize, -} - -impl Default for TestEntry { - fn default() -> TestEntry { - TestEntry { - cnt: AtomicUsize::new(0), - id: AtomicUsize::new(0), - } - } -} - -impl Entry for TestEntry { - fn reset(&self) { - self.cnt.fetch_add(1, SeqCst); - } -} - -/// SDV test cases for Slab -/// -/// # Brief -/// 1. Inserting large amounts of data into a container. -/// 2. Make changes to these inserted data. -/// 3. Modified data by address verification. -/// 4. Multiplexing mechanism after calibration is released. -#[test] -fn sdv_slab_insert_move() { - let mut slab = Slab::::new(); - let alloc = slab.handle(); - - unsafe { - // Find the first available `slot` and return its `addr` and `Ref` - let (addr1, test_entry1) = alloc.allocate().unwrap(); - // Modify the current `id` - slab.get(addr1).unwrap().id.store(1, SeqCst); - // The `reset` function has not been called yet, so `cnt` remains unchanged - assert_eq!(0, slab.get(addr1).unwrap().cnt.load(SeqCst)); - - // Find the second available `slot` and return its `addr` and `Ref` - let (addr2, test_entry2) = alloc.allocate().unwrap(); - slab.get(addr2).unwrap().id.store(2, SeqCst); - assert_eq!(0, slab.get(addr2).unwrap().cnt.load(SeqCst)); - - // This verifies that the function of finding data based on `addr` is working - assert_eq!(1, slab.get(addr1).unwrap().id.load(SeqCst)); - assert_eq!(2, slab.get(addr2).unwrap().id.load(SeqCst)); - - // Active destruct, the `slot` will be reused - drop(test_entry1); - - assert_eq!(1, slab.get(addr1).unwrap().id.load(SeqCst)); - - // Allocate again, but then the allocated `slot` should use the previously - // destructured `slot` - let (addr3, test_entry3) = alloc.allocate().unwrap(); - // Comparison, equal is successful - assert_eq!(addr3, addr1); - assert_eq!(1, slab.get(addr3).unwrap().cnt.load(SeqCst)); - slab.get(addr3).unwrap().id.store(3, SeqCst); - assert_eq!(3, slab.get(addr3).unwrap().id.load(SeqCst)); - - drop(test_entry2); - drop(test_entry3); - - // Cleaned regularly, but the first `page` is never cleaned - slab.compact(); - assert!(slab.get(addr1).is_some()); - assert!(slab.get(addr2).is_some()); - assert!(slab.get(addr3).is_some()); - } -} - -/// SDV test cases for Slab -/// -/// # Brief -/// 1. Inserting large amounts of data into a container -/// 2. Verify by address that the data is in the correct location -#[test] -fn sdv_slab_insert_many() { - unsafe { - // Verify that `page` is being allocated properly in the case of a large number - // of inserts. - let mut slab = Slab::::new(); - let alloc = slab.handle(); - let mut entries = vec![]; - - for i in 0..10_000 { - let (addr, val) = alloc.allocate().unwrap(); - val.id.store(i, SeqCst); - entries.push((addr, val)); - } - - for (i, (addr, v)) in entries.iter().enumerate() { - assert_eq!(i, v.id.load(SeqCst)); - assert_eq!(i, slab.get(*addr).unwrap().id.load(SeqCst)); - } - - entries.clear(); - - for i in 0..10_000 { - let (addr, val) = alloc.allocate().unwrap(); - val.id.store(10_000 - i, SeqCst); - entries.push((addr, val)); - } - - for (i, (addr, v)) in entries.iter().enumerate() { - assert_eq!(10_000 - i, v.id.load(SeqCst)); - assert_eq!(10_000 - i, slab.get(*addr).unwrap().id.load(SeqCst)); - } - } -} - -/// SDV test cases for Slab -/// -/// # Brief -/// 1. Inserting large amounts of data into a container -/// 2. Verify by address that the data is in the correct location -#[test] -fn sdv_slab_insert_drop_reverse() { - unsafe { - let mut slab = Slab::::new(); - let alloc = slab.handle(); - let mut entries = vec![]; - - for i in 0..10_000 { - let (addr, val) = alloc.allocate().unwrap(); - val.id.store(i, SeqCst); - entries.push((addr, val)); - } - - for _ in 0..10 { - for _ in 0..1_000 { - entries.pop(); - } - - for (i, (addr, v)) in entries.iter().enumerate() { - assert_eq!(i, v.id.load(SeqCst)); - assert_eq!(i, slab.get(*addr).unwrap().id.load(SeqCst)); - } - } - } -} - -/// SDV test cases for Slab -/// -/// # Brief -/// 1. Multi-threaded allocation of container space, inserting data into it, and -/// verifying that the function is correct -#[test] -fn sdv_slab_multi_allocate() { - // Multi-threaded either allocating space, or modifying values. - // finally comparing the values given by the acquired address to be equal. - let mut slab = Slab::::new(); - let thread_one_alloc = slab.handle(); - let thread_two_alloc = slab.handle(); - let thread_three_alloc = slab.handle(); - - let capacity = 3001; - let free_queue = Arc::new(Mutex::new(Vec::with_capacity(capacity))); - let free_queue_2 = free_queue.clone(); - let free_queue_3 = free_queue.clone(); - let free_queue_4 = free_queue.clone(); - - unsafe { - let thread_one = thread::spawn(move || { - for i in 0..10_00 { - let (addr, test_entry) = thread_one_alloc.allocate().unwrap(); - test_entry.id.store(i, SeqCst); - free_queue.lock().unwrap().push((addr, test_entry, i)); - } - }); - - let thread_two = thread::spawn(move || { - for i in 10_00..20_00 { - let (addr, test_entry) = thread_two_alloc.allocate().unwrap(); - test_entry.id.store(i, SeqCst); - free_queue_2.lock().unwrap().push((addr, test_entry, i)); - } - }); - - let thread_three = thread::spawn(move || { - for i in 20_00..30_00 { - let (addr, test_entry) = thread_three_alloc.allocate().unwrap(); - test_entry.id.store(i, SeqCst); - free_queue_3.lock().unwrap().push((addr, test_entry, i)); - } - }); - - thread_one - .join() - .expect("Couldn't join on the associated thread"); - thread_two - .join() - .expect("Couldn't join on the associated thread"); - thread_three - .join() - .expect("Couldn't join on the associated thread"); - } - - for _ in 0..30_00 { - let temp = free_queue_4.clone().lock().unwrap().pop().unwrap(); - assert_eq!(slab.get(temp.0).unwrap().id.load(SeqCst), temp.2); - } -} - -/// SDV test cases for Slab -/// -/// # Brief -/// 1. Multi-threaded allocation of container space, inserting data into it, and -/// verifying that the function is correct -/// 2. Free up some of the data space and check if the data is reused in the -/// multi-threaded case -#[test] -fn sdv_slab_multi_allocate_drop() { - // allocate space and free the used `slot` in the multi-threaded case. - // retaining the address of the freed `slot` and allocating it again. - // the address after reallocation is the same as the address of the previously - // freed `slot`. - let slab = Slab::::new(); - let thread_one_alloc = slab.handle(); - let thread_two_alloc = slab.handle(); - - let capacity = 2001; - let free_queue_one = Arc::new(Mutex::new(Vec::with_capacity(capacity))); - let free_queue_one_2 = free_queue_one.clone(); - - let free_queue_two = Arc::new(Mutex::new(Vec::with_capacity(capacity))); - let free_queue_two_2 = free_queue_two.clone(); - - unsafe { - let thread_one = thread::spawn(move || { - for i in 0..1000 { - let (addr, test_entry) = thread_one_alloc.allocate().unwrap(); - test_entry.id.store(i, SeqCst); - drop(test_entry); - - free_queue_one.lock().unwrap().push(addr); - } - }); - - thread_one - .join() - .expect("Couldn't join on the associated thread"); - - let thread_two = thread::spawn(move || { - thread::park(); - for i in 0..1000 { - let (addr, test_entry) = thread_two_alloc.allocate().unwrap(); - test_entry.id.store(i, SeqCst); - - free_queue_two.lock().unwrap().push(addr); - } - }); - - thread_two.thread().unpark(); - thread_two - .join() - .expect("Couldn't join on the associated thread"); - - for _ in 0..1000 { - assert_eq!( - free_queue_one_2.clone().lock().unwrap().pop().unwrap(), - free_queue_two_2.lock().unwrap().pop().unwrap() - ); - } - } -} diff --git a/ylong_runtime/tests/slots.rs b/ylong_runtime/tests/slots.rs deleted file mode 100644 index 981f2aea4614ef7523c0886715990199b61da3ef..0000000000000000000000000000000000000000 --- a/ylong_runtime/tests/slots.rs +++ /dev/null @@ -1,154 +0,0 @@ -// Copyright (c) 2023 Huawei Device Co., Ltd. -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -use ylong_runtime::util::slots::Slots; - -/// SDV test cases for Slots -/// -/// # Brief -/// 1. Push a large amount of data into the initialized container. -/// 2. Check the correctness of inserted data iteratively. -#[test] -fn sdv_slots_huge_data_push_back() { - let mut slots = Slots::new(); - let mut keys = Vec::new(); - - for data in 0..10000 { - let key = slots.push_back(data); - keys.push(key); - } - - for (index, key) in keys.iter().enumerate() { - assert_eq!(slots[*key], index); - } -} - -/// SDV test cases for Slots -/// -/// # Brief -/// 1. Push a large amount of data into the initialized container. -/// 2. Remove the first half of the container. -/// 3. Push new data into the container again. -/// 4. Check the correctness of data sequence and values. -#[test] -fn sdv_slots_huge_data_remove() { - let mut slots = Slots::new(); - let mut keys = Vec::new(); - - for data in 0..10000 { - let key = slots.push_back(data); - keys.push(key); - } - - for remove_index in 0..5000 { - let res = slots.remove(remove_index); - assert!(res.is_ok()); - } - - for data in 10000..15000 { - slots.push_back(data); - } - - let mut cnt = 14999; - for key in 0..5000 { - assert_eq!(slots[key], cnt); - cnt -= 1; - } -} - -/// SDV test cases for Slots -/// -/// # Brief -/// 1. Push data into the initialized container. -/// 2. Remove slots that have been popped. -/// 3. Remove slots at wrong index. -/// 4. Pop the remaining data. -#[test] -fn sdv_slots_remove_and_pop() { - let mut slots = Slots::new(); - - for data in 0..100 { - slots.push_back(data); - } - - for index in 0..10 { - slots.pop_front(); - let res = slots.remove(index); - assert!(res.is_err()); - } - - for remove_index in 100..150 { - let res = slots.remove(remove_index); - assert!(res.is_err()); - } - - for remove_index in 10..20 { - let res = slots.remove(remove_index); - assert!(res.is_ok()); - } - - for index in 20..100 { - assert_eq!(slots.pop_front(), Some(index)); - } - assert!(slots.pop_front().is_none()); -} - -/// SDV test cases for Slots -/// -/// # Brief -/// 1. Push a large amount of data into the initialized container. -/// 2. Find data through key-value pairs. -#[test] -fn sdv_slots_huge_data_find() { - let mut slots = Slots::new(); - let mut keys = Vec::new(); - - for data in 0..10000 { - let key = slots.push_back(data); - keys.push(key); - } - - for key in keys { - assert_eq!(slots[key], key); - } -} - -/// SDV test cases for Slots -/// -/// # Brief -/// 1. Push a large amount of data into the initialized container. -/// 2. Pop the first half of the container. -/// 3. Push new data into the container again. -/// 4. Pop all of the data and check correctness of data sequence and values. -#[test] -fn sdv_slots_huge_data_pop_front() { - let mut slots = Slots::new(); - - for data in 0..10000 { - slots.push_back(data); - } - - for _ in 0..5000 { - slots.pop_front(); - } - - for data in 10000..15000 { - slots.push_back(data); - } - - let mut cnt = 14999; - for key in 0..5000 { - assert_eq!(slots[key], cnt); - cnt -= 1; - } -}