1#![warn(rust_2018_idioms)]
2#![cfg(feature = "full")]
3
4use std::pin::Pin;
5use std::task::{Context, Poll};
6use tokio::io::{AsyncRead, AsyncReadExt, ReadBuf};
7use tokio_test::assert_ok;
8use tokio_test::io::Builder;
9
10#[tokio::test]
11async fn read_to_end() {
12 let mut buf = vec![];
13 let mut rd: &[u8] = b"hello world";
14
15 let n = assert_ok!(rd.read_to_end(&mut buf).await);
16 assert_eq!(n, 11);
17 assert_eq!(buf[..], b"hello world"[..]);
18}
19
20#[derive(Copy, Clone, Debug)]
21enum State {
22 Initializing,
23 JustFilling,
24 Done,
25}
26
27struct UninitTest {
28 num_init: usize,
29 state: State,
30}
31
32impl AsyncRead for UninitTest {
33 fn poll_read(
34 self: Pin<&mut Self>,
35 _cx: &mut Context<'_>,
36 buf: &mut ReadBuf<'_>,
37 ) -> Poll<std::io::Result<()>> {
38 let me = Pin::into_inner(self);
39 let real_num_init = buf.initialized().len() - buf.filled().len();
40 assert_eq!(real_num_init, me.num_init, "{:?}", me.state);
41
42 match me.state {
43 State::Initializing => {
44 buf.initialize_unfilled_to(me.num_init + 2);
45 buf.advance(1);
46 me.num_init += 1;
47
48 if me.num_init == 24 {
49 me.state = State::JustFilling;
50 }
51 }
52 State::JustFilling => {
53 buf.advance(1);
54 me.num_init -= 1;
55
56 if me.num_init == 15 {
57 // The buffer is resized on next call.
58 me.num_init = 0;
59 me.state = State::Done;
60 }
61 }
62 State::Done => { /* .. do nothing .. */ }
63 }
64
65 Poll::Ready(Ok(()))
66 }
67}
68
69#[tokio::test]
70async fn read_to_end_uninit() {
71 let mut buf = Vec::with_capacity(64);
72 let mut test = UninitTest {
73 num_init: 0,
74 state: State::Initializing,
75 };
76
77 test.read_to_end(&mut buf).await.unwrap();
78 assert_eq!(buf.len(), 33);
79}
80
81#[tokio::test]
82async fn read_to_end_doesnt_grow_with_capacity() {
83 let arr: Vec<u8> = (0..100).collect();
84
85 // We only test from 32 since we allocate at least 32 bytes each time
86 for len in 32..100 {
87 let bytes = &arr[..len];
88 for split in 0..len {
89 for cap in 0..101 {
90 let mut mock = if split == 0 {
91 Builder::new().read(bytes).build()
92 } else {
93 Builder::new()
94 .read(&bytes[..split])
95 .read(&bytes[split..])
96 .build()
97 };
98 let mut buf = Vec::with_capacity(cap);
99 AsyncReadExt::read_to_end(&mut mock, &mut buf)
100 .await
101 .unwrap();
102 // It has the right data.
103 assert_eq!(buf.as_slice(), bytes);
104 // Unless cap was smaller than length, then we did not reallocate.
105 if cap >= len {
106 assert_eq!(buf.capacity(), cap);
107 }
108 }
109 }
110 }
111}
112
113#[tokio::test]
114async fn read_to_end_grows_capacity_if_unfit() {
115 let bytes = b"the_vector_startingcap_will_be_smaller";
116 let mut mock = Builder::new().read(bytes).build();
117 let initial_capacity = bytes.len() - 4;
118 let mut buf = Vec::with_capacity(initial_capacity);
119 AsyncReadExt::read_to_end(&mut mock, &mut buf)
120 .await
121 .unwrap();
122 // *4 since it doubles when it doesn't fit and again when reaching EOF
123 assert_eq!(buf.capacity(), initial_capacity * 4);
124}
125