diff options
| author | Dario Nieuwenhuis <[email protected]> | 2023-11-24 21:33:30 +0100 |
|---|---|---|
| committer | Dario Nieuwenhuis <[email protected]> | 2023-11-24 23:52:09 +0100 |
| commit | 1fbc150fd6392d8268aa35d15380c02e363c4eb8 (patch) | |
| tree | 895711da5ee33944f5374c1572a4d60e370a1640 /embassy-executor | |
| parent | 259cf6192b920dff4cce0486488d929bf4e05b96 (diff) | |
executor: add some tests.
Diffstat (limited to 'embassy-executor')
| -rw-r--r-- | embassy-executor/Cargo.toml | 3 | ||||
| -rw-r--r-- | embassy-executor/tests/test.rs | 137 |
2 files changed, 140 insertions, 0 deletions
diff --git a/embassy-executor/Cargo.toml b/embassy-executor/Cargo.toml index 54ea1a548..f0e85a2c8 100644 --- a/embassy-executor/Cargo.toml +++ b/embassy-executor/Cargo.toml | |||
| @@ -68,3 +68,6 @@ cortex-m = { version = "0.7.6", optional = true } | |||
| 68 | # arch-wasm dependencies | 68 | # arch-wasm dependencies |
| 69 | wasm-bindgen = { version = "0.2.82", optional = true } | 69 | wasm-bindgen = { version = "0.2.82", optional = true } |
| 70 | js-sys = { version = "0.3", optional = true } | 70 | js-sys = { version = "0.3", optional = true } |
| 71 | |||
| 72 | [dev-dependencies] | ||
| 73 | critical-section = { version = "1.1", features = ["std"] } | ||
diff --git a/embassy-executor/tests/test.rs b/embassy-executor/tests/test.rs new file mode 100644 index 000000000..0dbd391e8 --- /dev/null +++ b/embassy-executor/tests/test.rs | |||
| @@ -0,0 +1,137 @@ | |||
| 1 | #![cfg_attr(feature = "nightly", feature(type_alias_impl_trait))] | ||
| 2 | |||
| 3 | use std::boxed::Box; | ||
| 4 | use std::future::poll_fn; | ||
| 5 | use std::sync::{Arc, Mutex}; | ||
| 6 | use std::task::Poll; | ||
| 7 | |||
| 8 | use embassy_executor::raw::Executor; | ||
| 9 | use embassy_executor::task; | ||
| 10 | |||
| 11 | #[export_name = "__pender"] | ||
| 12 | fn __pender(context: *mut ()) { | ||
| 13 | unsafe { | ||
| 14 | let trace = &*(context as *const Trace); | ||
| 15 | trace.push("pend"); | ||
| 16 | } | ||
| 17 | } | ||
| 18 | |||
| 19 | #[derive(Clone)] | ||
| 20 | struct Trace { | ||
| 21 | trace: Arc<Mutex<Vec<&'static str>>>, | ||
| 22 | } | ||
| 23 | |||
| 24 | impl Trace { | ||
| 25 | fn new() -> Self { | ||
| 26 | Self { | ||
| 27 | trace: Arc::new(Mutex::new(Vec::new())), | ||
| 28 | } | ||
| 29 | } | ||
| 30 | fn push(&self, value: &'static str) { | ||
| 31 | self.trace.lock().unwrap().push(value) | ||
| 32 | } | ||
| 33 | |||
| 34 | fn get(&self) -> Vec<&'static str> { | ||
| 35 | self.trace.lock().unwrap().clone() | ||
| 36 | } | ||
| 37 | } | ||
| 38 | |||
| 39 | fn setup() -> (&'static Executor, Trace) { | ||
| 40 | let trace = Trace::new(); | ||
| 41 | let context = Box::leak(Box::new(trace.clone())) as *mut _ as *mut (); | ||
| 42 | let executor = &*Box::leak(Box::new(Executor::new(context))); | ||
| 43 | (executor, trace) | ||
| 44 | } | ||
| 45 | |||
| 46 | #[test] | ||
| 47 | fn executor_noop() { | ||
| 48 | let (executor, trace) = setup(); | ||
| 49 | unsafe { executor.poll() }; | ||
| 50 | assert!(trace.get().is_empty()) | ||
| 51 | } | ||
| 52 | |||
| 53 | #[test] | ||
| 54 | fn executor_task() { | ||
| 55 | #[task] | ||
| 56 | async fn task1(trace: Trace) { | ||
| 57 | trace.push("poll task1") | ||
| 58 | } | ||
| 59 | |||
| 60 | let (executor, trace) = setup(); | ||
| 61 | executor.spawner().spawn(task1(trace.clone())).unwrap(); | ||
| 62 | |||
| 63 | unsafe { executor.poll() }; | ||
| 64 | unsafe { executor.poll() }; | ||
| 65 | |||
| 66 | assert_eq!( | ||
| 67 | trace.get(), | ||
| 68 | &[ | ||
| 69 | "pend", // spawning a task pends the executor | ||
| 70 | "poll task1", // poll only once. | ||
| 71 | ] | ||
| 72 | ) | ||
| 73 | } | ||
| 74 | |||
| 75 | #[test] | ||
| 76 | fn executor_task_self_wake() { | ||
| 77 | #[task] | ||
| 78 | async fn task1(trace: Trace) { | ||
| 79 | poll_fn(|cx| { | ||
| 80 | trace.push("poll task1"); | ||
| 81 | cx.waker().wake_by_ref(); | ||
| 82 | Poll::Pending | ||
| 83 | }) | ||
| 84 | .await | ||
| 85 | } | ||
| 86 | |||
| 87 | let (executor, trace) = setup(); | ||
| 88 | executor.spawner().spawn(task1(trace.clone())).unwrap(); | ||
| 89 | |||
| 90 | unsafe { executor.poll() }; | ||
| 91 | unsafe { executor.poll() }; | ||
| 92 | |||
| 93 | assert_eq!( | ||
| 94 | trace.get(), | ||
| 95 | &[ | ||
| 96 | "pend", // spawning a task pends the executor | ||
| 97 | "poll task1", // | ||
| 98 | "pend", // task self-wakes | ||
| 99 | "poll task1", // | ||
| 100 | "pend", // task self-wakes | ||
| 101 | ] | ||
| 102 | ) | ||
| 103 | } | ||
| 104 | |||
| 105 | #[test] | ||
| 106 | fn executor_task_self_wake_twice() { | ||
| 107 | #[task] | ||
| 108 | async fn task1(trace: Trace) { | ||
| 109 | poll_fn(|cx| { | ||
| 110 | trace.push("poll task1"); | ||
| 111 | cx.waker().wake_by_ref(); | ||
| 112 | trace.push("poll task1 wake 2"); | ||
| 113 | cx.waker().wake_by_ref(); | ||
| 114 | Poll::Pending | ||
| 115 | }) | ||
| 116 | .await | ||
| 117 | } | ||
| 118 | |||
| 119 | let (executor, trace) = setup(); | ||
| 120 | executor.spawner().spawn(task1(trace.clone())).unwrap(); | ||
| 121 | |||
| 122 | unsafe { executor.poll() }; | ||
| 123 | unsafe { executor.poll() }; | ||
| 124 | |||
| 125 | assert_eq!( | ||
| 126 | trace.get(), | ||
| 127 | &[ | ||
| 128 | "pend", // spawning a task pends the executor | ||
| 129 | "poll task1", // | ||
| 130 | "pend", // task self-wakes | ||
| 131 | "poll task1 wake 2", // task self-wakes again, shouldn't pend | ||
| 132 | "poll task1", // | ||
| 133 | "pend", // task self-wakes | ||
| 134 | "poll task1 wake 2", // task self-wakes again, shouldn't pend | ||
| 135 | ] | ||
| 136 | ) | ||
| 137 | } | ||
