From c142db6e23f197274b011b049292aae0313082dc Mon Sep 17 00:00:00 2001 From: "Christopher J. McClellan" Date: Sun, 30 Dec 2018 19:17:58 -0500 Subject: [PATCH 1/3] Add example of writing tests that run on host machine --- examples/test_on_host.rs | 44 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 examples/test_on_host.rs diff --git a/examples/test_on_host.rs b/examples/test_on_host.rs new file mode 100644 index 0000000..bb39de1 --- /dev/null +++ b/examples/test_on_host.rs @@ -0,0 +1,44 @@ +//! Conditionally compiling tests with std and our executable with no_std. +//! +//! Ensure there are no targets specified under `[build]` in `.cargo/config` +//! In order to make this work, we lose the convenience of having a default target that isn't the +//! host. +//! +//! cargo build --example test_on_host --target thumbv7m-none-eabi +//! cargo test --example test_on_host + +#![cfg_attr(test, allow(unused_imports))] + +#![cfg_attr(not(test), no_std)] +#![cfg_attr(not(test), no_main)] + +// pick a panicking behavior +#[cfg(not(test))] +extern crate panic_halt; // you can put a breakpoint on `rust_begin_unwind` to catch panics +// extern crate panic_abort; // requires nightly +// extern crate panic_itm; // logs messages over ITM; requires ITM support +// extern crate panic_semihosting; // logs messages to the host stderr; requires a debugger + +use cortex_m::asm; +use cortex_m_rt::entry; + +#[cfg(not(test))] +#[entry] +fn main() -> ! { + asm::nop(); // To not have main optimize to abort in release mode, remove when you add code + + loop { + // your code goes here + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn foo() { + println!("tests work!"); + assert!(1 == 1); + } +} From 0e2aadf8f279f03a012c909ab1e0e1151838127f Mon Sep 17 00:00:00 2001 From: "Christopher J. McClellan" Date: Sun, 30 Dec 2018 19:55:24 -0500 Subject: [PATCH 2/3] Make sure we can actually test prod code --- examples/test_on_host.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/examples/test_on_host.rs b/examples/test_on_host.rs index bb39de1..b5f386b 100644 --- a/examples/test_on_host.rs +++ b/examples/test_on_host.rs @@ -32,6 +32,10 @@ fn main() -> ! { } } +fn add(a: i32, b: i32) -> i32 { + a + b +} + #[cfg(test)] mod test { use super::*; @@ -39,6 +43,6 @@ mod test { #[test] fn foo() { println!("tests work!"); - assert!(1 == 1); + assert!(2 == add(1,1)); } } From e58549b2ec06111b0037ce6e282c085dd7c4c84d Mon Sep 17 00:00:00 2001 From: "Christopher J. McClellan" Date: Mon, 31 Dec 2018 07:01:16 -0500 Subject: [PATCH 3/3] Add more documentation for testing on host --- examples/test_on_host.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/examples/test_on_host.rs b/examples/test_on_host.rs index b5f386b..1c75ed1 100644 --- a/examples/test_on_host.rs +++ b/examples/test_on_host.rs @@ -1,5 +1,14 @@ //! Conditionally compiling tests with std and our executable with no_std. //! +//! Rust's built in unit testing framework requires the standard library, +//! but we need to build our final executable with no_std. +//! The testing framework also generates a `main` method, so we need to only use the `#[entry]` +//! annotation when building our final image. +//! For more information on why this example works, see this excellent blog post. +//! https://os.phil-opp.com/unit-testing/ +//! +//! Running this example: +//! //! Ensure there are no targets specified under `[build]` in `.cargo/config` //! In order to make this work, we lose the convenience of having a default target that isn't the //! host.