Rahix / avr-hal-template

cargo-generate template for avr-hal projects
Apache License 2.0
130 stars 28 forks source link

HOWTO: cargo test #28

Closed cdaringe closed 5 months ago

cdaringe commented 8 months ago

problem

I want to author unit tests, but doing so with no_std seems to introduce some problemos.

discussion

I read that #![cfg_attr(not(test), no_std)] may be a winning ticket to get std in test config, which makes sense.

However, you start to encounter some other (surely surmountable issues), e.g.

error[E0152]: duplicate lang item in crate `core` (which `rustc_std_workspace_core` depends on): `sized`.
  |
  = note: the lang item is first defined in crate `core` (which `void` depends on)
  = note: first definition in `core` loaded from /Users/cdaringe/src/nano-turret/target/avr-atmega328p/debug/deps/libcore-cb83c61aa17b09d5.rmeta
  = note: second definition in `core` loaded from /Users/cdaringe/src/nano-turret/target/avr-atmega328p/debug/deps/libcore-bf1da146ad2692e6.rmeta

Would be killer if the template was cargo test ready!

Rahix commented 8 months ago

Hm, do you intend to write unit tests that run on your host system (= the development machine) or on the target system (the AVR microcontroller)?

cdaringe commented 8 months ago

Host system, CI, etc.

Rahix commented 8 months ago

The problem is that you are using the cargo configuration for AVR and that of course does not build something you can run on your host system (without an AVR simulator). The config is in .cargo/config.toml.

The cleanest solution to this problem is, in my eyes, to split your application into a library crate which contains everything that's platform independent and a firmware crate which pulls in the library crate and "connects" it to the actual hardware peripherals. Your unit tests are then just a part of the library crate.

cdaringe commented 8 months ago

right. i'm still a noob. .cargo/config.toml applies to the whole project, but i was hoping that, if theres not a great way to do this all intra crate, that perhaps i'd at least be able to do it in a workspace? any ideas on how to make that work? sorry if you think it's outta scope for the template. i dunno--testing seems important enough to include in the recipe imho!

Rahix commented 8 months ago

Unfortunately, you've just discovered a big limitation of how cargo works at the moment. You can't do this well in a workspace either. The best bet you have is structuring your project like this:

+-my-avr-project/
  +-project-lib/
  | +-src/
  | | +-lib.rs
  | +-tests/
  | +-Cargo.toml
  +-project-firmware/
    +-.cargo/
    | +-config.toml
    +-src/
    | +-main.rs
    +-Cargo.toml       # has a dependency `project-lib = {path = "../project-lib/"}`

Then you have to cd into project-lib/ to run cargo test and into project-firmware/ for cargo run. I know this isn't particularly nice :(


sorry if you think it's outta scope for the template. i dunno--testing seems important enough to include in the recipe imho!

If it wasn't this unwieldy to implement, I'd gladly make the template support it. But as it stands, I think the additional complexity is not worth it...

In general, writing tests for embedded projects is a particularly difficult topic because you quickly hit limitations of what you can test outside of the real hardware environment. In practice (if tests are implemented at all), you'd build a sort of second firmware which just runs a number of tests on the hardware and then reports results e.g. over serial console.