1 | #![warn (rust_2018_idioms)] |
2 | #![cfg (all(feature = "full" , not(target_os = "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 { |
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 { |
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 | |
35 | fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Result<(), io::Error>> { |
36 | Poll::Ready(Ok(())) |
37 | } |
38 | |
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 { |
51 | fn as_raw_fd(&self) -> RawFd { |
52 | 0 |
53 | } |
54 | } |
55 | } |
56 | |
57 | #[cfg (panic = "unwind" )] |
58 | #[test] |
59 | fn read_buf_initialize_unfilled_to_panic_caller() -> Result<(), Box<dyn Error>> { |
60 | let panic_location_file = test_panic(|| { |
61 | let mut buffer = Vec::<u8>::new(); |
62 | let mut read_buf = ReadBuf::new(&mut buffer); |
63 | |
64 | read_buf.initialize_unfilled_to(2); |
65 | }); |
66 | |
67 | // The panic location should be in this file |
68 | assert_eq!(&panic_location_file.unwrap(), file!()); |
69 | |
70 | Ok(()) |
71 | } |
72 | |
73 | #[cfg (panic = "unwind" )] |
74 | #[test] |
75 | fn read_buf_advance_panic_caller() -> Result<(), Box<dyn Error>> { |
76 | let panic_location_file = test_panic(|| { |
77 | let mut buffer = Vec::<u8>::new(); |
78 | let mut read_buf = ReadBuf::new(&mut buffer); |
79 | |
80 | read_buf.advance(2); |
81 | }); |
82 | |
83 | // The panic location should be in this file |
84 | assert_eq!(&panic_location_file.unwrap(), file!()); |
85 | |
86 | Ok(()) |
87 | } |
88 | |
89 | #[cfg (panic = "unwind" )] |
90 | #[test] |
91 | fn read_buf_set_filled_panic_caller() -> Result<(), Box<dyn Error>> { |
92 | let panic_location_file = test_panic(|| { |
93 | let mut buffer = Vec::<u8>::new(); |
94 | let mut read_buf = ReadBuf::new(&mut buffer); |
95 | |
96 | read_buf.set_filled(2); |
97 | }); |
98 | |
99 | // The panic location should be in this file |
100 | assert_eq!(&panic_location_file.unwrap(), file!()); |
101 | |
102 | Ok(()) |
103 | } |
104 | |
105 | #[cfg (panic = "unwind" )] |
106 | #[test] |
107 | fn read_buf_put_slice_panic_caller() -> Result<(), Box<dyn Error>> { |
108 | let panic_location_file = test_panic(|| { |
109 | let mut buffer = Vec::<u8>::new(); |
110 | let mut read_buf = ReadBuf::new(&mut buffer); |
111 | |
112 | let new_slice = [0x40_u8, 0x41_u8]; |
113 | |
114 | read_buf.put_slice(&new_slice); |
115 | }); |
116 | |
117 | // The panic location should be in this file |
118 | assert_eq!(&panic_location_file.unwrap(), file!()); |
119 | |
120 | Ok(()) |
121 | } |
122 | |
123 | #[cfg (panic = "unwind" )] |
124 | #[test] |
125 | fn unsplit_panic_caller() -> Result<(), Box<dyn Error>> { |
126 | let panic_location_file = test_panic(|| { |
127 | let (r1, _w1) = split(RW); |
128 | let (_r2, w2) = split(RW); |
129 | r1.unsplit(w2); |
130 | }); |
131 | |
132 | // The panic location should be in this file |
133 | assert_eq!(&panic_location_file.unwrap(), file!()); |
134 | |
135 | Ok(()) |
136 | } |
137 | |
138 | #[test] |
139 | #[cfg (unix)] |
140 | fn async_fd_new_panic_caller() -> Result<(), Box<dyn Error>> { |
141 | use tokio::io::unix::AsyncFd; |
142 | use tokio::runtime::Builder; |
143 | |
144 | let panic_location_file = test_panic(|| { |
145 | // Runtime without `enable_io` so it has no IO driver set. |
146 | let rt = Builder::new_current_thread().build().unwrap(); |
147 | rt.block_on(async { |
148 | let fd = unix::MockFd; |
149 | |
150 | let _ = AsyncFd::new(fd); |
151 | }); |
152 | }); |
153 | |
154 | // The panic location should be in this file |
155 | assert_eq!(&panic_location_file.unwrap(), file!()); |
156 | |
157 | Ok(()) |
158 | } |
159 | |
160 | #[test] |
161 | #[cfg (unix)] |
162 | fn async_fd_with_interest_panic_caller() -> Result<(), Box<dyn Error>> { |
163 | use tokio::io::unix::AsyncFd; |
164 | use tokio::io::Interest; |
165 | use tokio::runtime::Builder; |
166 | |
167 | let panic_location_file = test_panic(|| { |
168 | // Runtime without `enable_io` so it has no IO driver set. |
169 | let rt = Builder::new_current_thread().build().unwrap(); |
170 | rt.block_on(async { |
171 | let fd = unix::MockFd; |
172 | |
173 | let _ = AsyncFd::with_interest(fd, Interest::READABLE); |
174 | }); |
175 | }); |
176 | |
177 | // The panic location should be in this file |
178 | assert_eq!(&panic_location_file.unwrap(), file!()); |
179 | |
180 | Ok(()) |
181 | } |
182 | |