• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #![warn(rust_2018_idioms)]
2 #![cfg(all(feature = "full", not(tokio_wasi)))] // Wasi does not support panic recovery
3 
4 use std::task::{Context, Poll};
5 use std::{error::Error, pin::Pin};
6 use tokio::io::{self, split, AsyncRead, AsyncWrite, ReadBuf};
7 
8 mod support {
9     pub mod panic;
10 }
11 use support::panic::test_panic;
12 
13 struct RW;
14 
15 impl AsyncRead for RW {
poll_read( self: Pin<&mut Self>, _cx: &mut Context<'_>, buf: &mut ReadBuf<'_>, ) -> Poll<io::Result<()>>16     fn poll_read(
17         self: Pin<&mut Self>,
18         _cx: &mut Context<'_>,
19         buf: &mut ReadBuf<'_>,
20     ) -> Poll<io::Result<()>> {
21         buf.put_slice(&[b'z']);
22         Poll::Ready(Ok(()))
23     }
24 }
25 
26 impl AsyncWrite for RW {
poll_write( self: Pin<&mut Self>, _cx: &mut Context<'_>, _buf: &[u8], ) -> Poll<Result<usize, io::Error>>27     fn poll_write(
28         self: Pin<&mut Self>,
29         _cx: &mut Context<'_>,
30         _buf: &[u8],
31     ) -> Poll<Result<usize, io::Error>> {
32         Poll::Ready(Ok(1))
33     }
34 
poll_flush(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Result<(), io::Error>>35     fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Result<(), io::Error>> {
36         Poll::Ready(Ok(()))
37     }
38 
poll_shutdown(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Result<(), io::Error>>39     fn poll_shutdown(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Result<(), io::Error>> {
40         Poll::Ready(Ok(()))
41     }
42 }
43 
44 #[cfg(unix)]
45 mod unix {
46     use std::os::unix::prelude::{AsRawFd, RawFd};
47 
48     pub struct MockFd;
49 
50     impl AsRawFd for MockFd {
as_raw_fd(&self) -> RawFd51         fn as_raw_fd(&self) -> RawFd {
52             0
53         }
54     }
55 }
56 
57 #[test]
read_buf_initialize_unfilled_to_panic_caller() -> Result<(), Box<dyn Error>>58 fn read_buf_initialize_unfilled_to_panic_caller() -> Result<(), Box<dyn Error>> {
59     let panic_location_file = test_panic(|| {
60         let mut buffer = Vec::<u8>::new();
61         let mut read_buf = ReadBuf::new(&mut buffer);
62 
63         read_buf.initialize_unfilled_to(2);
64     });
65 
66     // The panic location should be in this file
67     assert_eq!(&panic_location_file.unwrap(), file!());
68 
69     Ok(())
70 }
71 
72 #[test]
read_buf_advance_panic_caller() -> Result<(), Box<dyn Error>>73 fn read_buf_advance_panic_caller() -> Result<(), Box<dyn Error>> {
74     let panic_location_file = test_panic(|| {
75         let mut buffer = Vec::<u8>::new();
76         let mut read_buf = ReadBuf::new(&mut buffer);
77 
78         read_buf.advance(2);
79     });
80 
81     // The panic location should be in this file
82     assert_eq!(&panic_location_file.unwrap(), file!());
83 
84     Ok(())
85 }
86 
87 #[test]
read_buf_set_filled_panic_caller() -> Result<(), Box<dyn Error>>88 fn read_buf_set_filled_panic_caller() -> Result<(), Box<dyn Error>> {
89     let panic_location_file = test_panic(|| {
90         let mut buffer = Vec::<u8>::new();
91         let mut read_buf = ReadBuf::new(&mut buffer);
92 
93         read_buf.set_filled(2);
94     });
95 
96     // The panic location should be in this file
97     assert_eq!(&panic_location_file.unwrap(), file!());
98 
99     Ok(())
100 }
101 
102 #[test]
read_buf_put_slice_panic_caller() -> Result<(), Box<dyn Error>>103 fn read_buf_put_slice_panic_caller() -> Result<(), Box<dyn Error>> {
104     let panic_location_file = test_panic(|| {
105         let mut buffer = Vec::<u8>::new();
106         let mut read_buf = ReadBuf::new(&mut buffer);
107 
108         let new_slice = [0x40_u8, 0x41_u8];
109 
110         read_buf.put_slice(&new_slice);
111     });
112 
113     // The panic location should be in this file
114     assert_eq!(&panic_location_file.unwrap(), file!());
115 
116     Ok(())
117 }
118 
119 #[test]
unsplit_panic_caller() -> Result<(), Box<dyn Error>>120 fn unsplit_panic_caller() -> Result<(), Box<dyn Error>> {
121     let panic_location_file = test_panic(|| {
122         let (r1, _w1) = split(RW);
123         let (_r2, w2) = split(RW);
124         r1.unsplit(w2);
125     });
126 
127     // The panic location should be in this file
128     assert_eq!(&panic_location_file.unwrap(), file!());
129 
130     Ok(())
131 }
132 
133 #[test]
134 #[cfg(unix)]
async_fd_new_panic_caller() -> Result<(), Box<dyn Error>>135 fn async_fd_new_panic_caller() -> Result<(), Box<dyn Error>> {
136     use tokio::io::unix::AsyncFd;
137     use tokio::runtime::Builder;
138 
139     let panic_location_file = test_panic(|| {
140         // Runtime without `enable_io` so it has no IO driver set.
141         let rt = Builder::new_current_thread().build().unwrap();
142         rt.block_on(async {
143             let fd = unix::MockFd;
144 
145             let _ = AsyncFd::new(fd);
146         });
147     });
148 
149     // The panic location should be in this file
150     assert_eq!(&panic_location_file.unwrap(), file!());
151 
152     Ok(())
153 }
154 
155 #[test]
156 #[cfg(unix)]
async_fd_with_interest_panic_caller() -> Result<(), Box<dyn Error>>157 fn async_fd_with_interest_panic_caller() -> Result<(), Box<dyn Error>> {
158     use tokio::io::unix::AsyncFd;
159     use tokio::io::Interest;
160     use tokio::runtime::Builder;
161 
162     let panic_location_file = test_panic(|| {
163         // Runtime without `enable_io` so it has no IO driver set.
164         let rt = Builder::new_current_thread().build().unwrap();
165         rt.block_on(async {
166             let fd = unix::MockFd;
167 
168             let _ = AsyncFd::with_interest(fd, Interest::READABLE);
169         });
170     });
171 
172     // The panic location should be in this file
173     assert_eq!(&panic_location_file.unwrap(), file!());
174 
175     Ok(())
176 }
177