use super::*; use crate::{SyscallOutcome, SyscallResult}; use domain::syscall::Syscall; use types::address::{DataRef, EntryPoint, StackPointer}; use types::bounded::CapSlot; use types::id::ThreadId; #[test] fn spawn_thread_creates_ready_thread() { let (mut k, _) = kernel_with_process(); let outcome = k.handle_syscall(Syscall::SpawnThread { entry: EntryPoint::from_raw(0x1000), stack: StackPointer::from_raw(0x2000), arg: 0, }); assert!(matches!( outcome, SyscallOutcome::Complete(SyscallResult::Value(_)) )); } #[test] fn spawn_thread_preserves_entry_stack_and_arg() { let (mut k, _) = kernel_with_process(); let tid = match k.handle_syscall(Syscall::SpawnThread { entry: EntryPoint::from_raw(0xDEAD), stack: StackPointer::from_raw(0xBEEF), arg: 0x5107, }) { SyscallOutcome::Complete(SyscallResult::Value(v)) => ThreadId::from_raw(v as u16), _ => panic!("expected Value"), }; let ctx = k.thread_context(tid).unwrap(); assert_eq!(ctx.program_counter(), 0xDEAD); assert_eq!(ctx.registers()[2], 0xBEEF); assert_eq!( ctx.registers()[10], 0x5107, "the start argument arrives in a0" ); } #[test] fn create_process_with_cap_succeeds() { let (mut k, _) = kernel_with_process(); // boot() grants ProcessCreate cap at slot 0 let outcome = k.handle_syscall(Syscall::CreateProcess { create_cap: CapSlot::new(0).unwrap(), image: DataRef::empty(), }); assert!(matches!( outcome, SyscallOutcome::Complete(SyscallResult::Slot(_)) )); } #[test] fn create_process_without_cap_fails() { let (mut k, _) = kernel_with_process(); // slot 5 doesn't exist let outcome = k.handle_syscall(Syscall::CreateProcess { create_cap: CapSlot::new(5).unwrap(), image: DataRef::empty(), }); assert!(matches!( outcome, SyscallOutcome::Complete(SyscallResult::Error(_)) )); } #[test] fn kill_removes_process() { let (mut k, _pid) = kernel_with_process(); // Create a second process, get cap for it let slot = match k.handle_syscall(Syscall::CreateProcess { create_cap: CapSlot::new(0).unwrap(), image: DataRef::empty(), }) { SyscallOutcome::Complete(SyscallResult::Slot(s)) => s, _ => panic!("expected slot"), }; let outcome = k.handle_syscall(Syscall::Kill { process: slot }); assert!(matches!( outcome, SyscallOutcome::Complete(SyscallResult::Ok) )); }