use crate::mem::frame::SharedFrame; use crate::mem::phys::BitmapFrameAllocator; use crate::mem::refcount; crate::kernel_test!( fn increment_then_get() { let frame = BitmapFrameAllocator.allocate().expect("alloc for refcount"); let addr = frame.phys_addr(); let _ = refcount::increment(addr); let count = refcount::get(addr); assert_eq!( count, 1, "expected refcount 1 after increment, got {}", count ); let remaining = refcount::decrement(addr); assert_eq!(remaining, Ok(0), "expected Ok(0) after decrement"); drop(frame); } ); crate::kernel_test!( fn increment_n_times() { let frame = BitmapFrameAllocator .allocate() .expect("alloc for refcount N"); let addr = frame.phys_addr(); let n: u16 = 5; (0..n).for_each(|_| { let _ = refcount::increment(addr); }); let count = refcount::get(addr); assert_eq!(count, n, "expected refcount {}, got {}", n, count); (0..n).for_each(|_| { let _ = refcount::decrement(addr); }); drop(frame); } ); crate::kernel_test!( fn decrement_returns_new_count() { let frame = BitmapFrameAllocator.allocate().expect("alloc for dec test"); let addr = frame.phys_addr(); let _ = refcount::increment(addr); let _ = refcount::increment(addr); let after_first_dec = refcount::decrement(addr); assert_eq!(after_first_dec, Ok(1), "expected Ok(1) after first dec"); let after_second_dec = refcount::decrement(addr); assert_eq!(after_second_dec, Ok(0), "expected Ok(0) after second dec"); drop(frame); } ); crate::kernel_test!( fn high_refcount_survives() { let frame = BitmapFrameAllocator .allocate() .expect("alloc for high refcount"); let addr = frame.phys_addr(); let n: u16 = 1000; (0..n).for_each(|_| { refcount::increment(addr).expect("increment should succeed"); }); let count = refcount::get(addr); assert_eq!(count, n, "expected refcount {}, got {}", n, count); (0..n).for_each(|_| { let _ = refcount::decrement(addr); }); assert_eq!(refcount::get(addr), 0, "refcount should be 0 after cleanup"); drop(frame); } ); crate::kernel_test!( fn underflow_returns_err() { let frame = BitmapFrameAllocator .allocate() .expect("alloc for underflow test"); let addr = frame.phys_addr(); let result = refcount::decrement(addr); assert!( result.is_err(), "decrement from 0 must return Err to prevent double-free, got {:?}", result ); assert_eq!( refcount::get(addr), 0, "count must remain 0 after underflow" ); drop(frame); } ); crate::kernel_test!( fn overflow_returns_error() { let frame = BitmapFrameAllocator .allocate() .expect("alloc for overflow test"); let addr = frame.phys_addr(); (0..u16::MAX).for_each(|i| { refcount::increment(addr).unwrap_or_else(|_| panic!("increment {} should succeed", i)); }); assert_eq!(refcount::get(addr), u16::MAX, "should be at u16::MAX"); let result = refcount::increment(addr); assert!( result.is_err(), "increment past u16::MAX must return Err, not panic" ); (0..u16::MAX).for_each(|_| { let _ = refcount::decrement(addr); }); drop(frame); } ); crate::kernel_test!( fn into_shared_returns_some_for_valid_frame() { let frame = BitmapFrameAllocator .allocate() .expect("alloc for into_shared test"); let addr = frame.phys_addr(); let shared: Option = frame.into_shared(); assert!( shared.is_some(), "into_shared on valid frame must return Some" ); assert_eq!( refcount::get(addr), 1, "refcount should be 1 after into_shared" ); drop(shared); } ); crate::kernel_test!( fn duplicate_returns_some_for_valid_frame() { let frame = BitmapFrameAllocator .allocate() .expect("alloc for duplicate test"); let addr = frame.phys_addr(); let shared = frame.into_shared().expect("into_shared should succeed"); let dup: Option = shared.duplicate(); assert!( dup.is_some(), "duplicate on valid shared frame must return Some" ); assert_eq!( refcount::get(addr), 2, "refcount should be 2 after duplicate" ); drop(dup); assert_eq!( refcount::get(addr), 1, "refcount should be 1 after dropping dup" ); drop(shared); assert_eq!( refcount::get(addr), 0, "refcount should be 0 after dropping original" ); } );