1use futures::future::FutureExt;
2use std::alloc::Layout;
3use std::future::Future;
4use std::marker::PhantomPinned;
5use std::pin::Pin;
6use std::rc::Rc;
7use std::task::{Context, Poll};
8use 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)]
13fn 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]
22fn 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]
43fn 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
61struct ZeroSizedFuture {}
62impl Future for ZeroSizedFuture {
63 type Output = u32;
64 fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<u32> {
65 Poll::Ready(5)
66 }
67}
68
69#[test]
70fn 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