use crossbeam_channel::Sender; use std::time::Duration; use tokio::time; struct Dropper { sender: Sender<&'static str>, } impl Drop for Dropper { fn drop(&mut self) { self.sender.send("done").unwrap(); } } #[tokio::test(flavor = "multi_thread")] async fn strict_drop_ordering() { let (sender, receiver) = crossbeam_channel::bounded(10); let dropper = Dropper { sender }; let handle = structured_spawn::spawn(async move { let dropper = dropper; time::sleep(Duration::from_millis(100)).await; drop(dropper); unreachable!("the future should time-out before the timer resolves"); }); assert!(receiver.try_recv().is_err()); let _ = time::timeout(Duration::from_millis(10), handle).await; assert_eq!(receiver.try_recv().unwrap(), "done"); } #[tokio::test(flavor = "multi_thread")] async fn relaxed_drop_ordering() { let (sender, receiver) = crossbeam_channel::bounded(10); let dropper = Dropper { sender }; let handle = structured_spawn::spawn_relaxed(async move { let dropper = dropper; time::sleep(Duration::from_millis(100)).await; drop(dropper); // to guarantee the handle stays live unreachable!("the future should time-out before the timer resolves"); }); let _ = time::timeout(Duration::from_millis(10), handle).await; assert!( receiver.try_recv().is_err(), "cancellation might take a while to resolve" ); assert_eq!( receiver.recv().unwrap(), "done", "but cancellation is guaranteed to eventually resolve" ); }