mirror of
https://github.com/italicsjenga/agb.git
synced 2024-12-24 00:31:34 +11:00
add what's required for cargo test
This commit is contained in:
parent
adfa3b9fde
commit
b9de6b5ce5
|
@ -1,10 +1,10 @@
|
||||||
[unstable]
|
[unstable]
|
||||||
build-std = ["core", "compiler_builtins", "alloc"]
|
build-std = ["core"]
|
||||||
build-std-features = ["compiler-builtins-mem"]
|
build-std-features = ["compiler-builtins-mem"]
|
||||||
|
|
||||||
[build]
|
[build]
|
||||||
target = "thumbv4t-none-eabi"
|
target = "thumbv4t-none-eabi"
|
||||||
|
|
||||||
[target.thumbv4t-none-eabi]
|
[target.thumbv4t-none-eabi]
|
||||||
runner = "mgba-qt -l 31 -d -C logToStdout=1"
|
|
||||||
rustflags = ["-Clink-arg=-Tgba.ld"]
|
rustflags = ["-Clink-arg=-Tgba.ld"]
|
||||||
|
runner = "mgba-test-runner"
|
|
@ -6,8 +6,6 @@ edition = "2018"
|
||||||
|
|
||||||
[profile.dev]
|
[profile.dev]
|
||||||
opt-level = 2
|
opt-level = 2
|
||||||
panic = "abort"
|
|
||||||
lto = true
|
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
panic = "abort"
|
panic = "abort"
|
||||||
|
|
83
src/lib.rs
83
src/lib.rs
|
@ -1,6 +1,10 @@
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
#![feature(asm)]
|
#![feature(asm)]
|
||||||
#![deny(clippy::all)]
|
#![deny(clippy::all)]
|
||||||
|
#![feature(custom_test_frameworks)]
|
||||||
|
#![test_runner(crate::test_runner)]
|
||||||
|
#![reexport_test_harness_main = "test_main"]
|
||||||
|
|
||||||
use core::fmt::Write;
|
use core::fmt::Write;
|
||||||
pub mod display;
|
pub mod display;
|
||||||
|
@ -13,6 +17,7 @@ mod single;
|
||||||
|
|
||||||
pub mod syscall;
|
pub mod syscall;
|
||||||
|
|
||||||
|
#[cfg(not(test))]
|
||||||
#[panic_handler]
|
#[panic_handler]
|
||||||
#[allow(unused_must_use)]
|
#[allow(unused_must_use)]
|
||||||
fn panic_implementation(info: &core::panic::PanicInfo) -> ! {
|
fn panic_implementation(info: &core::panic::PanicInfo) -> ! {
|
||||||
|
@ -24,8 +29,12 @@ fn panic_implementation(info: &core::panic::PanicInfo) -> ! {
|
||||||
loop {}
|
loop {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(test))]
|
||||||
static mut GBASINGLE: single::Singleton<Gba> = single::Singleton::new(unsafe { Gba::single_new() });
|
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 struct Gba {
|
||||||
pub display: display::Display,
|
pub display: display::Display,
|
||||||
}
|
}
|
||||||
|
@ -47,3 +56,77 @@ impl Default for Gba {
|
||||||
Self::new()
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -6,10 +6,17 @@ impl<T> Singleton<T> {
|
||||||
pub const fn new(s: T) -> Self {
|
pub const fn new(s: T) -> Self {
|
||||||
Singleton { single: Some(s) }
|
Singleton { single: Some(s) }
|
||||||
}
|
}
|
||||||
|
pub const fn empty() -> Self {
|
||||||
|
Singleton { single: None }
|
||||||
|
}
|
||||||
pub fn take(&mut self) -> T {
|
pub fn take(&mut self) -> T {
|
||||||
let g = core::mem::replace(&mut self.single, None);
|
let g = core::mem::replace(&mut self.single, None);
|
||||||
g.unwrap()
|
g.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn ret(&mut self, ret: T) {
|
||||||
|
self.single = Some(ret);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Single {
|
pub struct Single {
|
||||||
|
|
Loading…
Reference in a new issue