diff --git a/Cargo.lock b/Cargo.lock index 66f1968..5626108 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -99,6 +99,7 @@ dependencies = [ "env_logger", "log", "object", + "rstest", "tempfile", ] @@ -164,6 +165,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "pest" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53" +dependencies = [ + "ucd-trie", +] + [[package]] name = "ppv-lite86" version = "0.2.10" @@ -196,6 +206,24 @@ dependencies = [ "treeline", ] +[[package]] +name = "proc-macro2" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0d8caf72986c1a598726adc988bb5984792ef84f5ee5aa50209145ee8077038" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quote" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" +dependencies = [ + "proc-macro2", +] + [[package]] name = "rand" version = "0.8.3" @@ -277,6 +305,57 @@ dependencies = [ "winapi", ] +[[package]] +name = "rstest" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "041bb0202c14f6a158bbbf086afb03d0c6e975c2dec7d4912f8061ed44f290af" +dependencies = [ + "cfg-if", + "proc-macro2", + "quote", + "rustc_version", + "syn", +] + +[[package]] +name = "rustc_version" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" +dependencies = [ + "semver", +] + +[[package]] +name = "semver" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver-parser" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7" +dependencies = [ + "pest", +] + +[[package]] +name = "syn" +version = "1.0.73" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f71489ff30030d2ae598524f61326b902466f72a0fb1a8564c001cc63425bcc7" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + [[package]] name = "tempfile" version = "3.2.0" @@ -306,6 +385,18 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7f741b240f1a48843f9b8e0444fb55fb2a4ff67293b50a9179dfd5ea67f8d41" +[[package]] +name = "ucd-trie" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c" + +[[package]] +name = "unicode-xid" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" + [[package]] name = "wait-timeout" version = "0.2.0" diff --git a/Cargo.toml b/Cargo.toml index 76bfc30..06d4e0c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,6 +19,7 @@ tempfile = "3.2" [dev-dependencies] assert_cmd = "1.0" +rstest = "0.10" [workspace] members = [".", "xtest"] diff --git a/test-flip-link-app/.empty.x b/test-flip-link-app/.empty.x new file mode 100644 index 0000000..e69de29 diff --git a/test-flip-link-app/.memory.x b/test-flip-link-app/.memory.x new file mode 100644 index 0000000..475726c --- /dev/null +++ b/test-flip-link-app/.memory.x @@ -0,0 +1,7 @@ +MEMORY +{ + FLASH : ORIGIN = 0x00000000, LENGTH = 256K + RAM : ORIGIN = 0x20000000, LENGTH = 64K +} + +INCLUDE empty.x diff --git a/test-flip-link-app/Cargo.toml b/test-flip-link-app/Cargo.toml index 268a3bb..fd45ac2 100644 --- a/test-flip-link-app/Cargo.toml +++ b/test-flip-link-app/Cargo.toml @@ -9,7 +9,15 @@ version = "0.1.0" cortex-m = "0.7" cortex-m-rt = "0.6" cortex-m-semihosting = "0.3" -lm3s6965 = "0.1" panic-semihosting = { version = "0.5", features = ["exit"] } +# optional +lm3s6965 = { version = "0.1", optional = true } + +[build-dependencies] +anyhow = "1.0" + +[features] +default = ["lm3s6965"] + [workspace] # needed to exclude package from parent workspace diff --git a/test-flip-link-app/build.rs b/test-flip-link-app/build.rs new file mode 100644 index 0000000..5185077 --- /dev/null +++ b/test-flip-link-app/build.rs @@ -0,0 +1,19 @@ +fn main() -> anyhow::Result<()> { + // include following if hal is excluded (aka. default features are disabled) + #[cfg(not(feature = "lm3s6965"))] + { + use std::{env, fs::File, io::Write, path::PathBuf}; + + let out = PathBuf::from(env::var_os("OUT_DIR").expect("`OUT_DIR` is not set")); + + File::create(out.join("memory.x"))?.write_all(include_bytes!(".memory.x"))?; + File::create(out.join("empty.x"))?.write_all(include_bytes!(".empty.x"))?; + + println!("cargo:rustc-link-search={}", out.display()); + println!("cargo:rerun-if-changed=.memory.x"); + println!("cargo:rerun-if-changed=.empty.x"); + println!("cargo:rerun-if-changed=build.rs"); + } + + Ok(()) +} diff --git a/test-flip-link-app/examples/crash.rs b/test-flip-link-app/examples/crash.rs index 71976c5..36b84bf 100644 --- a/test-flip-link-app/examples/crash.rs +++ b/test-flip-link-app/examples/crash.rs @@ -4,6 +4,7 @@ use core::ptr; use cortex_m_rt::entry; +#[cfg(feature = "lm3s6965")] use lm3s6965 as _; use panic_semihosting as _; diff --git a/test-flip-link-app/examples/exception.rs b/test-flip-link-app/examples/exception.rs index e3c2dc5..fd3f590 100644 --- a/test-flip-link-app/examples/exception.rs +++ b/test-flip-link-app/examples/exception.rs @@ -5,6 +5,7 @@ use cortex_m::{peripheral::syst::SystClkSource, Peripherals}; use cortex_m_rt::{entry, exception}; use cortex_m_semihosting::hprint; +#[cfg(feature = "lm3s6965")] use lm3s6965 as _; use panic_semihosting as _; diff --git a/test-flip-link-app/examples/hello.rs b/test-flip-link-app/examples/hello.rs index dc5df4c..0cfef71 100644 --- a/test-flip-link-app/examples/hello.rs +++ b/test-flip-link-app/examples/hello.rs @@ -3,6 +3,7 @@ use cortex_m_rt::entry; use cortex_m_semihosting::{debug, hprintln}; +#[cfg(feature = "lm3s6965")] use lm3s6965 as _; use panic_semihosting as _; diff --git a/test-flip-link-app/examples/panic.rs b/test-flip-link-app/examples/panic.rs index 1c42392..90699dc 100644 --- a/test-flip-link-app/examples/panic.rs +++ b/test-flip-link-app/examples/panic.rs @@ -2,6 +2,7 @@ #![no_std] use cortex_m_rt::entry; +#[cfg(feature = "lm3s6965")] use lm3s6965 as _; use panic_semihosting as _; diff --git a/tests/verify.rs b/tests/verify.rs index d594422..66d1a82 100644 --- a/tests/verify.rs +++ b/tests/verify.rs @@ -1,5 +1,7 @@ use std::fs; +use rstest::rstest; + /// Path to test app const CRATE: &str = "test-flip-link-app"; /// Example firmware in `$CRATE/examples` @@ -7,13 +9,15 @@ const FILES: [&str; 4] = ["crash", "exception", "hello", "panic"]; /// Compilation target firmware is build for const TARGET: &str = "thumbv7m-none-eabi"; -#[test] -fn should_link_example_firmware() -> anyhow::Result<()> { +#[rstest] +#[case::normal(true)] +#[case::custom_linkerscript(false)] +fn should_link_example_firmware(#[case] default_features: bool) -> anyhow::Result<()> { // Arrange cargo::check_flip_link(); // Act - let cmd = cargo::build_example_firmware(CRATE); + let cmd = cargo::build_example_firmware(CRATE, default_features); // Assert cmd.success(); @@ -28,7 +32,7 @@ fn should_verify_memory_layout() -> anyhow::Result<()> { cargo::check_flip_link(); // Act - cargo::build_example_firmware(CRATE).success(); + cargo::build_example_firmware(CRATE, true).success(); // Assert for elf_path in elf::paths() { @@ -58,13 +62,19 @@ mod cargo { /// Build all examples in `$REPO/$rel_path` #[must_use] - pub fn build_example_firmware(rel_path: &str) -> Assert { + pub fn build_example_firmware(rel_path: &str, default_features: bool) -> Assert { // append `rel_path` to the current working directory let mut firmware_dir = std::env::current_dir().unwrap(); firmware_dir.push(rel_path); + // disable default features or use `-v` as a no-op + let default_features = match default_features { + false => "--no-default-features", + true => "-v", + }; + Command::new("cargo") - .args(&["build", "--examples"]) + .args(&["build", "--examples", default_features]) .current_dir(firmware_dir) .unwrap() .assert() diff --git a/xtest/src/main.rs b/xtest/src/main.rs index 139e12c..30552ed 100644 --- a/xtest/src/main.rs +++ b/xtest/src/main.rs @@ -26,7 +26,10 @@ mod cargo { } pub fn test() -> anyhow::Result<()> { - let status = Command::new("cargo").arg("test").status()?; + let status = Command::new("cargo") + // `--test-threads=1` prevents race conditions accessing the elf-file + .args(&["test", "--", "--test-threads=1"]) + .status()?; match status.success() { false => Err(anyhow!("running `cargo test`")), true => Ok(()),