1 #![warn(rust_2018_idioms)]
2 #![cfg(all(feature = "full", not(target_os = "wasi")))] // Wasi does not support panic recovery
3
4 use tokio::io::{AsyncRead, AsyncReadExt, ReadBuf};
5 use tokio_test::assert_ok;
6
7 use std::io;
8 use std::pin::Pin;
9 use std::task::{Context, Poll};
10
11 mod support {
12 pub(crate) mod leaked_buffers;
13 }
14 use support::leaked_buffers::LeakedBuffers;
15
16 #[tokio::test]
read()17 async 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
45 struct BadAsyncRead {
46 leaked_buffers: LeakedBuffers,
47 }
48
49 impl BadAsyncRead {
new() -> Self50 fn new() -> Self {
51 Self {
52 leaked_buffers: LeakedBuffers::new(),
53 }
54 }
55 }
56
57 impl AsyncRead for BadAsyncRead {
poll_read( mut self: Pin<&mut Self>, _cx: &mut Context<'_>, buf: &mut ReadBuf<'_>, ) -> Poll<io::Result<()>>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]
read_buf_bad_async_read()72 async 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