diff options
| author | Dániel Buga <[email protected]> | 2024-11-26 00:20:34 +0100 |
|---|---|---|
| committer | Dániel Buga <[email protected]> | 2024-12-17 16:52:13 +0100 |
| commit | c6ca46c82529e014aaceb218ad88978c50f0db07 (patch) | |
| tree | ed976c45f41a34e6b7ba59aaa047dfc6adc00728 /embassy-executor/tests/test.rs | |
| parent | 2853308d8f7b845a9255bd7f68911a5214f17ca1 (diff) | |
Set RUN_QUEUED unconditionally
Diffstat (limited to 'embassy-executor/tests/test.rs')
| -rw-r--r-- | embassy-executor/tests/test.rs | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/embassy-executor/tests/test.rs b/embassy-executor/tests/test.rs index 0ce1f1891..78c49c071 100644 --- a/embassy-executor/tests/test.rs +++ b/embassy-executor/tests/test.rs | |||
| @@ -138,6 +138,139 @@ fn executor_task_self_wake_twice() { | |||
| 138 | } | 138 | } |
| 139 | 139 | ||
| 140 | #[test] | 140 | #[test] |
| 141 | fn waking_after_completion_does_not_poll() { | ||
| 142 | use embassy_sync::waitqueue::AtomicWaker; | ||
| 143 | |||
| 144 | #[task] | ||
| 145 | async fn task1(trace: Trace, waker: &'static AtomicWaker) { | ||
| 146 | poll_fn(|cx| { | ||
| 147 | trace.push("poll task1"); | ||
| 148 | waker.register(cx.waker()); | ||
| 149 | Poll::Ready(()) | ||
| 150 | }) | ||
| 151 | .await | ||
| 152 | } | ||
| 153 | |||
| 154 | let waker = Box::leak(Box::new(AtomicWaker::new())); | ||
| 155 | |||
| 156 | let (executor, trace) = setup(); | ||
| 157 | executor.spawner().spawn(task1(trace.clone(), waker)).unwrap(); | ||
| 158 | |||
| 159 | unsafe { executor.poll() }; | ||
| 160 | waker.wake(); | ||
| 161 | unsafe { executor.poll() }; | ||
| 162 | |||
| 163 | // Exited task may be waken but is not polled | ||
| 164 | waker.wake(); | ||
| 165 | waker.wake(); | ||
| 166 | unsafe { executor.poll() }; // Clears running status | ||
| 167 | |||
| 168 | // Can respawn waken-but-dead task | ||
| 169 | executor.spawner().spawn(task1(trace.clone(), waker)).unwrap(); | ||
| 170 | |||
| 171 | unsafe { executor.poll() }; | ||
| 172 | |||
| 173 | assert_eq!( | ||
| 174 | trace.get(), | ||
| 175 | &[ | ||
| 176 | "pend", // spawning a task pends the executor | ||
| 177 | "poll task1", // | ||
| 178 | "pend", // manual wake, gets cleared by poll | ||
| 179 | "pend", // manual wake, single pend for two wakes | ||
| 180 | "pend", // respawning a task pends the executor | ||
| 181 | "poll task1", // | ||
| 182 | ] | ||
| 183 | ) | ||
| 184 | } | ||
| 185 | |||
| 186 | #[test] | ||
| 187 | fn waking_with_old_waker_after_respawn() { | ||
| 188 | use embassy_sync::waitqueue::AtomicWaker; | ||
| 189 | |||
| 190 | async fn yield_now(trace: Trace) { | ||
| 191 | let mut yielded = false; | ||
| 192 | poll_fn(|cx| { | ||
| 193 | if yielded { | ||
| 194 | Poll::Ready(()) | ||
| 195 | } else { | ||
| 196 | trace.push("yield_now"); | ||
| 197 | yielded = true; | ||
| 198 | cx.waker().wake_by_ref(); | ||
| 199 | Poll::Pending | ||
| 200 | } | ||
| 201 | }) | ||
| 202 | .await | ||
| 203 | } | ||
| 204 | |||
| 205 | #[task] | ||
| 206 | async fn task1(trace: Trace, waker: &'static AtomicWaker) { | ||
| 207 | yield_now(trace.clone()).await; | ||
| 208 | poll_fn(|cx| { | ||
| 209 | trace.push("poll task1"); | ||
| 210 | waker.register(cx.waker()); | ||
| 211 | Poll::Ready(()) | ||
| 212 | }) | ||
| 213 | .await; | ||
| 214 | } | ||
| 215 | |||
| 216 | let waker = Box::leak(Box::new(AtomicWaker::new())); | ||
| 217 | |||
| 218 | let (executor, trace) = setup(); | ||
| 219 | executor.spawner().spawn(task1(trace.clone(), waker)).unwrap(); | ||
| 220 | |||
| 221 | unsafe { executor.poll() }; | ||
| 222 | unsafe { executor.poll() }; // progress to registering the waker | ||
| 223 | waker.wake(); | ||
| 224 | unsafe { executor.poll() }; | ||
| 225 | // Task has exited | ||
| 226 | |||
| 227 | assert_eq!( | ||
| 228 | trace.get(), | ||
| 229 | &[ | ||
| 230 | "pend", // spawning a task pends the executor | ||
| 231 | "yield_now", // | ||
| 232 | "pend", // yield_now wakes the task | ||
| 233 | "poll task1", // | ||
| 234 | "pend", // task self-wakes | ||
| 235 | ] | ||
| 236 | ); | ||
| 237 | |||
| 238 | // Can respawn task on another executor | ||
| 239 | let (other_executor, other_trace) = setup(); | ||
| 240 | other_executor | ||
| 241 | .spawner() | ||
| 242 | .spawn(task1(other_trace.clone(), waker)) | ||
| 243 | .unwrap(); | ||
| 244 | |||
| 245 | unsafe { other_executor.poll() }; // just run to the yield_now | ||
| 246 | waker.wake(); // trigger old waker registration | ||
| 247 | unsafe { executor.poll() }; | ||
| 248 | unsafe { other_executor.poll() }; | ||
| 249 | |||
| 250 | // First executor's trace has not changed | ||
| 251 | assert_eq!( | ||
| 252 | trace.get(), | ||
| 253 | &[ | ||
| 254 | "pend", // spawning a task pends the executor | ||
| 255 | "yield_now", // | ||
| 256 | "pend", // yield_now wakes the task | ||
| 257 | "poll task1", // | ||
| 258 | "pend", // task self-wakes | ||
| 259 | ] | ||
| 260 | ); | ||
| 261 | |||
| 262 | assert_eq!( | ||
| 263 | other_trace.get(), | ||
| 264 | &[ | ||
| 265 | "pend", // spawning a task pends the executor | ||
| 266 | "yield_now", // | ||
| 267 | "pend", // manual wake, gets cleared by poll | ||
| 268 | "poll task1", // | ||
| 269 | ] | ||
| 270 | ); | ||
| 271 | } | ||
| 272 | |||
| 273 | #[test] | ||
| 141 | fn executor_task_cfg_args() { | 274 | fn executor_task_cfg_args() { |
| 142 | // simulate cfg'ing away argument c | 275 | // simulate cfg'ing away argument c |
| 143 | #[task] | 276 | #[task] |
