diff --git a/kernel/src/utils/immut_after_init.rs b/kernel/src/utils/immut_after_init.rs index c765fb88f..ef0f410db 100644 --- a/kernel/src/utils/immut_after_init.rs +++ b/kernel/src/utils/immut_after_init.rs @@ -12,7 +12,7 @@ use core::sync::atomic::{AtomicU8, Ordering}; pub type ImmutAfterInitResult = Result; -#[derive(Clone, Copy, Debug)] +#[derive(Clone, Copy, Debug, PartialEq)] pub enum ImmutAfterInitError { AlreadyInit, Uninitialized, @@ -292,3 +292,60 @@ impl Deref for ImmutAfterInitRef<'_, T> { unsafe impl Send for ImmutAfterInitRef<'_, T> {} unsafe impl Sync for ImmutAfterInitRef<'_, T> {} + +#[cfg(test)] +mod tests { + + use crate::utils::immut_after_init::*; + use core::sync::atomic::{AtomicU32, Ordering}; + + #[test] + fn test_with_move() { + let v = AtomicU32::new(5); + let immut = ImmutAfterInitCell::::uninit(); + match immut.try_get_inner() { + Ok(_) => panic!("uninitialized cell returned Ok()"), + Err(e) => assert_eq!(e, ImmutAfterInitError::Uninitialized), + } + let init = immut.init(v); + if init.is_err() { + panic!("initializing uninitialized cell returned {:?}", init); + } + match immut.init(AtomicU32::new(0)) { + Ok(_) => panic!("reinitializing initialized cell returned Ok()"), + Err(e) => assert_eq!(e, ImmutAfterInitError::AlreadyInit), + } + + assert_eq!(immut.load(Ordering::Relaxed), 5); + } + + #[test] + fn test_with_copy() { + let v: u32 = 5; + let immut = ImmutAfterInitCell::::uninit(); + immut.init_from_ref(&v).expect("init failed"); + assert_eq!(*immut, 5); + } + + struct ItemWithDrop<'a> { + pub drop_count: &'a mut u32, + } + + impl Drop for ItemWithDrop<'_> { + fn drop(&mut self) { + *self.drop_count += 1; + } + } + + #[test] + fn test_with_drop() { + let mut local_drop_count: u32 = 0; + let item = ItemWithDrop { + drop_count: &mut local_drop_count, + }; + let immut = ImmutAfterInitCell::>::uninit(); + immut.init(item).expect("init failed"); + drop(immut); + assert_eq!(local_drop_count, 1); + } +}