1#![warn(rust_2018_idioms)]
2#![cfg(all(feature = "full", not(target_os = "wasi")))] // Wasi does not support panic recovery
3
4use tokio::io::{AsyncRead, AsyncReadExt, ReadBuf};
5use tokio_test::assert_ok;
6
7use std::io;
8use std::pin::Pin;
9use std::task::{Context, Poll};
10
11mod support {
12 pub(crate) mod leaked_buffers;
13}
14use support::leaked_buffers::LeakedBuffers;
15
16#[tokio::test]
17async fn read() {
18 #[derive(Default)]
19 struct Rd {
20 poll_cnt: usize,
21 }
22
23 impl AsyncRead for Rd {
24 fn poll_read(
25 mut self: Pin<&mut Self>,
26 _cx: &mut Context<'_>,
27 buf: &mut ReadBuf<'_>,
28 ) -> Poll<io::Result<()>> {
29 assert_eq!(0, self.poll_cnt);
30 self.poll_cnt += 1;
31
32 buf.put_slice(b"hello world");
33 Poll::Ready(Ok(()))
34 }
35 }
36
37 let mut buf = Box::new([0; 11]);
38 let mut rd = Rd::default();
39
40 let n = assert_ok!(rd.read(&mut buf[..]).await);
41 assert_eq!(n, 11);
42 assert_eq!(buf[..], b"hello world"[..]);
43}
44
45struct BadAsyncRead {
46 leaked_buffers: LeakedBuffers,
47}
48
49impl BadAsyncRead {
50 fn new() -> Self {
51 Self {
52 leaked_buffers: LeakedBuffers::new(),
53 }
54 }
55}
56
57impl AsyncRead for BadAsyncRead {
58 fn poll_read(
59 mut self: Pin<&mut Self>,
60 _cx: &mut Context<'_>,
61 buf: &mut ReadBuf<'_>,
62 ) -> Poll<io::Result<()>> {
63 *buf = ReadBuf::new(unsafe { self.leaked_buffers.create(buf.capacity()) });
64 buf.advance(buf.capacity());
65
66 Poll::Ready(Ok(()))
67 }
68}
69
70#[tokio::test]
71#[should_panic]
72async fn read_buf_bad_async_read() {
73 let mut buf = Vec::with_capacity(10);
74 BadAsyncRead::new().read_buf(&mut buf).await.unwrap();
75}
76