Nothing to see here, move along meow
0

Configure Feed

Select the types of activity you want to include in your feed.

at main 13 kB View raw
1use lancer_core::header::{KernelObjectHeader, NONE_SENTINEL}; 2use lancer_core::object_layout::*; 3use lancer_core::object_tag::ObjectTag; 4use lancer_core::untyped::UntypedState; 5 6#[test] 7fn header_size_is_24() { 8 assert_eq!(core::mem::size_of::<KernelObjectHeader>(), 24); 9} 10 11#[test] 12fn all_fixed_objects_are_64_bytes() { 13 assert_eq!(core::mem::size_of::<EndpointObject>(), 64); 14 assert_eq!(core::mem::size_of::<NotificationObject>(), 64); 15 assert_eq!(core::mem::size_of::<SchedContextObject>(), 64); 16 assert_eq!(core::mem::size_of::<UntypedObject>(), 64); 17 assert_eq!(core::mem::size_of::<IrqHandlerObject>(), 64); 18 assert_eq!(core::mem::size_of::<FramebufferObject>(), 64); 19 assert_eq!(core::mem::size_of::<PciDeviceObject>(), 64); 20 assert_eq!(core::mem::size_of::<ProcessObject>(), 64); 21 assert_eq!(core::mem::size_of::<FrameObject>(), 64); 22 assert_eq!(core::mem::size_of::<CNodeObject>(), 64); 23 assert_eq!(core::mem::size_of::<VRegionObject>(), 64); 24} 25 26#[test] 27fn header_field_offsets() { 28 assert_eq!(core::mem::offset_of!(KernelObjectHeader, tag), 0); 29 assert_eq!(core::mem::offset_of!(KernelObjectHeader, generation), 4); 30 assert_eq!(core::mem::offset_of!(KernelObjectHeader, ref_count), 8); 31 assert_eq!( 32 core::mem::offset_of!(KernelObjectHeader, parent_untyped), 33 12 34 ); 35 assert_eq!(core::mem::offset_of!(KernelObjectHeader, next_child), 16); 36 assert_eq!(core::mem::offset_of!(KernelObjectHeader, object_size), 20); 37} 38 39#[test] 40fn data_fields_start_after_header() { 41 assert_eq!(core::mem::offset_of!(EndpointObject, sender_head), 24); 42 assert_eq!(core::mem::offset_of!(NotificationObject, word), 24); 43 assert_eq!(core::mem::offset_of!(SchedContextObject, replenish_at), 24); 44 assert_eq!(core::mem::offset_of!(UntypedObject, phys_base), 24); 45 assert_eq!(core::mem::offset_of!(IrqHandlerObject, vector), 24); 46 assert_eq!(core::mem::offset_of!(FramebufferObject, phys_addr), 24); 47 assert_eq!(core::mem::offset_of!(PciDeviceObject, device_table_idx), 24); 48 assert_eq!(core::mem::offset_of!(ProcessObject, pid), 24); 49 assert_eq!(core::mem::offset_of!(FrameObject, phys_addr), 24); 50 assert_eq!(core::mem::offset_of!(CNodeObject, slots_phys), 24); 51 assert_eq!(core::mem::offset_of!(VRegionObject, phys_base), 24); 52} 53 54#[test] 55fn init_default_sets_tag_and_refcount() { 56 let header = KernelObjectHeader::new(ObjectTag::Endpoint, 42, 64); 57 let obj = EndpointObject::init_default(header); 58 assert_eq!(obj.header.tag_byte(), ObjectTag::Endpoint as u8); 59 assert_eq!(obj.header.ref_count(), 1); 60 assert_eq!(obj.header.generation(), 42); 61 assert_eq!(obj.header.object_size(), 64); 62 assert_eq!(obj.sender_head, NONE_SENTINEL); 63 assert_eq!(obj.sender_tail, NONE_SENTINEL); 64 assert_eq!(obj.sender_len, 0); 65 assert_eq!(obj.receiver_head, NONE_SENTINEL); 66 assert_eq!(obj.receiver_tail, NONE_SENTINEL); 67 assert_eq!(obj.receiver_len, 0); 68 assert_eq!(obj.holder, NONE_SENTINEL); 69} 70 71#[test] 72fn init_default_notification() { 73 let header = KernelObjectHeader::new(ObjectTag::Notification, 7, 64); 74 let obj = NotificationObject::init_default(header); 75 assert_eq!(obj.header.tag_byte(), ObjectTag::Notification as u8); 76 assert_eq!(obj.word, 0); 77 assert_eq!(obj.waiter_count, 0); 78 obj.waiters 79 .iter() 80 .for_each(|w| assert_eq!(*w, NONE_SENTINEL)); 81} 82 83#[test] 84fn init_default_sched_context() { 85 let header = KernelObjectHeader::new(ObjectTag::SchedContext, 0, 64); 86 let obj = SchedContextObject::init_default(header); 87 assert_eq!(obj.budget_us, 0); 88 assert_eq!(obj.period_us, 0); 89 assert_eq!(obj.remaining_us, 0); 90 assert_eq!(obj.replenish_at, 0); 91 assert_eq!(obj.attached_pid, NONE_SENTINEL); 92 assert_eq!(obj.priority, 0); 93 assert_eq!(obj.flags, 0); 94} 95 96#[test] 97fn header_parent_and_child_default_to_none() { 98 let header = KernelObjectHeader::new(ObjectTag::Endpoint, 0, 64); 99 assert_eq!(header.parent_untyped(), NONE_SENTINEL); 100 assert_eq!(header.next_child(), NONE_SENTINEL); 101} 102 103#[test] 104fn inc_dec_ref_roundtrip() { 105 let mut header = KernelObjectHeader::new(ObjectTag::Endpoint, 0, 64); 106 assert_eq!(header.ref_count(), 1); 107 assert_eq!(header.inc_ref(), Some(2)); 108 assert_eq!(header.ref_count(), 2); 109 assert_eq!(header.inc_ref(), Some(3)); 110 assert_eq!(header.ref_count(), 3); 111 let remaining = header.dec_ref(); 112 assert_eq!(remaining, 2); 113 let remaining = header.dec_ref(); 114 assert_eq!(remaining, 1); 115 let remaining = header.dec_ref(); 116 assert_eq!(remaining, 0); 117} 118 119#[test] 120fn ref_count_saturates() { 121 let mut header = KernelObjectHeader::new(ObjectTag::Endpoint, 0, 64); 122 let remaining = header.dec_ref(); 123 assert_eq!(remaining, 0); 124 let remaining = header.dec_ref(); 125 assert_eq!(remaining, 0); 126} 127 128#[test] 129fn inc_ref_returns_none_at_max() { 130 let mut header = KernelObjectHeader::new(ObjectTag::Endpoint, 0, 64); 131 header.ref_count = u32::MAX; 132 assert_eq!(header.inc_ref(), None); 133 assert_eq!(header.ref_count(), u32::MAX); 134} 135 136#[test] 137fn inc_ref_sequential() { 138 let mut header = KernelObjectHeader::new(ObjectTag::Endpoint, 0, 64); 139 (0..10u32).for_each(|_| { 140 assert!(header.inc_ref().is_some()); 141 }); 142 assert_eq!(header.ref_count(), 11); 143} 144 145#[test] 146fn is_stale_correctness() { 147 let header = KernelObjectHeader::new(ObjectTag::Frame, 100, 64); 148 assert!(!header.is_stale(100)); 149 assert!(header.is_stale(99)); 150 assert!(header.is_stale(101)); 151} 152 153#[test] 154fn set_parent_and_next_child() { 155 let mut header = KernelObjectHeader::new(ObjectTag::Endpoint, 0, 64); 156 header.set_parent_untyped(42); 157 header.set_next_child(99); 158 assert_eq!(header.parent_untyped(), 42); 159 assert_eq!(header.next_child(), 99); 160} 161 162#[test] 163fn untyped_state_roundtrip() { 164 let state = UntypedState::from_parts(1024, 20, true, 5); 165 let header = KernelObjectHeader::new(ObjectTag::Untyped, 0, 64); 166 let mut obj = UntypedObject::init_default(header); 167 obj.apply_state(&state); 168 169 let recovered = obj.to_state(); 170 assert_eq!(recovered.watermark(), 1024); 171 assert_eq!(recovered.size_bits(), 20); 172 assert!(recovered.is_device()); 173 assert_eq!(recovered.child_count(), 5); 174} 175 176#[test] 177fn untyped_state_roundtrip_non_device() { 178 let state = UntypedState::new(15, false); 179 let header = KernelObjectHeader::new(ObjectTag::Untyped, 0, 64); 180 let mut obj = UntypedObject::init_default(header); 181 obj.apply_state(&state); 182 183 let recovered = obj.to_state(); 184 assert_eq!(recovered.watermark(), 0); 185 assert_eq!(recovered.size_bits(), 15); 186 assert!(!recovered.is_device()); 187 assert_eq!(recovered.child_count(), 0); 188} 189 190#[test] 191fn kernel_object_trait_constants() { 192 assert_eq!(EndpointObject::METADATA_SIZE, 64); 193 assert_eq!(EndpointObject::METADATA_ALIGN, 64); 194 assert_eq!(EndpointObject::TAG, ObjectTag::Endpoint); 195 196 assert_eq!(CNodeObject::TAG, ObjectTag::CNode); 197 assert_eq!(FrameObject::TAG, ObjectTag::Frame); 198 assert_eq!(UntypedObject::TAG, ObjectTag::Untyped); 199 assert_eq!(SchedContextObject::TAG, ObjectTag::SchedContext); 200 assert_eq!(VRegionObject::TAG, ObjectTag::VRegion); 201} 202 203#[test] 204fn frame_object_default_size_bits() { 205 let header = KernelObjectHeader::new(ObjectTag::Frame, 0, 64); 206 let obj = FrameObject::init_default(header); 207 assert_eq!(obj.size_bits, 12); 208 assert_eq!(obj.phys_addr, 0); 209} 210 211#[test] 212fn cnode_object_default() { 213 let header = KernelObjectHeader::new(ObjectTag::CNode, 0, 64); 214 let obj = CNodeObject::init_default(header); 215 assert_eq!(obj.slots_phys, 0); 216 assert_eq!(obj.size_bits, 0); 217 assert_eq!(obj.frame_count, 0); 218} 219 220#[test] 221fn init_default_tag_matches_trait_tag_all_types() { 222 fn check<T: KernelObject>() { 223 let header = KernelObjectHeader::new(T::TAG, 0, T::METADATA_SIZE as u16); 224 let obj = T::init_default(header); 225 let header_ref: &KernelObjectHeader = 226 unsafe { &*((&obj as *const T).cast::<KernelObjectHeader>()) }; 227 assert_eq!(header_ref.tag_byte(), T::TAG as u8); 228 assert_eq!(header_ref.object_size(), T::METADATA_SIZE as u16); 229 } 230 check::<EndpointObject>(); 231 check::<NotificationObject>(); 232 check::<SchedContextObject>(); 233 check::<UntypedObject>(); 234 check::<IrqHandlerObject>(); 235 check::<FramebufferObject>(); 236 check::<PciDeviceObject>(); 237 check::<ProcessObject>(); 238 check::<FrameObject>(); 239 check::<CNodeObject>(); 240 check::<VRegionObject>(); 241} 242 243#[test] 244fn vregion_object_field_offsets() { 245 assert_eq!(core::mem::offset_of!(VRegionObject, header), 0); 246 assert_eq!(core::mem::offset_of!(VRegionObject, phys_base), 24); 247 assert_eq!(core::mem::offset_of!(VRegionObject, owner_vaddr), 32); 248 assert_eq!(core::mem::offset_of!(VRegionObject, child_vaddr), 40); 249 assert_eq!(core::mem::offset_of!(VRegionObject, owner_pid), 48); 250 assert_eq!(core::mem::offset_of!(VRegionObject, child_pid), 52); 251 assert_eq!(core::mem::offset_of!(VRegionObject, page_count), 56); 252 assert_eq!(core::mem::offset_of!(VRegionObject, flags), 58); 253 assert_eq!(core::mem::offset_of!(VRegionObject, is_derived), 60); 254} 255 256#[test] 257fn vregion_object_init_default() { 258 let header = KernelObjectHeader::new(ObjectTag::VRegion, 0, 64); 259 let obj = VRegionObject::init_default(header); 260 assert_eq!(obj.header.tag_byte(), ObjectTag::VRegion as u8); 261 assert_eq!(obj.phys_base, 0); 262 assert_eq!(obj.owner_vaddr, 0); 263 assert_eq!(obj.child_vaddr, 0); 264 assert_eq!(obj.owner_pid, NONE_SENTINEL); 265 assert_eq!(obj.child_pid, NONE_SENTINEL); 266 assert_eq!(obj.page_count, 0); 267 assert_eq!(obj.flags.raw(), 0); 268 assert_eq!(obj.is_derived, 0); 269} 270 271#[test] 272fn vregion_flags_basic() { 273 use lancer_core::types::VRegionFlags; 274 275 let empty = VRegionFlags::try_new(0).unwrap(); 276 assert!(!empty.writable()); 277 assert!(!empty.executable()); 278 279 let rw = VRegionFlags::try_new(VRegionFlags::WRITABLE).unwrap(); 280 assert!(rw.writable()); 281 assert!(!rw.executable()); 282 283 let rx = VRegionFlags::try_new(VRegionFlags::EXECUTABLE).unwrap(); 284 assert!(!rx.writable()); 285 assert!(rx.executable()); 286 287 let rwx = VRegionFlags::try_new(VRegionFlags::WRITABLE | VRegionFlags::EXECUTABLE).unwrap(); 288 assert!(rwx.writable()); 289 assert!(rwx.executable()); 290 291 assert!(VRegionFlags::try_new(0b100).is_none()); 292} 293 294#[test] 295fn vregion_flags_subset() { 296 use lancer_core::types::VRegionFlags; 297 298 let rw = VRegionFlags::try_new(VRegionFlags::WRITABLE).unwrap(); 299 let rwx = VRegionFlags::try_new(VRegionFlags::WRITABLE | VRegionFlags::EXECUTABLE).unwrap(); 300 let empty = VRegionFlags::try_new(0).unwrap(); 301 302 assert!(rw.is_subset_of(rwx)); 303 assert!(empty.is_subset_of(rw)); 304 assert!(empty.is_subset_of(rwx)); 305 assert!(!rwx.is_subset_of(rw)); 306} 307 308#[test] 309fn untyped_vregion_allocation_math() { 310 let state = UntypedState::new(20, false); 311 let backing_size = 16u32 * 4096; 312 let result = state.try_allocate_raw(backing_size, 4096, 1).unwrap(); 313 assert_eq!(result.start_offset(), 0); 314 assert_eq!(result.stride(), backing_size); 315 assert_eq!(result.object_count(), 1); 316} 317 318#[test] 319fn untyped_vregion_insufficient_space() { 320 let state = UntypedState::new(14, false); 321 let backing_size = 16u32 * 4096; 322 assert!(state.try_allocate_raw(backing_size, 4096, 1).is_err()); 323} 324 325#[test] 326fn untyped_vregion_device_rejected() { 327 let state = UntypedState::new(20, true); 328 let result = state.try_retype(ObjectTag::VRegion, 0, 1); 329 assert!(result.is_err()); 330} 331 332use proptest::prelude::*; 333 334proptest! { 335 #[test] 336 fn arbitrary_generation_header(generation in proptest::num::u32::ANY) { 337 let header = KernelObjectHeader::new(ObjectTag::Notification, generation, 64); 338 prop_assert_eq!(header.generation(), generation); 339 prop_assert!(!header.is_stale(generation)); 340 prop_assert!(header.is_stale(generation.wrapping_add(1))); 341 } 342 343 #[test] 344 fn ref_count_sequence(ops in proptest::collection::vec(proptest::bool::ANY, 0..50)) { 345 let mut header = KernelObjectHeader::new(ObjectTag::Endpoint, 0, 64); 346 let mut expected: u32 = 1; 347 ops.iter().for_each(|inc| { 348 match *inc { 349 true => match expected.checked_add(1) { 350 Some(next) => { 351 assert_eq!(header.inc_ref(), Some(next)); 352 expected = next; 353 } 354 None => { 355 assert_eq!(header.inc_ref(), None); 356 } 357 }, 358 false => { 359 header.dec_ref(); 360 expected = expected.saturating_sub(1); 361 } 362 } 363 assert_eq!(header.ref_count(), expected); 364 }); 365 } 366}