From c238b2ea1dff60a5be6a796f44e533e89a346199 Mon Sep 17 00:00:00 2001 From: Christian Cunningham Date: Mon, 22 Aug 2022 21:28:18 -0700 Subject: Add serial suite --- src/.sync.rs.swp | Bin 12288 -> 0 bytes src/kernel.rs | 74 +++++++++++++++++++++++++++++++++++++++++++++++-- src/vga/.buffer.rs.swp | Bin 20480 -> 20480 bytes src/vga/.mod.rs.swp | Bin 12288 -> 0 bytes src/vga/buffer.rs | 34 ++++++++++++++++++++++- 5 files changed, 104 insertions(+), 4 deletions(-) delete mode 100644 src/.sync.rs.swp delete mode 100644 src/vga/.mod.rs.swp (limited to 'src') diff --git a/src/.sync.rs.swp b/src/.sync.rs.swp deleted file mode 100644 index 462e2ef..0000000 Binary files a/src/.sync.rs.swp and /dev/null differ 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 Testable for T +where + T: Fn(), +{ + fn run(&self) { + serial_print!("{}...\t", core::any::type_name::()); + 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); + } +} diff --git a/src/vga/.buffer.rs.swp b/src/vga/.buffer.rs.swp index 0ce0feb..012b7b1 100644 Binary files a/src/vga/.buffer.rs.swp and b/src/vga/.buffer.rs.swp differ diff --git a/src/vga/.mod.rs.swp b/src/vga/.mod.rs.swp deleted file mode 100644 index 6071785..0000000 Binary files a/src/vga/.mod.rs.swp and /dev/null differ diff --git a/src/vga/buffer.rs b/src/vga/buffer.rs index 34c665d..4ca001c 100644 --- a/src/vga/buffer.rs +++ b/src/vga/buffer.rs @@ -109,6 +109,7 @@ impl NullLock { }); } + #[allow(dead_code)] pub fn write_string(&self, s: &str) { self.lock(|writer| { writer.write_string(s); @@ -152,6 +153,37 @@ macro_rules! println { pub static WRITER: NullLock = NullLock::new(VgaWriter { column_position: 0, - color_code: ColorCode::new(Color::Yellow, Color::Black), + color_code: ColorCode::new(Color::LightBlue, Color::Black), buffer: None, }); + +#[test_case] +fn test_println_simple() { + println!("test_println_simple output"); +} + +#[test_case] +fn test_println_many() { + for _ in 0..200 { + println!("test_println_many output"); + } +} + +#[test_case] +fn test_println_output() { + let s = "Some test string that fits on a single line"; + println!("{}", s); + for (i, c) in s.chars().enumerate() { + let screen_char = WRITER.lock(|writer| { + if let Some(buffer) = &writer.buffer { + return buffer.chars[BUFFER_HEIGHT - 2][i].read(); + } else { + return ScreenChar { + ascii_character: b' ', + color_code: ColorCode::new(Color::LightBlue, Color::Black), + }; + } + }); + assert_eq!(char::from(screen_char.ascii_character), c); + } +} -- cgit v1.2.1