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