aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndres O. Vela <[email protected]>2023-10-29 19:49:52 +0100
committerAndres O. Vela <[email protected]>2023-10-29 19:49:52 +0100
commit0d6094c8b10da141d048ec23133df4525befbd44 (patch)
tree83c9c80134717e03f89091eed0417694766e7b6c
parentb6fc682117a41e8e63a9632e06da5a17f46d9ab0 (diff)
time: add MockDriver for testing purposes
-rw-r--r--embassy-time/Cargo.toml3
-rw-r--r--embassy-time/src/driver_mock.rs73
-rw-r--r--embassy-time/src/lib.rs6
3 files changed, 82 insertions, 0 deletions
diff --git a/embassy-time/Cargo.toml b/embassy-time/Cargo.toml
index 62404863d..8b5d31ee1 100644
--- a/embassy-time/Cargo.toml
+++ b/embassy-time/Cargo.toml
@@ -59,6 +59,9 @@ generic-queue-32 = ["generic-queue"]
59generic-queue-64 = ["generic-queue"] 59generic-queue-64 = ["generic-queue"]
60generic-queue-128 = ["generic-queue"] 60generic-queue-128 = ["generic-queue"]
61 61
62# Create a `MockDriver` that can be manually advanced for testing purposes.
63mock-driver = ["tick-hz-1_000_000"]
64
62# Set the `embassy_time` tick rate. 65# Set the `embassy_time` tick rate.
63# 66#
64# At most 1 `tick-*` feature can be enabled. If none is enabled, a default of 1MHz is used. 67# At most 1 `tick-*` feature can be enabled. If none is enabled, a default of 1MHz is used.
diff --git a/embassy-time/src/driver_mock.rs b/embassy-time/src/driver_mock.rs
new file mode 100644
index 000000000..4ae5a2d96
--- /dev/null
+++ b/embassy-time/src/driver_mock.rs
@@ -0,0 +1,73 @@
1use core::cell::Cell;
2
3use critical_section::Mutex as CsMutex;
4
5use crate::driver::{AlarmHandle, Driver};
6use crate::{Duration, Instant};
7
8/// A mock driver that can be manually advanced.
9/// This is useful for testing code that works with [`Instant`] and [`Duration`].
10///
11/// This driver cannot currently be used to test runtime functionality, such as
12/// timers, delays, etc.
13///
14/// # Example
15///
16/// ```ignore
17/// fn has_a_second_passed(reference: Instant) -> bool {
18/// Instant::now().duration_since(reference) > Duration::from_secs(1)
19/// }
20///
21/// fn test_second_passed() {
22/// let driver = embassy_time::MockDriver::get();
23/// let reference = Instant::now();
24/// assert_eq!(false, has_a_second_passed(reference));
25/// driver.advance(Duration::from_secs(1));
26/// assert_eq!(true, has_a_second_passed(reference));
27/// }
28/// ```
29pub struct MockDriver {
30 now: CsMutex<Cell<Instant>>,
31}
32
33crate::time_driver_impl!(static DRIVER: MockDriver = MockDriver {
34 now: CsMutex::new(Cell::new(Instant::from_ticks(0))),
35});
36
37impl MockDriver {
38 /// Gets a reference to the global mock driver.
39 pub fn get() -> &'static MockDriver {
40 &DRIVER
41 }
42
43 /// Sets the current time of the mock driver.
44 pub fn set_current_time(&self, now: Instant) {
45 critical_section::with(|cs| self.now.borrow(cs).set(now))
46 }
47
48 /// Advances the time by the specified [`Duration`].
49 pub fn advance(&self, duration: Duration) {
50 critical_section::with(|cs| {
51 let now = self.now.borrow(cs).get().as_ticks();
52 self.now.borrow(cs).set(Instant::from_ticks(now + duration.as_ticks()));
53 });
54 }
55}
56
57impl Driver for MockDriver {
58 fn now(&self) -> u64 {
59 critical_section::with(|cs| self.now.borrow(cs).get().as_micros() as u64)
60 }
61
62 unsafe fn allocate_alarm(&self) -> Option<AlarmHandle> {
63 unimplemented!("MockDriver does not support runtime features that require an executor");
64 }
65
66 fn set_alarm_callback(&self, _alarm: AlarmHandle, _callback: fn(*mut ()), _ctx: *mut ()) {
67 unimplemented!("MockDriver does not support runtime features that require an executor");
68 }
69
70 fn set_alarm(&self, _alarm: AlarmHandle, _timestamp: u64) -> bool {
71 unimplemented!("MockDriver does not support runtime features that require an executor");
72 }
73}
diff --git a/embassy-time/src/lib.rs b/embassy-time/src/lib.rs
index 8f57eabcb..45c1e882b 100644
--- a/embassy-time/src/lib.rs
+++ b/embassy-time/src/lib.rs
@@ -15,6 +15,12 @@ pub mod queue;
15mod tick; 15mod tick;
16mod timer; 16mod timer;
17 17
18#[cfg(feature = "mock-driver")]
19mod driver_mock;
20
21#[cfg(feature = "mock-driver")]
22pub use driver_mock::MockDriver;
23
18#[cfg(feature = "std")] 24#[cfg(feature = "std")]
19mod driver_std; 25mod driver_std;
20#[cfg(feature = "wasm")] 26#[cfg(feature = "wasm")]