move test runner to own module

This commit is contained in:
Corwin Kuiper 2022-01-18 19:49:07 +00:00
parent e75adf9e67
commit 1614e46c4e
4 changed files with 81 additions and 79 deletions

View file

@ -50,6 +50,7 @@ impl BlockAllocator {
} }
} }
#[allow(dead_code)]
pub unsafe fn number_of_blocks(&self) -> u32 { pub unsafe fn number_of_blocks(&self) -> u32 {
free(|key| { free(|key| {
let mut state = self.state.borrow(*key).borrow_mut(); let mut state = self.state.borrow(*key).borrow_mut();

View file

@ -35,6 +35,7 @@ const EWRAM_END: usize = 0x0204_0000;
#[global_allocator] #[global_allocator]
static GLOBAL_ALLOC: BlockAllocator = unsafe { BlockAllocator::new() }; static GLOBAL_ALLOC: BlockAllocator = unsafe { BlockAllocator::new() };
#[allow(dead_code)]
pub unsafe fn number_of_blocks() -> u32 { pub unsafe fn number_of_blocks() -> u32 {
GLOBAL_ALLOC.number_of_blocks() GLOBAL_ALLOC.number_of_blocks()
} }

View file

@ -29,6 +29,6 @@ mod tests {
display_logo(&mut gfx); display_logo(&mut gfx);
crate::assert_image_output("gfx/test_logo.png"); crate::test_runner::assert_image_output("gfx/test_logo.png");
} }
} }

View file

@ -2,7 +2,7 @@
// This appears to be needed for testing to work // This appears to be needed for testing to work
#![cfg_attr(test, no_main)] #![cfg_attr(test, no_main)]
#![cfg_attr(test, feature(custom_test_frameworks))] #![cfg_attr(test, feature(custom_test_frameworks))]
#![cfg_attr(test, test_runner(crate::test_runner))] #![cfg_attr(test, test_runner(crate::test_runner::test_runner))]
#![cfg_attr(test, reexport_test_harness_main = "test_main")] #![cfg_attr(test, reexport_test_harness_main = "test_main")]
#![deny(clippy::all)] #![deny(clippy::all)]
#![feature(alloc_error_handler)] #![feature(alloc_error_handler)]
@ -224,96 +224,96 @@ impl Gba {
} }
} }
#[doc(hidden)] #[cfg(test)]
pub trait Testable { mod test_runner {
fn run(&self, gba: &mut Gba); use super::*;
}
impl<T> Testable for T #[doc(hidden)]
where pub trait Testable {
T: Fn(&mut Gba), fn run(&self, gba: &mut Gba);
{ }
fn run(&self, gba: &mut Gba) {
impl<T> Testable for T
where
T: Fn(&mut Gba),
{
fn run(&self, gba: &mut Gba) {
let mut mgba = mgba::Mgba::new().unwrap();
mgba.print(
format_args!("{}...", core::any::type_name::<T>()),
mgba::DebugLevel::Info,
)
.unwrap();
mgba::number_of_cycles_tagged(785);
self(gba);
mgba::number_of_cycles_tagged(785);
assert!(
unsafe { agb_alloc::number_of_blocks() } < 2,
"memory is being leaked, there are {} blocks",
unsafe { agb_alloc::number_of_blocks() }
);
mgba.print(format_args!("[ok]"), mgba::DebugLevel::Info)
.unwrap();
}
}
#[panic_handler]
fn panic_implementation(info: &core::panic::PanicInfo) -> ! {
if let Some(mut mgba) = mgba::Mgba::new() {
mgba.print(format_args!("[failed]"), mgba::DebugLevel::Error)
.unwrap();
mgba.print(format_args!("Error: {}", info), mgba::DebugLevel::Fatal)
.unwrap();
}
loop {}
}
static mut TEST_GBA: Option<Gba> = None;
#[doc(hidden)]
pub fn test_runner(tests: &[&dyn Testable]) {
let mut mgba = mgba::Mgba::new().unwrap(); let mut mgba = mgba::Mgba::new().unwrap();
mgba.print( mgba.print(
format_args!("{}...", core::any::type_name::<T>()), format_args!("Running {} tests", tests.len()),
mgba::DebugLevel::Info, mgba::DebugLevel::Info,
) )
.unwrap(); .unwrap();
mgba::number_of_cycles_tagged(785);
self(gba);
mgba::number_of_cycles_tagged(785);
assert!( let gba = unsafe { TEST_GBA.as_mut() }.unwrap();
unsafe { agb_alloc::number_of_blocks() } < 2,
"memory is being leaked, there are {} blocks",
unsafe { agb_alloc::number_of_blocks() }
);
mgba.print(format_args!("[ok]"), mgba::DebugLevel::Info) for test in tests {
.unwrap(); test.run(gba);
} }
}
#[panic_handler] mgba.print(
#[cfg(test)] format_args!("Tests finished successfully"),
fn panic_implementation(info: &core::panic::PanicInfo) -> ! { mgba::DebugLevel::Info,
if let Some(mut mgba) = mgba::Mgba::new() { )
mgba.print(format_args!("[failed]"), mgba::DebugLevel::Error) .unwrap();
.unwrap();
mgba.print(format_args!("Error: {}", info), mgba::DebugLevel::Fatal)
.unwrap();
} }
loop {} #[entry]
} fn agb_test_main(gba: Gba) -> ! {
unsafe { TEST_GBA = Some(gba) };
#[cfg(test)] test_main();
static mut TEST_GBA: Option<Gba> = None; #[allow(clippy::empty_loop)]
loop {}
#[doc(hidden)]
#[cfg(test)]
pub fn test_runner(tests: &[&dyn Testable]) {
let mut mgba = mgba::Mgba::new().unwrap();
mgba.print(
format_args!("Running {} tests", tests.len()),
mgba::DebugLevel::Info,
)
.unwrap();
let gba = unsafe { TEST_GBA.as_mut() }.unwrap();
for test in tests {
test.run(gba);
} }
mgba.print( pub fn assert_image_output(image: &str) {
format_args!("Tests finished successfully"), display::busy_wait_for_vblank();
mgba::DebugLevel::Info, display::busy_wait_for_vblank();
) let mut mgba = crate::mgba::Mgba::new().unwrap();
.unwrap(); mgba.print(
} format_args!("image:{}", image),
crate::mgba::DebugLevel::Info,
#[cfg(test)] )
#[entry] .unwrap();
fn agb_test_main(gba: Gba) -> ! { display::busy_wait_for_vblank();
unsafe { TEST_GBA = Some(gba) }; }
test_main();
#[allow(clippy::empty_loop)]
loop {}
}
#[cfg(test)]
fn assert_image_output(image: &str) {
display::busy_wait_for_vblank();
display::busy_wait_for_vblank();
let mut mgba = crate::mgba::Mgba::new().unwrap();
mgba.print(
format_args!("image:{}", image),
crate::mgba::DebugLevel::Info,
)
.unwrap();
display::busy_wait_for_vblank();
} }
#[cfg(test)] #[cfg(test)]