diff options
| author | Christian Cunningham <c@localhost> | 2022-08-22 21:28:18 -0700 |
|---|---|---|
| committer | Christian Cunningham <c@localhost> | 2022-08-22 21:28:18 -0700 |
| commit | c238b2ea1dff60a5be6a796f44e533e89a346199 (patch) | |
| tree | 47a6a0009172d83bcd2e1be7df9dbd8aeb77ea50 /src/kernel.rs | |
| parent | 8c60628bd5db5c238d22fd3ce8b739824606a9de (diff) | |
Add serial suite
Diffstat (limited to 'src/kernel.rs')
| -rw-r--r-- | src/kernel.rs | 74 |
1 files changed, 71 insertions, 3 deletions
diff --git a/src/kernel.rs b/src/kernel.rs index 2382345..cf594cd 100644 --- a/src/kernel.rs +++ b/src/kernel.rs @@ -5,13 +5,44 @@ #![no_std] // don't link the Rust standard library #![no_main] // disable all Rust-level entry points #![feature(const_mut_refs)] +#![feature(custom_test_frameworks)] +#![test_runner(crate::test_runner)] +#![reexport_test_harness_main = "test_main"] mod sync; mod vga; +mod serial; use vga::*; +use serial::*; use core::panic::PanicInfo; +pub trait Testable { + fn run(&self) -> (); +} + +impl<T> Testable for T +where + T: Fn(), +{ + fn run(&self) { + serial_print!("{}...\t", core::any::type_name::<T>()); + self(); + serial_println!("[ok]"); + } +} + +/// This function is called on panic. +#[cfg(test)] +#[panic_handler] +fn panic(info: &PanicInfo) -> ! { + serial_println!("[failed]\n"); + serial_println!("Error: {}\n", info); + exit_qemu(QemuExitCode::Failed); + loop {} +} + /// This function is called on panic. +#[cfg(not(test))] #[panic_handler] fn panic(info: &PanicInfo) -> ! { println!("{}", info); @@ -20,15 +51,52 @@ fn panic(info: &PanicInfo) -> ! { fn kernel_init() { WRITER.init(); + SERIAL1.init(); } #[no_mangle] pub extern "C" fn _start() -> ! { kernel_init(); - WRITER.write_string("Hello World!"); - WRITER.write_string("\n\nHi\n"); - println!("{}", 5); + #[cfg(not(test))] + { + WRITER.write_string("Hello World!"); + WRITER.write_string("\n\nHi\n"); + println!("{}", 5); + } + + #[cfg(test)] + test_main(); loop {} } + +#[cfg(test)] +fn test_runner(tests: &[&dyn Testable]) { + serial_println!("Running {} tests", tests.len()); + for test in tests { + test.run(); + } + exit_qemu(QemuExitCode::Success); +} + +#[test_case] +fn trivial_assertion() { + assert_eq!(1, 1); +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[repr(u32)] +pub enum QemuExitCode { + Success = 0x10, + Failed = 0x11, +} + +pub fn exit_qemu(exit_code: QemuExitCode) { + use x86_64::instructions::port::Port; + + unsafe { + let mut port = Port::new(0xf4); + port.write(exit_code as u32); + } +} |
