Tests and test output over serial working

This commit is contained in:
Greg Shuflin 2022-02-20 02:01:45 -08:00
parent 4d7aa79434
commit a5fb50ffb5
5 changed files with 125 additions and 0 deletions

View File

@ -5,3 +5,6 @@ build-std-features = ["compiler-builtins-mem"]
[build] [build]
target = "x86_64_target.json" target = "x86_64_target.json"
# Facilitates running tests with qemu
[target.'cfg(target_os = "none")']
runner = "bootimage runner"

41
Cargo.lock generated
View File

@ -2,6 +2,18 @@
# It is not intended for manual editing. # It is not intended for manual editing.
version = 3 version = 3
[[package]]
name = "bit_field"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcb6dd1c2376d2e096796e234a70e17e94cc2d5d54ff8ce42b28cef1d0d359a4"
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]] [[package]]
name = "bootloader" name = "bootloader"
version = "0.9.21" version = "0.9.21"
@ -33,6 +45,8 @@ dependencies = [
"bootloader", "bootloader",
"lazy_static", "lazy_static",
"spin 0.9.2", "spin 0.9.2",
"uart_16550",
"x86_64",
] ]
[[package]] [[package]]
@ -55,3 +69,30 @@ checksum = "511254be0c5bcf062b019a6c89c01a664aa359ded62f78aa72c6fc137c0590e5"
dependencies = [ dependencies = [
"lock_api", "lock_api",
] ]
[[package]]
name = "uart_16550"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af81448a9a53c7b0f66198381f80912fd18f2c8965f9da4319e6f92e740bca5b"
dependencies = [
"bitflags",
"x86_64",
]
[[package]]
name = "volatile"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e4c2dbd44eb8b53973357e6e207e370f0c1059990df850aca1eca8947cf464f0"
[[package]]
name = "x86_64"
version = "0.14.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "958ab3202b01bc43ba2eb832102c4a487ed93151667a2289062e5f2b00058be2"
dependencies = [
"bit_field",
"bitflags",
"volatile",
]

View File

@ -8,8 +8,14 @@ edition = "2021"
#bootloader = "0.10.12" #bootloader = "0.10.12"
bootloader = "0.9.8" bootloader = "0.9.8"
spin = "0.9.2" spin = "0.9.2"
x86_64 = "0.14.8"
uart_16550 = "0.2.16"
[dependencies.lazy_static] [dependencies.lazy_static]
version = "1.4.0" version = "1.4.0"
features = ["spin_no_std"] features = ["spin_no_std"]
[package.metadata.bootimage]
test-args = ["-device", "isa-debug-exit,iobase=0xf4,iosize=0x04", "-serial", "stdio"]
test-success-exit-code = 33 # (0x10 << 1) | 1

View File

@ -2,8 +2,14 @@
#![no_std] #![no_std]
#![no_main] #![no_main]
#![feature(custom_test_frameworks)]
#![test_runner(crate::test_runner)]
#![reexport_test_harness_main = "test_main"]
#[macro_use] #[macro_use]
mod vga_buffer; mod vga_buffer;
#[macro_use]
mod serial;
use core::panic::PanicInfo; use core::panic::PanicInfo;
@ -15,6 +21,42 @@ fn panic(info: &PanicInfo) -> ! {
#[no_mangle] #[no_mangle]
pub extern "C" fn _start() -> ! { pub extern "C" fn _start() -> ! {
#[cfg(test)]
test_main();
println!("Gamarjoba, munde!"); println!("Gamarjoba, munde!");
loop {} loop {}
} }
#[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); // isa-debug-exit port, see Cargo.toml
port.write(exit_code as u32);
}
}
#[cfg(test)]
fn test_runner(tests: &[&dyn Fn()]) {
serial_println!("Running {} test(s)", tests.len());
for test in tests {
test();
}
exit_qemu(QemuExitCode::Success);
}
#[test_case]
fn basic_test() {
serial_print!("Trivial test... ");
assert_eq!(5, 5);
serial_println!("[ok]");
}

33
src/serial.rs Normal file
View File

@ -0,0 +1,33 @@
use uart_16550::SerialPort;
use spin::Mutex;
use lazy_static::lazy_static;
lazy_static! {
pub static ref SERIAL1: Mutex<SerialPort> = {
let mut serial_port = unsafe { SerialPort::new(0x3f8) }; // 0x3f8 is standard address of 1st serial port
serial_port.init();
Mutex::new(serial_port)
};
}
#[doc(hidden)]
pub fn _print(args: ::core::fmt::Arguments) {
use core::fmt::Write;
SERIAL1.lock().write_fmt(args).expect("Serial print failed");
}
#[macro_export]
macro_rules! serial_print {
($($arg:tt)*) => {
$crate::serial::_print(format_args!($($arg)*));
};
}
#[macro_export]
macro_rules! serial_println {
() => ($crate::serial_print!("\n"));
($fmt:expr) => ($crate::serial_print!(concat!($fmt, "\n")));
($fmt:expr, $($arg:tt)*) => ($crate::serial_print!(
concat!($fmt, "\n"), $($arg)*));
}