mirror of
https://github.com/italicsjenga/agb.git
synced 2025-01-11 17:41:33 +11:00
Merge pull request #246 from gwilymk/add-ability-for-subcrates-to-test
Make it possible to run tests in target crates (and add a basic tests in hat-wizard)
This commit is contained in:
commit
97c4115973
|
@ -76,6 +76,7 @@ pub fn entry(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||||
);
|
);
|
||||||
|
|
||||||
quote!(
|
quote!(
|
||||||
|
#[cfg(not(test))]
|
||||||
#[export_name = "main"]
|
#[export_name = "main"]
|
||||||
#(#attrs)*
|
#(#attrs)*
|
||||||
pub fn #fn_name() -> ! {
|
pub fn #fn_name() -> ! {
|
||||||
|
@ -83,6 +84,19 @@ pub fn entry(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||||
|
|
||||||
#(#stmts)*
|
#(#stmts)*
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[export_name = "main"]
|
||||||
|
#(#attrs)*
|
||||||
|
pub fn #fn_name() -> ! {
|
||||||
|
let mut #argument_name = unsafe { #argument_type ::new_in_entry() };
|
||||||
|
|
||||||
|
if cfg!(test) {
|
||||||
|
agb::test_runner::agb_start_tests(#argument_name, test_main);
|
||||||
|
} else {
|
||||||
|
#(#stmts)*
|
||||||
|
}
|
||||||
|
}
|
||||||
)
|
)
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ debug = true
|
||||||
default = []
|
default = []
|
||||||
freq18157 = ["agb_sound_converter/freq18157"]
|
freq18157 = ["agb_sound_converter/freq18157"]
|
||||||
freq32768 = ["agb_sound_converter/freq32768"]
|
freq32768 = ["agb_sound_converter/freq32768"]
|
||||||
|
testing = []
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bitflags = "1"
|
bitflags = "1"
|
||||||
|
|
|
@ -58,7 +58,8 @@ impl BlockAllocator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[doc(hidden)]
|
||||||
|
#[cfg(any(test, feature = "testing"))]
|
||||||
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();
|
||||||
|
|
|
@ -42,7 +42,7 @@ static GLOBAL_ALLOC: BlockAllocator = unsafe {
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(any(test, feature = "testing"))]
|
||||||
pub unsafe fn number_of_blocks() -> u32 {
|
pub unsafe fn number_of_blocks() -> u32 {
|
||||||
GLOBAL_ALLOC.number_of_blocks()
|
GLOBAL_ALLOC.number_of_blocks()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,15 @@
|
||||||
#![no_std]
|
#![no_std]
|
||||||
// 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(any(test, feature = "testing"), no_main)]
|
||||||
#![cfg_attr(test, feature(custom_test_frameworks))]
|
#![cfg_attr(any(test, feature = "testing"), feature(custom_test_frameworks))]
|
||||||
#![cfg_attr(test, test_runner(crate::test_runner::test_runner))]
|
#![cfg_attr(
|
||||||
#![cfg_attr(test, reexport_test_harness_main = "test_main")]
|
any(test, feature = "testing"),
|
||||||
|
test_runner(crate::test_runner::test_runner)
|
||||||
|
)]
|
||||||
|
#![cfg_attr(
|
||||||
|
any(test, feature = "testing"),
|
||||||
|
reexport_test_harness_main = "test_main"
|
||||||
|
)]
|
||||||
#![feature(alloc_error_handler)]
|
#![feature(alloc_error_handler)]
|
||||||
#![warn(clippy::all)]
|
#![warn(clippy::all)]
|
||||||
#![deny(clippy::must_use_candidate)]
|
#![deny(clippy::must_use_candidate)]
|
||||||
|
@ -183,7 +189,7 @@ pub mod syscall;
|
||||||
/// Interactions with the internal timers
|
/// Interactions with the internal timers
|
||||||
pub mod timer;
|
pub mod timer;
|
||||||
|
|
||||||
#[cfg(not(test))]
|
#[cfg(not(any(test, feature = "testing")))]
|
||||||
#[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) -> ! {
|
||||||
|
@ -249,8 +255,37 @@ impl Gba {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(any(test, feature = "testing"))]
|
||||||
mod test_runner {
|
/// *Unstable* support for running tests using `agb`
|
||||||
|
///
|
||||||
|
/// In order to use this, you need to enable the unstable `custom_test_framework` feature and copy-paste
|
||||||
|
/// the following into the top of your application:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![cfg_attr(test, feature(custom_test_frameworks))]
|
||||||
|
/// #![cfg_attr(test, reexport_test_harness_main = "test_main")]
|
||||||
|
/// #![cfg_attr(test, test_runner(agb::test_runner::test_runner))]
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// And ensure you add agb with the `testing` feature to your `dev-dependencies`
|
||||||
|
/// ```toml
|
||||||
|
/// [dev-dependencies]
|
||||||
|
/// agb = { version = "<same as in dependencies>", features = ["testing"] }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// With this support, you will be able to write tests which you can run using `mgba-test-runner`.
|
||||||
|
/// Tests are written using `#[test_case]` rather than `#[test]`.
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #[test_case]
|
||||||
|
/// fn test_ping_pong(_gba: &mut Gba) {
|
||||||
|
/// assert_eq!(1, 1);
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// You can run the tests using `cargo test`, but it will work better through `mgba-test-runner` by
|
||||||
|
/// running something along the lines of `CARGO_TARGET_THUMBV4T_NONE_EABI_RUNNER=mgba-test-runner cargo test`.
|
||||||
|
pub mod test_runner {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
|
@ -320,8 +355,22 @@ mod test_runner {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// needed to fudge the #[entry] below
|
||||||
|
mod agb {
|
||||||
|
pub mod test_runner {
|
||||||
|
pub use super::super::agb_start_tests;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
#[entry]
|
#[entry]
|
||||||
fn agb_test_main(gba: Gba) -> ! {
|
fn agb_test_main(gba: Gba) -> ! {
|
||||||
|
#[allow(clippy::empty_loop)]
|
||||||
|
loop {} // full implementation provided by the #[entry]
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub fn agb_start_tests(gba: Gba, test_main: impl Fn()) -> ! {
|
||||||
unsafe { TEST_GBA = Some(gba) };
|
unsafe { TEST_GBA = Some(gba) };
|
||||||
test_main();
|
test_main();
|
||||||
#[allow(clippy::empty_loop)]
|
#[allow(clippy::empty_loop)]
|
||||||
|
|
|
@ -9,6 +9,9 @@ edition = "2018"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
agb = { version = "0.9.2", path = "../../agb" }
|
agb = { version = "0.9.2", path = "../../agb" }
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
agb = { version = "0.9.2", path = "../../agb", features = ["testing"] }
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
|
#![cfg_attr(test, feature(custom_test_frameworks))]
|
||||||
|
#![cfg_attr(test, reexport_test_harness_main = "test_main")]
|
||||||
|
#![cfg_attr(test, test_runner(agb::test_runner::test_runner))]
|
||||||
|
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
|
|
||||||
|
@ -776,7 +779,11 @@ impl<'a, 'b> PlayingLevel<'a, 'b> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[agb::entry]
|
#[agb::entry]
|
||||||
fn main(mut agb: agb::Gba) -> ! {
|
fn agb_main(mut gba: agb::Gba) -> ! {
|
||||||
|
main(gba);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn main(mut agb: agb::Gba) -> ! {
|
||||||
let (tiled, mut vram) = agb.display.video.tiled0();
|
let (tiled, mut vram) = agb.display.video.tiled0();
|
||||||
vram.set_background_palettes(tile_sheet::background.palettes);
|
vram.set_background_palettes(tile_sheet::background.palettes);
|
||||||
let mut splash_screen = tiled.background(Priority::P0, RegularBackgroundSize::Background32x32);
|
let mut splash_screen = tiled.background(Priority::P0, RegularBackgroundSize::Background32x32);
|
||||||
|
@ -958,3 +965,32 @@ fn main(mut agb: agb::Gba) -> ! {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use agb::Gba;
|
||||||
|
|
||||||
|
#[test_case]
|
||||||
|
fn test_ping_pong(_gba: &mut Gba) {
|
||||||
|
let test_cases = [
|
||||||
|
[0, 2, 0],
|
||||||
|
[0, 7, 0],
|
||||||
|
[1, 2, 1],
|
||||||
|
[2, 2, 0],
|
||||||
|
[3, 2, 1],
|
||||||
|
[4, 2, 0],
|
||||||
|
];
|
||||||
|
|
||||||
|
for test_case in test_cases {
|
||||||
|
assert_eq!(
|
||||||
|
ping_pong(test_case[0], test_case[1]),
|
||||||
|
test_case[2],
|
||||||
|
"Expected ping_pong({}, {}) to equal {}",
|
||||||
|
test_case[0],
|
||||||
|
test_case[1],
|
||||||
|
test_case[2],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,22 +1,26 @@
|
||||||
#!/bin/bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
MGBA_VERSION=$1
|
MGBA_VERSION=$1
|
||||||
OUT_DIRECTORY=$2
|
OUT_DIRECTORY=$2
|
||||||
CURRENT_DIRECTORY=$(pwd)
|
CURRENT_DIRECTORY=$(pwd)
|
||||||
|
|
||||||
cd ${OUT_DIRECTORY}
|
cd "${OUT_DIRECTORY}" || exit
|
||||||
|
|
||||||
|
if [[ ! -f "mgba-${MGBA_VERSION}.tar.gz" ]]; then
|
||||||
|
curl -L "https://github.com/mgba-emu/mgba/archive/refs/tags/${MGBA_VERSION}.tar.gz" -o "mgba-${MGBA_VERSION}.tar.gz"
|
||||||
|
fi
|
||||||
|
|
||||||
if [[ -f libmgba-cycle.a ]]; then
|
if [[ -f libmgba-cycle.a ]]; then
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
curl -L https://github.com/mgba-emu/mgba/archive/refs/tags/${MGBA_VERSION}.tar.gz -o mgba-${MGBA_VERSION}.tar.gz
|
curl -L "https://github.com/mgba-emu/mgba/archive/refs/tags/${MGBA_VERSION}.tar.gz" -o "mgba-${MGBA_VERSION}.tar.gz"
|
||||||
tar -xvf mgba-${MGBA_VERSION}.tar.gz
|
tar -xvf "mgba-${MGBA_VERSION}.tar.gz"
|
||||||
cd mgba-${MGBA_VERSION}
|
cd "mgba-${MGBA_VERSION}" || exit
|
||||||
rm -rf build
|
rm -rf build
|
||||||
patch --strip=1 < ${CURRENT_DIRECTORY}/add_cycles_register.patch
|
patch --strip=1 < "${CURRENT_DIRECTORY}/add_cycles_register.patch"
|
||||||
mkdir -p build
|
mkdir -p build
|
||||||
cd build
|
cd build || exit
|
||||||
cmake .. \
|
cmake .. \
|
||||||
-DBUILD_STATIC=ON \
|
-DBUILD_STATIC=ON \
|
||||||
-DBUILD_SHARED=OFF \
|
-DBUILD_SHARED=OFF \
|
||||||
|
|
|
@ -59,7 +59,7 @@ for PROJECT_TOML_FILE in agb/Cargo.toml agb-*/Cargo.toml; do
|
||||||
# also update the agb version in the template and the examples
|
# also update the agb version in the template and the examples
|
||||||
sed -i -e "s/^agb = \".*\"/agb = \"$VERSION\"/" template/Cargo.toml
|
sed -i -e "s/^agb = \".*\"/agb = \"$VERSION\"/" template/Cargo.toml
|
||||||
|
|
||||||
for EXAMPLE_TOML_FILE in examples/*/Cargo.toml book/games/*/Cargo.toml; do
|
for EXAMPLE_TOML_FILE in examples/*/Cargo.toml book/games/*/Cargo.toml template/Cargo.toml; do
|
||||||
EXAMPLE_DIR=$(dirname "$EXAMPLE_TOML_FILE")
|
EXAMPLE_DIR=$(dirname "$EXAMPLE_TOML_FILE")
|
||||||
sed -E -i -e "/agb =/ s/version = \"[^\"]+\"/version = \"$VERSION\"/" "$EXAMPLE_DIR/Cargo.toml"
|
sed -E -i -e "/agb =/ s/version = \"[^\"]+\"/version = \"$VERSION\"/" "$EXAMPLE_DIR/Cargo.toml"
|
||||||
(cd "$EXAMPLE_DIR" && cargo update)
|
(cd "$EXAMPLE_DIR" && cargo update)
|
||||||
|
|
|
@ -9,6 +9,9 @@ edition = "2018"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
agb = "0.9.2"
|
agb = "0.9.2"
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
agb = { version = "0.9.2", features = ["testing"] }
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
panic = "abort"
|
panic = "abort"
|
||||||
lto = true
|
lto = true
|
|
@ -9,6 +9,10 @@
|
||||||
// using the #[agb::entry] proc macro. Failing to do so will cause failure in linking
|
// using the #[agb::entry] proc macro. Failing to do so will cause failure in linking
|
||||||
// which won't be a particularly clear error message.
|
// which won't be a particularly clear error message.
|
||||||
#![no_main]
|
#![no_main]
|
||||||
|
// This is required to allow writing tests
|
||||||
|
#![cfg_attr(test, feature(custom_test_frameworks))]
|
||||||
|
#![cfg_attr(test, reexport_test_harness_main = "test_main")]
|
||||||
|
#![cfg_attr(test, test_runner(agb::test_runner::test_runner))]
|
||||||
|
|
||||||
use agb::{display, syscall};
|
use agb::{display, syscall};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue