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 | |
| parent | 8c60628bd5db5c238d22fd3ce8b739824606a9de (diff) | |
Add serial suite
| -rw-r--r-- | Cargo.toml | 4 | ||||
| -rw-r--r-- | src/.sync.rs.swp | bin | 12288 -> 0 bytes | |||
| -rw-r--r-- | src/kernel.rs | 74 | ||||
| -rw-r--r-- | src/vga/.buffer.rs.swp | bin | 20480 -> 20480 bytes | |||
| -rw-r--r-- | src/vga/.mod.rs.swp | bin | 12288 -> 0 bytes | |||
| -rw-r--r-- | src/vga/buffer.rs | 34 |
6 files changed, 108 insertions, 4 deletions
@@ -11,7 +11,11 @@ path = "src/kernel.rs" [dependencies] bootloader = "0.9.8" volatile = "0.2.6" +x86_64 = "0.14.2" +uart_16550 = "0.2.0" [package.metadata.bootimage] #run-command = ["qemu-system-x86_64", "-drive", "format=raw,file={}", "-serial", "mon:stdio"] run-args = ["-serial", "mon:stdio"] +test-args = ["-device", "isa-debug-exit,iobase=0xf4,iosize=0x04", "-serial", "mon:stdio", "-display","none"] +test-success-exit-code = 33 diff --git a/src/.sync.rs.swp b/src/.sync.rs.swp Binary files differdeleted file mode 100644 index 462e2ef..0000000 --- a/src/.sync.rs.swp +++ /dev/null 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); + } +} diff --git a/src/vga/.buffer.rs.swp b/src/vga/.buffer.rs.swp Binary files differindex 0ce0feb..012b7b1 100644 --- a/src/vga/.buffer.rs.swp +++ b/src/vga/.buffer.rs.swp diff --git a/src/vga/.mod.rs.swp b/src/vga/.mod.rs.swp Binary files differdeleted file mode 100644 index 6071785..0000000 --- a/src/vga/.mod.rs.swp +++ /dev/null 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<VgaWriter> { }); } + #[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<VgaWriter> = 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); + } +} |
