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)] |
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] |
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] |
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; |
64 | fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<u32> { |
65 | Poll::Ready(5) |
66 | } |
67 | } |
68 | |
69 | #[test] |
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 | |