feat(kernel): add Kernel struct, MockPlatform, and simple syscalls (GetTime, GetProcessId, Yield)
This commit is contained in:
70
crates/kernel/src/tests/mod.rs
Normal file
70
crates/kernel/src/tests/mod.rs
Normal file
@@ -0,0 +1,70 @@
|
||||
mod simple;
|
||||
|
||||
use domain::memory::page_pool::PagePool;
|
||||
use platform::Platform;
|
||||
use types::{
|
||||
address::{EntryPoint, PhysicalAddress, StackPointer},
|
||||
bounded::Priority,
|
||||
id::{CoreId, IrqId, ProcessId},
|
||||
time::{Ticks, TimerDuration, TimeSlice},
|
||||
};
|
||||
|
||||
use domain::memory::MemoryRegion;
|
||||
use domain::thread::SavedContext;
|
||||
|
||||
use crate::Kernel;
|
||||
|
||||
pub struct MockPlatform {
|
||||
ticks: Ticks,
|
||||
core: CoreId,
|
||||
cores: u8,
|
||||
}
|
||||
|
||||
impl MockPlatform {
|
||||
pub fn new(num_cores: u8) -> Self {
|
||||
Self {
|
||||
ticks: Ticks::from_raw(0),
|
||||
core: CoreId::from_raw(0),
|
||||
cores: num_cores,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_ticks(&mut self, ticks: Ticks) {
|
||||
self.ticks = ticks;
|
||||
}
|
||||
}
|
||||
|
||||
impl Platform for MockPlatform {
|
||||
fn configure_protection(&mut self, _process: ProcessId, _regions: &[MemoryRegion]) {}
|
||||
fn context_switch(&mut self, _from: &mut SavedContext, _to: &SavedContext) {}
|
||||
fn enable_user_mode(&mut self, _entry: EntryPoint, _stack: StackPointer) -> ! {
|
||||
loop {}
|
||||
}
|
||||
fn set_timer(&mut self, _duration: TimerDuration) {}
|
||||
fn current_ticks(&self) -> Ticks {
|
||||
self.ticks
|
||||
}
|
||||
fn mask_irq(&mut self, _irq: IrqId) {}
|
||||
fn unmask_irq(&mut self, _irq: IrqId) {}
|
||||
fn send_ipi(&mut self, _target: CoreId) {}
|
||||
fn core_id(&self) -> CoreId {
|
||||
self.core
|
||||
}
|
||||
fn num_cores(&self) -> u8 {
|
||||
self.cores
|
||||
}
|
||||
}
|
||||
|
||||
pub fn test_kernel() -> Kernel<MockPlatform> {
|
||||
let mock = MockPlatform::new(1);
|
||||
let pool = PagePool::new(PhysicalAddress::from_raw(0x8000_0000), 1024);
|
||||
Kernel::new(mock, pool)
|
||||
}
|
||||
|
||||
pub fn kernel_with_process() -> (Kernel<MockPlatform>, ProcessId) {
|
||||
let mut kernel = test_kernel();
|
||||
let (pid, _tid) = kernel
|
||||
.boot(Priority::new(16).unwrap(), TimeSlice::new(100))
|
||||
.unwrap();
|
||||
(kernel, pid)
|
||||
}
|
||||
45
crates/kernel/src/tests/simple.rs
Normal file
45
crates/kernel/src/tests/simple.rs
Normal file
@@ -0,0 +1,45 @@
|
||||
use super::*;
|
||||
use crate::{SyscallOutcome, SyscallResult};
|
||||
use domain::syscall::Syscall;
|
||||
use types::time::Ticks;
|
||||
|
||||
#[test]
|
||||
fn get_time_returns_current_ticks() {
|
||||
let (mut k, _) = kernel_with_process();
|
||||
k.platform_mut().set_ticks(Ticks::from_raw(12345));
|
||||
let outcome = k.handle_syscall(Syscall::GetTime);
|
||||
assert!(matches!(
|
||||
outcome,
|
||||
SyscallOutcome::Complete(SyscallResult::Value(12345))
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn get_process_id_returns_caller_process() {
|
||||
let (mut k, pid) = kernel_with_process();
|
||||
let outcome = k.handle_syscall(Syscall::GetProcessId);
|
||||
assert!(matches!(
|
||||
outcome,
|
||||
SyscallOutcome::Complete(SyscallResult::Value(v)) if v == pid.raw() as usize
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn yield_with_no_other_threads_returns_complete() {
|
||||
let (mut k, _) = kernel_with_process();
|
||||
let outcome = k.handle_syscall(Syscall::Yield);
|
||||
assert!(matches!(
|
||||
outcome,
|
||||
SyscallOutcome::Complete(SyscallResult::Ok)
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn syscall_with_no_running_thread_returns_error() {
|
||||
let mut k = test_kernel();
|
||||
let outcome = k.handle_syscall(Syscall::GetTime);
|
||||
assert!(matches!(
|
||||
outcome,
|
||||
SyscallOutcome::Complete(SyscallResult::Error(_))
|
||||
));
|
||||
}
|
||||
Reference in New Issue
Block a user