diff options
| author | Dario Nieuwenhuis <[email protected]> | 2024-05-13 00:35:46 +0200 |
|---|---|---|
| committer | Dario Nieuwenhuis <[email protected]> | 2024-05-13 00:35:46 +0200 |
| commit | 1c9bb7c2e1ff7d68bfa709745f935040c8b415e1 (patch) | |
| tree | c0b6eac6b3a1e72f5d902d3ada8862e213c81353 /embassy-time/src | |
| parent | a8f578751ff3050edbd49cbeb7bbdddf0f3af6a5 (diff) | |
time/generic-queue: fix ub in tests.
Diffstat (limited to 'embassy-time/src')
| -rw-r--r-- | embassy-time/src/queue_generic.rs | 118 |
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")] |
| 179 | mod tests { | 179 | mod 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 | } |
