use super::*; use crate::capability::CapabilityTable; use types::bounded::CapSlot; use types::id::{ProcessId, ThreadId}; fn thread(id: u16) -> ThreadId { ThreadId::from_raw(id) } fn test_process(id: u16) -> Process { Process::new(ProcessId::from_raw(id), CapabilityTable::new(), None) } #[test] fn new_process_has_no_threads() { let p = test_process(0); assert_eq!(p.thread_ids().count(), 0); } #[test] fn id_matches_construction() { let p = test_process(42); assert_eq!(p.id(), ProcessId::from_raw(42)); } #[test] fn fault_handler_none_by_default() { let p = test_process(0); assert!(p.fault_handler().is_none()); } #[test] fn fault_handler_preserved() { let slot = CapSlot::new(5).unwrap(); let p = Process::new(ProcessId::from_raw(0), CapabilityTable::new(), Some(slot)); assert_eq!(p.fault_handler(), Some(slot)); } #[test] fn add_and_iterate_threads() { let mut p = test_process(0); p.add_thread(thread(0)).unwrap(); p.add_thread(thread(1)).unwrap(); assert_eq!(p.thread_ids().count(), 2); assert!(p.thread_ids().any(|t| t == thread(0))); assert!(p.thread_ids().any(|t| t == thread(1))); } #[test] fn add_thread_beyond_max_fails() { let mut p = test_process(0); for i in 0..MAX_THREADS_PER_PROCESS { p.add_thread(thread(i as u16)).unwrap(); } assert!(p.add_thread(thread(99)).is_err()); } #[test] fn remove_thread_frees_slot() { let mut p = test_process(0); p.add_thread(thread(0)).unwrap(); p.remove_thread(thread(0)); assert_eq!(p.thread_ids().count(), 0); p.add_thread(thread(1)).unwrap(); assert_eq!(p.thread_ids().count(), 1); } #[test] fn capabilities_accessible() { let p = test_process(0); let _caps = p.capabilities(); } #[test] fn capabilities_mut_accessible() { let mut p = test_process(0); let _caps = p.capabilities_mut(); } // --- ProcessTable tests --- #[test] fn table_create_and_lookup() { let mut table = ProcessTable::new(); let id = table.create(CapabilityTable::new(), None).unwrap(); assert_eq!(table.get(id).unwrap().id(), id); } #[test] fn table_create_returns_unique_ids() { let mut table = ProcessTable::new(); let a = table.create(CapabilityTable::new(), None).unwrap(); let b = table.create(CapabilityTable::new(), None).unwrap(); assert_ne!(a, b); } #[test] fn table_destroy_then_get_fails() { let mut table = ProcessTable::new(); let id = table.create(CapabilityTable::new(), None).unwrap(); table.destroy(id).unwrap(); assert!(table.get(id).is_err()); } #[test] fn table_full_returns_error() { let mut table = ProcessTable::new(); for _ in 0..MAX_PROCESSES { table.create(CapabilityTable::new(), None).unwrap(); } assert!(table.create(CapabilityTable::new(), None).is_err()); } #[test] fn table_destroy_reuses_slot() { let mut table = ProcessTable::new(); let id = table.create(CapabilityTable::new(), None).unwrap(); table.destroy(id).unwrap(); let new_id = table.create(CapabilityTable::new(), None).unwrap(); assert_eq!(id, new_id); } #[test] fn table_get_mut_allows_modification() { let mut table = ProcessTable::new(); let id = table.create(CapabilityTable::new(), None).unwrap(); let p = table.get_mut(id).unwrap(); p.add_thread(thread(0)).unwrap(); assert_eq!(table.get(id).unwrap().thread_ids().count(), 1); }