aboutsummaryrefslogtreecommitdiff
path: root/embassy-time
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2024-05-13 00:35:46 +0200
committerDario Nieuwenhuis <[email protected]>2024-05-13 00:35:46 +0200
commit1c9bb7c2e1ff7d68bfa709745f935040c8b415e1 (patch)
treec0b6eac6b3a1e72f5d902d3ada8862e213c81353 /embassy-time
parenta8f578751ff3050edbd49cbeb7bbdddf0f3af6a5 (diff)
time/generic-queue: fix ub in tests.
Diffstat (limited to 'embassy-time')
-rw-r--r--embassy-time/src/queue_generic.rs118
1 files changed, 52 insertions, 66 deletions
diff --git a/embassy-time/src/queue_generic.rs b/embassy-time/src/queue_generic.rs
index cf7a986d5..4882afd3e 100644
--- a/embassy-time/src/queue_generic.rs
+++ b/embassy-time/src/queue_generic.rs
@@ -177,9 +177,10 @@ embassy_time_queue_driver::timer_queue_impl!(static QUEUE: Queue = Queue::new())
177#[cfg(test)] 177#[cfg(test)]
178#[cfg(feature = "mock-driver")] 178#[cfg(feature = "mock-driver")]
179mod tests { 179mod tests {
180 use core::cell::Cell; 180 use core::sync::atomic::{AtomicBool, Ordering};
181 use core::task::{RawWaker, RawWakerVTable, Waker}; 181 use core::task::Waker;
182 use std::rc::Rc; 182 use std::sync::Arc;
183 use std::task::Wake;
183 184
184 use serial_test::serial; 185 use serial_test::serial;
185 186
@@ -188,44 +189,28 @@ mod tests {
188 use crate::{Duration, Instant}; 189 use crate::{Duration, Instant};
189 190
190 struct TestWaker { 191 struct TestWaker {
191 pub awoken: Rc<Cell<bool>>, 192 pub awoken: AtomicBool,
192 pub waker: Waker,
193 } 193 }
194 194
195 impl TestWaker { 195 impl Wake for TestWaker {
196 fn new() -> Self { 196 fn wake(self: Arc<Self>) {
197 let flag = Rc::new(Cell::new(false)); 197 self.awoken.store(true, Ordering::Relaxed);
198 198 }
199 const VTABLE: RawWakerVTable = RawWakerVTable::new(
200 |data: *const ()| {
201 unsafe {
202 Rc::increment_strong_count(data as *const Cell<bool>);
203 }
204 199
205 RawWaker::new(data as _, &VTABLE) 200 fn wake_by_ref(self: &Arc<Self>) {
206 }, 201 self.awoken.store(true, Ordering::Relaxed);
207 |data: *const ()| unsafe {
208 let data = data as *const Cell<bool>;
209 data.as_ref().unwrap().set(true);
210 Rc::decrement_strong_count(data);
211 },
212 |data: *const ()| unsafe {
213 (data as *const Cell<bool>).as_ref().unwrap().set(true);
214 },
215 |data: *const ()| unsafe {
216 Rc::decrement_strong_count(data);
217 },
218 );
219
220 let raw = RawWaker::new(Rc::into_raw(flag.clone()) as _, &VTABLE);
221
222 Self {
223 awoken: flag.clone(),
224 waker: unsafe { Waker::from_raw(raw) },
225 }
226 } 202 }
227 } 203 }
228 204
205 fn test_waker() -> (Arc<TestWaker>, Waker) {
206 let arc = Arc::new(TestWaker {
207 awoken: AtomicBool::new(false),
208 });
209 let waker = Waker::from(arc.clone());
210
211 (arc, waker)
212 }
213
229 fn setup() { 214 fn setup() {
230 MockDriver::get().reset(); 215 MockDriver::get().reset();
231 critical_section::with(|cs| *QUEUE.inner.borrow_ref_mut(cs) = None); 216 critical_section::with(|cs| *QUEUE.inner.borrow_ref_mut(cs) = None);
@@ -249,11 +234,11 @@ mod tests {
249 234
250 assert_eq!(queue_len(), 0); 235 assert_eq!(queue_len(), 0);
251 236
252 let waker = TestWaker::new(); 237 let (flag, waker) = test_waker();
253 238
254 QUEUE.schedule_wake(Instant::from_secs(1), &waker.waker); 239 QUEUE.schedule_wake(Instant::from_secs(1), &waker);
255 240
256 assert!(!waker.awoken.get()); 241 assert!(!flag.awoken.load(Ordering::Relaxed));
257 assert_eq!(queue_len(), 1); 242 assert_eq!(queue_len(), 1);
258 } 243 }
259 244
@@ -262,23 +247,23 @@ mod tests {
262 fn test_schedule_same() { 247 fn test_schedule_same() {
263 setup(); 248 setup();
264 249
265 let waker = TestWaker::new(); 250 let (_flag, waker) = test_waker();
266 251
267 QUEUE.schedule_wake(Instant::from_secs(1), &waker.waker); 252 QUEUE.schedule_wake(Instant::from_secs(1), &waker);
268 253
269 assert_eq!(queue_len(), 1); 254 assert_eq!(queue_len(), 1);
270 255
271 QUEUE.schedule_wake(Instant::from_secs(1), &waker.waker); 256 QUEUE.schedule_wake(Instant::from_secs(1), &waker);
272 257
273 assert_eq!(queue_len(), 1); 258 assert_eq!(queue_len(), 1);
274 259
275 QUEUE.schedule_wake(Instant::from_secs(100), &waker.waker); 260 QUEUE.schedule_wake(Instant::from_secs(100), &waker);
276 261
277 assert_eq!(queue_len(), 1); 262 assert_eq!(queue_len(), 1);
278 263
279 let waker2 = TestWaker::new(); 264 let (_flag2, waker2) = test_waker();
280 265
281 QUEUE.schedule_wake(Instant::from_secs(100), &waker2.waker); 266 QUEUE.schedule_wake(Instant::from_secs(100), &waker2);
282 267
283 assert_eq!(queue_len(), 2); 268 assert_eq!(queue_len(), 2);
284 } 269 }
@@ -288,21 +273,21 @@ mod tests {
288 fn test_trigger() { 273 fn test_trigger() {
289 setup(); 274 setup();
290 275
291 let waker = TestWaker::new(); 276 let (flag, waker) = test_waker();
292 277
293 QUEUE.schedule_wake(Instant::from_secs(100), &waker.waker); 278 QUEUE.schedule_wake(Instant::from_secs(100), &waker);
294 279
295 assert!(!waker.awoken.get()); 280 assert!(!flag.awoken.load(Ordering::Relaxed));
296 281
297 MockDriver::get().advance(Duration::from_secs(99)); 282 MockDriver::get().advance(Duration::from_secs(99));
298 283
299 assert!(!waker.awoken.get()); 284 assert!(!flag.awoken.load(Ordering::Relaxed));
300 285
301 assert_eq!(queue_len(), 1); 286 assert_eq!(queue_len(), 1);
302 287
303 MockDriver::get().advance(Duration::from_secs(1)); 288 MockDriver::get().advance(Duration::from_secs(1));
304 289
305 assert!(waker.awoken.get()); 290 assert!(flag.awoken.load(Ordering::Relaxed));
306 291
307 assert_eq!(queue_len(), 0); 292 assert_eq!(queue_len(), 0);
308 } 293 }
@@ -312,18 +297,18 @@ mod tests {
312 fn test_immediate_trigger() { 297 fn test_immediate_trigger() {
313 setup(); 298 setup();
314 299
315 let waker = TestWaker::new(); 300 let (flag, waker) = test_waker();
316 301
317 QUEUE.schedule_wake(Instant::from_secs(100), &waker.waker); 302 QUEUE.schedule_wake(Instant::from_secs(100), &waker);
318 303
319 MockDriver::get().advance(Duration::from_secs(50)); 304 MockDriver::get().advance(Duration::from_secs(50));
320 305
321 let waker2 = TestWaker::new(); 306 let (flag2, waker2) = test_waker();
322 307
323 QUEUE.schedule_wake(Instant::from_secs(40), &waker2.waker); 308 QUEUE.schedule_wake(Instant::from_secs(40), &waker2);
324 309
325 assert!(!waker.awoken.get()); 310 assert!(!flag.awoken.load(Ordering::Relaxed));
326 assert!(waker2.awoken.get()); 311 assert!(flag2.awoken.load(Ordering::Relaxed));
327 assert_eq!(queue_len(), 1); 312 assert_eq!(queue_len(), 1);
328 } 313 }
329 314
@@ -333,30 +318,31 @@ mod tests {
333 setup(); 318 setup();
334 319
335 for i in 1..super::QUEUE_SIZE { 320 for i in 1..super::QUEUE_SIZE {
336 let waker = TestWaker::new(); 321 let (flag, waker) = test_waker();
337 322
338 QUEUE.schedule_wake(Instant::from_secs(310), &waker.waker); 323 QUEUE.schedule_wake(Instant::from_secs(310), &waker);
339 324
340 assert_eq!(queue_len(), i); 325 assert_eq!(queue_len(), i);
341 assert!(!waker.awoken.get()); 326 assert!(!flag.awoken.load(Ordering::Relaxed));
342 } 327 }
343 328
344 let first_waker = TestWaker::new(); 329 let (flag, waker) = test_waker();
345 330
346 QUEUE.schedule_wake(Instant::from_secs(300), &first_waker.waker); 331 QUEUE.schedule_wake(Instant::from_secs(300), &waker);
347 332
348 assert_eq!(queue_len(), super::QUEUE_SIZE); 333 assert_eq!(queue_len(), super::QUEUE_SIZE);
349 assert!(!first_waker.awoken.get()); 334 assert!(!flag.awoken.load(Ordering::Relaxed));
350 335
351 let second_waker = TestWaker::new(); 336 let (flag2, waker2) = test_waker();
352 337
353 QUEUE.schedule_wake(Instant::from_secs(305), &second_waker.waker); 338 QUEUE.schedule_wake(Instant::from_secs(305), &waker2);
354 339
355 assert_eq!(queue_len(), super::QUEUE_SIZE); 340 assert_eq!(queue_len(), super::QUEUE_SIZE);
356 assert!(first_waker.awoken.get()); 341 assert!(flag.awoken.load(Ordering::Relaxed));
357 342
358 QUEUE.schedule_wake(Instant::from_secs(320), &TestWaker::new().waker); 343 let (_flag3, waker3) = test_waker();
344 QUEUE.schedule_wake(Instant::from_secs(320), &waker3);
359 assert_eq!(queue_len(), super::QUEUE_SIZE); 345 assert_eq!(queue_len(), super::QUEUE_SIZE);
360 assert!(second_waker.awoken.get()); 346 assert!(flag2.awoken.load(Ordering::Relaxed));
361 } 347 }
362} 348}