add what's required for cargo test

This commit is contained in:
Corwin Kuiper 2021-04-10 22:22:56 +01:00 committed by Corwin
parent adfa3b9fde
commit b9de6b5ce5
4 changed files with 93 additions and 5 deletions

View file

@ -1,10 +1,10 @@
[unstable]
build-std = ["core", "compiler_builtins", "alloc"]
build-std = ["core"]
build-std-features = ["compiler-builtins-mem"]
[build]
target = "thumbv4t-none-eabi"
[target.thumbv4t-none-eabi]
runner = "mgba-qt -l 31 -d -C logToStdout=1"
rustflags = ["-Clink-arg=-Tgba.ld"]
runner = "mgba-test-runner"

View file

@ -6,8 +6,6 @@ edition = "2018"
[profile.dev]
opt-level = 2
panic = "abort"
lto = true
[profile.release]
panic = "abort"

View file

@ -1,6 +1,10 @@
#![no_std]
#![no_main]
#![feature(asm)]
#![deny(clippy::all)]
#![feature(custom_test_frameworks)]
#![test_runner(crate::test_runner)]
#![reexport_test_harness_main = "test_main"]
use core::fmt::Write;
pub mod display;
@ -13,6 +17,7 @@ mod single;
pub mod syscall;
#[cfg(not(test))]
#[panic_handler]
#[allow(unused_must_use)]
fn panic_implementation(info: &core::panic::PanicInfo) -> ! {
@ -24,8 +29,12 @@ fn panic_implementation(info: &core::panic::PanicInfo) -> ! {
loop {}
}
#[cfg(not(test))]
static mut GBASINGLE: single::Singleton<Gba> = single::Singleton::new(unsafe { Gba::single_new() });
#[cfg(test)]
static mut GBASINGLE: single::Singleton<Gba> = single::Singleton::empty();
pub struct Gba {
pub display: display::Display,
}
@ -47,3 +56,77 @@ impl Default for Gba {
Self::new()
}
}
pub trait Testable {
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,
);
self(gba);
mgba.print(format_args!("[ok]"), mgba::DebugLevel::Info);
}
}
#[panic_handler]
#[cfg(test)]
fn panic_implementation(info: &core::panic::PanicInfo) -> ! {
if let Some(mut mgba) = mgba::Mgba::new() {
mgba.print(format_args!("[failed]"), mgba::DebugLevel::Error);
mgba.print(format_args!("Error: {}", info), mgba::DebugLevel::Fatal);
}
loop {}
}
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,
);
let mut gba = unsafe { Gba::single_new() };
for test in tests {
test.run(&mut gba);
}
mgba.print(
format_args!("Tests finished successfully"),
mgba::DebugLevel::Info,
);
}
#[no_mangle]
#[cfg(test)]
pub extern "C" fn main() -> ! {
test_main();
loop {}
}
#[test_case]
fn trivial_test(_gba: &mut Gba) {
assert_eq!(1, 1);
}
#[test_case]
fn wait_30_frames(gba: &mut Gba) {
let vblank = gba.display.vblank.get();
let mut counter = 0;
loop {
if counter > 30 {
break;
}
vblank.wait_for_VBlank();
counter += 1
}
}

View file

@ -6,10 +6,17 @@ impl<T> Singleton<T> {
pub const fn new(s: T) -> Self {
Singleton { single: Some(s) }
}
pub const fn empty() -> Self {
Singleton { single: None }
}
pub fn take(&mut self) -> T {
let g = core::mem::replace(&mut self.single, None);
g.unwrap()
}
pub fn ret(&mut self, ret: T) {
self.single = Some(ret);
}
}
pub struct Single {