diff options
Diffstat (limited to 'embassy-executor/tests/test.rs')
| -rw-r--r-- | embassy-executor/tests/test.rs | 93 |
1 files changed, 83 insertions, 10 deletions
diff --git a/embassy-executor/tests/test.rs b/embassy-executor/tests/test.rs index 78c49c071..6baf3dc21 100644 --- a/embassy-executor/tests/test.rs +++ b/embassy-executor/tests/test.rs | |||
| @@ -1,12 +1,13 @@ | |||
| 1 | #![cfg_attr(feature = "nightly", feature(impl_trait_in_assoc_type))] | 1 | #![cfg_attr(feature = "nightly", feature(impl_trait_in_assoc_type))] |
| 2 | #![cfg_attr(feature = "nightly", feature(never_type))] | ||
| 2 | 3 | ||
| 3 | use std::boxed::Box; | 4 | use std::boxed::Box; |
| 4 | use std::future::poll_fn; | 5 | use std::future::{poll_fn, Future}; |
| 5 | use std::sync::{Arc, Mutex}; | 6 | use std::sync::{Arc, Mutex}; |
| 6 | use std::task::Poll; | 7 | use std::task::Poll; |
| 7 | 8 | ||
| 8 | use embassy_executor::raw::Executor; | 9 | use embassy_executor::raw::Executor; |
| 9 | use embassy_executor::task; | 10 | use embassy_executor::{task, Spawner}; |
| 10 | 11 | ||
| 11 | #[export_name = "__pender"] | 12 | #[export_name = "__pender"] |
| 12 | fn __pender(context: *mut ()) { | 13 | fn __pender(context: *mut ()) { |
| @@ -58,8 +59,41 @@ fn executor_task() { | |||
| 58 | trace.push("poll task1") | 59 | trace.push("poll task1") |
| 59 | } | 60 | } |
| 60 | 61 | ||
| 62 | #[task] | ||
| 63 | async fn task2() -> ! { | ||
| 64 | panic!() | ||
| 65 | } | ||
| 66 | |||
| 61 | let (executor, trace) = setup(); | 67 | let (executor, trace) = setup(); |
| 62 | executor.spawner().spawn(task1(trace.clone())).unwrap(); | 68 | executor.spawner().spawn(task1(trace.clone()).unwrap()); |
| 69 | |||
| 70 | unsafe { executor.poll() }; | ||
| 71 | unsafe { executor.poll() }; | ||
| 72 | |||
| 73 | assert_eq!( | ||
| 74 | trace.get(), | ||
| 75 | &[ | ||
| 76 | "pend", // spawning a task pends the executor | ||
| 77 | "poll task1", // poll only once. | ||
| 78 | ] | ||
| 79 | ) | ||
| 80 | } | ||
| 81 | |||
| 82 | #[test] | ||
| 83 | fn executor_task_rpit() { | ||
| 84 | #[task] | ||
| 85 | fn task1(trace: Trace) -> impl Future<Output = ()> { | ||
| 86 | async move { trace.push("poll task1") } | ||
| 87 | } | ||
| 88 | |||
| 89 | #[cfg(feature = "nightly")] | ||
| 90 | #[task] | ||
| 91 | fn task2() -> impl Future<Output = !> { | ||
| 92 | async { panic!() } | ||
| 93 | } | ||
| 94 | |||
| 95 | let (executor, trace) = setup(); | ||
| 96 | executor.spawner().spawn(task1(trace.clone()).unwrap()); | ||
| 63 | 97 | ||
| 64 | unsafe { executor.poll() }; | 98 | unsafe { executor.poll() }; |
| 65 | unsafe { executor.poll() }; | 99 | unsafe { executor.poll() }; |
| @@ -86,7 +120,7 @@ fn executor_task_self_wake() { | |||
| 86 | } | 120 | } |
| 87 | 121 | ||
| 88 | let (executor, trace) = setup(); | 122 | let (executor, trace) = setup(); |
| 89 | executor.spawner().spawn(task1(trace.clone())).unwrap(); | 123 | executor.spawner().spawn(task1(trace.clone()).unwrap()); |
| 90 | 124 | ||
| 91 | unsafe { executor.poll() }; | 125 | unsafe { executor.poll() }; |
| 92 | unsafe { executor.poll() }; | 126 | unsafe { executor.poll() }; |
| @@ -118,7 +152,7 @@ fn executor_task_self_wake_twice() { | |||
| 118 | } | 152 | } |
| 119 | 153 | ||
| 120 | let (executor, trace) = setup(); | 154 | let (executor, trace) = setup(); |
| 121 | executor.spawner().spawn(task1(trace.clone())).unwrap(); | 155 | executor.spawner().spawn(task1(trace.clone()).unwrap()); |
| 122 | 156 | ||
| 123 | unsafe { executor.poll() }; | 157 | unsafe { executor.poll() }; |
| 124 | unsafe { executor.poll() }; | 158 | unsafe { executor.poll() }; |
| @@ -154,7 +188,7 @@ fn waking_after_completion_does_not_poll() { | |||
| 154 | let waker = Box::leak(Box::new(AtomicWaker::new())); | 188 | let waker = Box::leak(Box::new(AtomicWaker::new())); |
| 155 | 189 | ||
| 156 | let (executor, trace) = setup(); | 190 | let (executor, trace) = setup(); |
| 157 | executor.spawner().spawn(task1(trace.clone(), waker)).unwrap(); | 191 | executor.spawner().spawn(task1(trace.clone(), waker).unwrap()); |
| 158 | 192 | ||
| 159 | unsafe { executor.poll() }; | 193 | unsafe { executor.poll() }; |
| 160 | waker.wake(); | 194 | waker.wake(); |
| @@ -166,7 +200,7 @@ fn waking_after_completion_does_not_poll() { | |||
| 166 | unsafe { executor.poll() }; // Clears running status | 200 | unsafe { executor.poll() }; // Clears running status |
| 167 | 201 | ||
| 168 | // Can respawn waken-but-dead task | 202 | // Can respawn waken-but-dead task |
| 169 | executor.spawner().spawn(task1(trace.clone(), waker)).unwrap(); | 203 | executor.spawner().spawn(task1(trace.clone(), waker).unwrap()); |
| 170 | 204 | ||
| 171 | unsafe { executor.poll() }; | 205 | unsafe { executor.poll() }; |
| 172 | 206 | ||
| @@ -216,7 +250,7 @@ fn waking_with_old_waker_after_respawn() { | |||
| 216 | let waker = Box::leak(Box::new(AtomicWaker::new())); | 250 | let waker = Box::leak(Box::new(AtomicWaker::new())); |
| 217 | 251 | ||
| 218 | let (executor, trace) = setup(); | 252 | let (executor, trace) = setup(); |
| 219 | executor.spawner().spawn(task1(trace.clone(), waker)).unwrap(); | 253 | executor.spawner().spawn(task1(trace.clone(), waker).unwrap()); |
| 220 | 254 | ||
| 221 | unsafe { executor.poll() }; | 255 | unsafe { executor.poll() }; |
| 222 | unsafe { executor.poll() }; // progress to registering the waker | 256 | unsafe { executor.poll() }; // progress to registering the waker |
| @@ -239,8 +273,7 @@ fn waking_with_old_waker_after_respawn() { | |||
| 239 | let (other_executor, other_trace) = setup(); | 273 | let (other_executor, other_trace) = setup(); |
| 240 | other_executor | 274 | other_executor |
| 241 | .spawner() | 275 | .spawner() |
| 242 | .spawn(task1(other_trace.clone(), waker)) | 276 | .spawn(task1(other_trace.clone(), waker).unwrap()); |
| 243 | .unwrap(); | ||
| 244 | 277 | ||
| 245 | unsafe { other_executor.poll() }; // just run to the yield_now | 278 | unsafe { other_executor.poll() }; // just run to the yield_now |
| 246 | waker.wake(); // trigger old waker registration | 279 | waker.wake(); // trigger old waker registration |
| @@ -283,3 +316,43 @@ fn executor_task_cfg_args() { | |||
| 283 | let (_, _, _) = (a, b, c); | 316 | let (_, _, _) = (a, b, c); |
| 284 | } | 317 | } |
| 285 | } | 318 | } |
| 319 | |||
| 320 | #[test] | ||
| 321 | fn recursive_task() { | ||
| 322 | #[embassy_executor::task(pool_size = 2)] | ||
| 323 | async fn task1() { | ||
| 324 | let spawner = unsafe { Spawner::for_current_executor().await }; | ||
| 325 | spawner.spawn(task1().unwrap()); | ||
| 326 | } | ||
| 327 | } | ||
| 328 | |||
| 329 | #[cfg(feature = "metadata-name")] | ||
| 330 | #[test] | ||
| 331 | fn task_metadata() { | ||
| 332 | #[task] | ||
| 333 | async fn task1(expected_name: Option<&'static str>) { | ||
| 334 | use embassy_executor::Metadata; | ||
| 335 | assert_eq!(Metadata::for_current_task().await.name(), expected_name); | ||
| 336 | } | ||
| 337 | |||
| 338 | // check no task name | ||
| 339 | let (executor, _) = setup(); | ||
| 340 | executor.spawner().spawn(task1(None).unwrap()); | ||
| 341 | unsafe { executor.poll() }; | ||
| 342 | |||
| 343 | // check setting task name | ||
| 344 | let token = task1(Some("foo")).unwrap(); | ||
| 345 | token.metadata().set_name("foo"); | ||
| 346 | executor.spawner().spawn(token); | ||
| 347 | unsafe { executor.poll() }; | ||
| 348 | |||
| 349 | let token = task1(Some("bar")).unwrap(); | ||
| 350 | token.metadata().set_name("bar"); | ||
| 351 | executor.spawner().spawn(token); | ||
| 352 | unsafe { executor.poll() }; | ||
| 353 | |||
| 354 | // check name is cleared if the task pool slot is recycled. | ||
| 355 | let (executor, _) = setup(); | ||
| 356 | executor.spawner().spawn(task1(None).unwrap()); | ||
| 357 | unsafe { executor.poll() }; | ||
| 358 | } | ||
