1 use futures::future::FutureExt;
2 use std::alloc::Layout;
3 use std::future::Future;
4 use std::marker::PhantomPinned;
5 use std::pin::Pin;
6 use std::rc::Rc;
7 use std::task::{Context, Poll};
8 use tokio_util::sync::ReusableBoxFuture;
9
10 #[test]
11 // Clippy false positive; it's useful to be able to test the trait impls for any lifetime
12 #[allow(clippy::extra_unused_lifetimes)]
traits<'a>()13 fn traits<'a>() {
14 fn assert_traits<T: Send + Sync + Unpin>() {}
15 // Use a type that is !Unpin
16 assert_traits::<ReusableBoxFuture<'a, PhantomPinned>>();
17 // Use a type that is !Send + !Sync
18 assert_traits::<ReusableBoxFuture<'a, Rc<()>>>();
19 }
20
21 #[test]
test_different_futures()22 fn test_different_futures() {
23 let fut = async move { 10 };
24 // Not zero sized!
25 assert_eq!(Layout::for_value(&fut).size(), 1);
26
27 let mut b = ReusableBoxFuture::new(fut);
28
29 assert_eq!(b.get_pin().now_or_never(), Some(10));
30
31 b.try_set(async move { 20 })
32 .unwrap_or_else(|_| panic!("incorrect size"));
33
34 assert_eq!(b.get_pin().now_or_never(), Some(20));
35
36 b.try_set(async move { 30 })
37 .unwrap_or_else(|_| panic!("incorrect size"));
38
39 assert_eq!(b.get_pin().now_or_never(), Some(30));
40 }
41
42 #[test]
test_different_sizes()43 fn test_different_sizes() {
44 let fut1 = async move { 10 };
45 let val = [0u32; 1000];
46 let fut2 = async move { val[0] };
47 let fut3 = ZeroSizedFuture {};
48
49 assert_eq!(Layout::for_value(&fut1).size(), 1);
50 assert_eq!(Layout::for_value(&fut2).size(), 4004);
51 assert_eq!(Layout::for_value(&fut3).size(), 0);
52
53 let mut b = ReusableBoxFuture::new(fut1);
54 assert_eq!(b.get_pin().now_or_never(), Some(10));
55 b.set(fut2);
56 assert_eq!(b.get_pin().now_or_never(), Some(0));
57 b.set(fut3);
58 assert_eq!(b.get_pin().now_or_never(), Some(5));
59 }
60
61 struct ZeroSizedFuture {}
62 impl Future for ZeroSizedFuture {
63 type Output = u32;
poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<u32>64 fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<u32> {
65 Poll::Ready(5)
66 }
67 }
68
69 #[test]
test_zero_sized()70 fn test_zero_sized() {
71 let fut = ZeroSizedFuture {};
72 // Zero sized!
73 assert_eq!(Layout::for_value(&fut).size(), 0);
74
75 let mut b = ReusableBoxFuture::new(fut);
76
77 assert_eq!(b.get_pin().now_or_never(), Some(5));
78 assert_eq!(b.get_pin().now_or_never(), Some(5));
79
80 b.try_set(ZeroSizedFuture {})
81 .unwrap_or_else(|_| panic!("incorrect size"));
82
83 assert_eq!(b.get_pin().now_or_never(), Some(5));
84 assert_eq!(b.get_pin().now_or_never(), Some(5));
85 }
86