use turkos_os_shell_foreground::{Adapter, Cause, Error, Foreground, Outcome, Pid}; #[derive(Default)] struct Fake { next: u64, fail_spawn: bool, fail_wait: bool, waits: Vec } impl Adapter for Fake { fn spawn(&mut self) -> Result { if self.fail_spawn { self.fail_spawn = false; return Err(Cause::Injected); } self.next += 1; Ok(Pid(self.next)) } fn wait(&mut self, pid: Pid) -> Result { self.waits.push(pid); if self.fail_wait { self.fail_wait = false; return Err(Cause::Busy); } if pid == Pid(2) { Ok(Outcome::Fault(0x9000_0000)) } else { Ok(Outcome::Exited(42)) } } } #[test] fn os_shell_foreground_runs_one_child_and_returns_outcome() { let mut foreground = Foreground::new(); let mut adapter = Fake::default(); assert_eq!(foreground.launch(&mut adapter), Ok(Pid(1))); assert_eq!(foreground.owner(), Some(Pid(1))); assert_eq!(foreground.launch(&mut adapter), Err(Error::AlreadyRunning)); assert_eq!(foreground.collect(&mut adapter), Ok(Outcome::Exited(42))); assert_eq!(foreground.owner(), None); assert_eq!(foreground.launch(&mut adapter), Ok(Pid(2))); assert_eq!(foreground.collect(&mut adapter), Ok(Outcome::Fault(0x9000_0000))); assert_eq!(adapter.waits, [Pid(1), Pid(2)]); } #[test] fn os_shell_foreground_rejects_empty_and_failed_spawn() { let mut foreground = Foreground::new(); let mut adapter = Fake {fail_spawn: true, ..Fake::default()}; assert_eq!(foreground.collect(&mut adapter), Err(Error::NoForeground)); assert_eq!(foreground.launch(&mut adapter), Err(Error::Spawn(Cause::Injected))); assert_eq!(foreground.owner(), None); struct Zero; impl Adapter for Zero { fn spawn(&mut self) -> Result { Ok(Pid(0)) } fn wait(&mut self, _: Pid) -> Result { unreachable!() } } assert_eq!(foreground.launch(&mut Zero), Err(Error::InvalidPid)); assert_eq!(foreground.owner(), None); } #[test] fn os_shell_foreground_wait_error_retains_owner() { let mut foreground = Foreground::new(); let mut adapter = Fake {fail_wait: true, ..Fake::default()}; foreground.launch(&mut adapter).unwrap(); assert_eq!(foreground.collect(&mut adapter), Err(Error::Wait(Cause::Busy))); assert_eq!(foreground.owner(), Some(Pid(1))); assert_eq!(foreground.launch(&mut adapter), Err(Error::AlreadyRunning)); assert_eq!(foreground.collect(&mut adapter), Ok(Outcome::Exited(42))); assert_eq!(foreground.owner(), None); assert_eq!(adapter.waits, [Pid(1), Pid(1)]); }