Closed dbrgn closed 5 years ago
@dbrgn awesome! We were actually just talking about this in the wg. I'll take a more detailed look later!
CC @japaric and @jcsoo
What I noticed when trying to write a few tests is that it's not possible to reconfigure the mock if you pass it into a driver by-value.
This probably ties into https://github.com/japaric/embedded-hal/issues/35
Right now I'm simply creating a new driver instance every time I want to change the return value:
https://github.com/dbrgn/sgp30-rs/blob/0b8d54fd34bbee2ac79258982b3bfb61c919ec6b/src/lib.rs#L180-L202
@dbrgn - generally whenever I worked with this in C, I would have some kind of global that would handle this, or provide access. I haven't tried to tackle this in Rust before.
A couple ideas I have off the top of my head:
@jamesmunns I was thinking of using channels for the shared driver problem discussed in japaric/embedded-hal#35, but AFAIK there's nothing like this available in #[no_std]
at the moment?
@therealprof Can you just extern crate std;
in the test mod? Or maybe #cfg[test] extern crate std;
?
I'll try to make a test example
This is a tiny impl, I'm going to take it further to try out what a mock impl would look like:
➜ nostdtest git:(master) ✗ cat src/lib.rs
#![no_std]
#![allow(unused_variables, dead_code)]
fn foo() -> () {
()
}
#[cfg(test)]
mod tests {
extern crate std;
#[test]
fn it_works() {
use tests::std::vec::Vec;
let x: Vec<u8> = Vec::new();
assert_eq!(2 + 2, 4);
}
}
➜ nostdtest git:(master) ✗ cargo check
Compiling nostdtest v0.1.0 (file:///home/james/personal/nostdtest)
Finished dev [unoptimized + debuginfo] target(s) in 0.10 secs
➜ nostdtest git:(master) ✗ cargo test
Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs
Running target/debug/deps/nostdtest-f266c74e06fc6874
running 1 test
test tests::it_works ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
Doc-tests nostdtest
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
➜ nostdtest git:(master) ✗ xargo check --target thumbv6m-none-eabi
Compiling nostdtest v0.1.0 (file:///home/james/personal/nostdtest)
Finished dev [unoptimized + debuginfo] target(s) in 0.10 secs
@jamesmunns Well, my question was related to using channels on #[no_std]
drivers so the answer is: no, I can't.
Hey @therealprof, sorry, what I was trying to illustrate was that the channels would only be used by the test and embedded-hal-mock
, but not in the underlying driver crate you are trying to develop/test. I'll get back to you later today with an experiment of what I meant, and if that was not helpful (or not what you had in mind, or doesn't actually work), then thats okay :)
@jamesmunns I just had a glimpse of hope that someone had an idea that would help to solve one of the most limiting problems we face on embedded rust today. If that's not you, that's okay. ;)
My intent was definitely to facilitate testing of drivers, so while channels are a great idea that probably won't work with no_std...
Your mock doesn't need to be no_std
, you can definitely use standard library channels inside mock implementations of the embedded-hal
traits and pass those into no_std
drivers.
@Nemo157 ah of course, you are right! :+1:
I did something nasty:
Rc<RefCell<X>>
I wrote a "simulator" of my SX1278 chip (I called it mock, but it simulates the SPI traffic)https://github.com/susu/sx1278/blob/master/tests/test_radio_settings.rs
Because it is a simulator, it is not really reusable. Maybe you can use the "pattern".
Hey @dbrgn, do you feel that this issue should stay open? Or would discussions on this topic be better suited to live in the embedded-hal-mock space?
I think embedded-hal-mock
has developed quite nicely and has already received a few contributions. I think this can be closed.
What's the best way to test embedded-hal drivers without actual hardware access?
I think a "mocked" implementation of the embedded-hal traits would be very useful. I started with I2C and Delay:
https://github.com/dbrgn/embedded-hal-mock
The goal is to provide functions to mock certain outcomes:
Currently I only provide implementations for I2C and a no-op implementation of the
Delay
trait.Is this a good approach? If yes, contributions are welcome. (I'm also open to moving the crate/repo to another organization where more people can contribute.)