From ccb8b79ef81b986dae51dd5e2c2976e34b374187 Mon Sep 17 00:00:00 2001 From: Philipp Oppermann Date: Tue, 23 Apr 2019 16:50:32 +0200 Subject: [PATCH] Add a panic handler test --- Cargo.toml | 4 +++ tests/panic_handler.rs | 69 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+) create mode 100644 tests/panic_handler.rs diff --git a/Cargo.toml b/Cargo.toml index 554e3482..d984b6ae 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,6 +4,10 @@ version = "0.1.0" authors = ["Philipp Oppermann "] edition = "2018" +[[test]] +name = "panic_handler" +harness = false + [dependencies] bootloader = "0.6.0" volatile = "0.2.3" diff --git a/tests/panic_handler.rs b/tests/panic_handler.rs new file mode 100644 index 00000000..c15df7d3 --- /dev/null +++ b/tests/panic_handler.rs @@ -0,0 +1,69 @@ +#![no_std] +#![no_main] +#![feature(panic_info_message)] + +use core::{fmt::{self, Write}, panic::PanicInfo}; +use blog_os::{serial_print, serial_println, QemuExitCode, exit_qemu}; + +const MESSAGE: &str = "Example panic message from panic_handler test"; +const PANIC_LINE: u32 = 14; // adjust this when moving the `panic!` call + +#[no_mangle] +pub extern "C" fn _start() -> ! { + serial_print!("panic_handler... "); + panic!(MESSAGE); // must be in line `PANIC_LINE` +} + +#[panic_handler] +fn panic(info: &PanicInfo) -> ! { + check_location(info); + check_message(info); + + serial_println!("[ok]"); + exit_qemu(QemuExitCode::Success); + loop {} +} + +fn fail(error: &str) -> ! { + serial_println!("[failed]"); + serial_println!("{}", error); + exit_qemu(QemuExitCode::Failed); + loop {} +} + +fn check_location(info: &PanicInfo) { + let location = info.location().unwrap_or_else(|| fail("no location")); + if location.file() != file!() { + fail("file name wrong"); + } + if location.line() != PANIC_LINE { + fail("file line wrong"); + } +} + +fn check_message(info: &PanicInfo) { + let message = info.message().unwrap_or_else(|| fail("no message")); + let mut compare_message = CompareMessage { equals: false }; + write!(&mut compare_message, "{}", message).unwrap_or_else(|_| fail("write failed")); + if !compare_message.equals { + fail("message not equal to expected message"); + } +} + +/// Compares a `fmt::Arguments` instance with the `MESSAGE` string +/// +/// To use this type, write the `fmt::Arguments` instance to it using the +/// `write` macro. If a message component matches `MESSAGE`, the equals +/// field is set to true. +struct CompareMessage { + equals: bool, +} + +impl fmt::Write for CompareMessage { + fn write_str(&mut self, s: &str) -> fmt::Result { + if s == MESSAGE { + self.equals = true; + } + Ok(()) + } +} \ No newline at end of file