1 #![warn(rust_2018_idioms)]
2 #![cfg(all(feature = "full", not(target_os = "wasi")))]
3 #![cfg(panic = "unwind")]
4 
5 use std::error::Error;
6 use tokio::net::{TcpListener, TcpStream};
7 use tokio::runtime::{Builder, Runtime};
8 
9 mod support {
10     pub mod panic;
11 }
12 use support::panic::test_panic;
13 
14 #[test]
15 #[cfg_attr(miri, ignore)] // No `socket` in miri.
udp_socket_from_std_panic_caller() -> Result<(), Box<dyn Error>>16 fn udp_socket_from_std_panic_caller() -> Result<(), Box<dyn Error>> {
17     use std::net::SocketAddr;
18     use tokio::net::UdpSocket;
19 
20     let addr = "127.0.0.1:0".parse::<SocketAddr>().unwrap();
21     let std_sock = std::net::UdpSocket::bind(addr).unwrap();
22     std_sock.set_nonblocking(true).unwrap();
23 
24     let panic_location_file = test_panic(|| {
25         let rt = runtime_without_io();
26         rt.block_on(async {
27             let _sock = UdpSocket::from_std(std_sock);
28         });
29     });
30 
31     // The panic location should be in this file
32     assert_eq!(&panic_location_file.unwrap(), file!());
33 
34     Ok(())
35 }
36 
37 #[test]
38 #[cfg_attr(miri, ignore)] // No `socket` in miri.
tcp_listener_from_std_panic_caller() -> Result<(), Box<dyn Error>>39 fn tcp_listener_from_std_panic_caller() -> Result<(), Box<dyn Error>> {
40     let std_listener = std::net::TcpListener::bind("127.0.0.1:0").unwrap();
41     std_listener.set_nonblocking(true).unwrap();
42 
43     let panic_location_file = test_panic(|| {
44         let rt = runtime_without_io();
45         rt.block_on(async {
46             let _ = TcpListener::from_std(std_listener);
47         });
48     });
49 
50     // The panic location should be in this file
51     assert_eq!(&panic_location_file.unwrap(), file!());
52 
53     Ok(())
54 }
55 
56 #[test]
57 #[cfg_attr(miri, ignore)] // No `socket` in miri.
tcp_stream_from_std_panic_caller() -> Result<(), Box<dyn Error>>58 fn tcp_stream_from_std_panic_caller() -> Result<(), Box<dyn Error>> {
59     let std_listener = std::net::TcpListener::bind("127.0.0.1:0").unwrap();
60 
61     let std_stream = std::net::TcpStream::connect(std_listener.local_addr().unwrap()).unwrap();
62     std_stream.set_nonblocking(true).unwrap();
63 
64     let panic_location_file = test_panic(|| {
65         let rt = runtime_without_io();
66         rt.block_on(async {
67             let _ = TcpStream::from_std(std_stream);
68         });
69     });
70 
71     // The panic location should be in this file
72     assert_eq!(&panic_location_file.unwrap(), file!());
73 
74     Ok(())
75 }
76 
77 #[test]
78 #[cfg(unix)]
79 #[cfg_attr(miri, ignore)] // No `socket` in miri.
unix_listener_bind_panic_caller() -> Result<(), Box<dyn Error>>80 fn unix_listener_bind_panic_caller() -> Result<(), Box<dyn Error>> {
81     use tokio::net::UnixListener;
82 
83     let dir = tempfile::tempdir().unwrap();
84     let sock_path = dir.path().join("socket");
85 
86     let panic_location_file = test_panic(|| {
87         let rt = runtime_without_io();
88         rt.block_on(async {
89             let _ = UnixListener::bind(&sock_path);
90         });
91     });
92 
93     // The panic location should be in this file
94     assert_eq!(&panic_location_file.unwrap(), file!());
95 
96     Ok(())
97 }
98 
99 #[test]
100 #[cfg(unix)]
101 #[cfg_attr(miri, ignore)] // No `socket` in miri.
unix_listener_from_std_panic_caller() -> Result<(), Box<dyn Error>>102 fn unix_listener_from_std_panic_caller() -> Result<(), Box<dyn Error>> {
103     use tokio::net::UnixListener;
104 
105     let dir = tempfile::tempdir().unwrap();
106     let sock_path = dir.path().join("socket");
107     let std_listener = std::os::unix::net::UnixListener::bind(sock_path).unwrap();
108 
109     let panic_location_file = test_panic(|| {
110         let rt = runtime_without_io();
111         rt.block_on(async {
112             let _ = UnixListener::from_std(std_listener);
113         });
114     });
115 
116     // The panic location should be in this file
117     assert_eq!(&panic_location_file.unwrap(), file!());
118 
119     Ok(())
120 }
121 
122 #[test]
123 #[cfg(unix)]
124 #[cfg_attr(miri, ignore)] // No `socket` in miri.
unix_stream_from_std_panic_caller() -> Result<(), Box<dyn Error>>125 fn unix_stream_from_std_panic_caller() -> Result<(), Box<dyn Error>> {
126     use tokio::net::UnixStream;
127 
128     let dir = tempfile::tempdir().unwrap();
129     let sock_path = dir.path().join("socket");
130     let _std_listener = std::os::unix::net::UnixListener::bind(&sock_path).unwrap();
131     let std_stream = std::os::unix::net::UnixStream::connect(&sock_path).unwrap();
132 
133     let panic_location_file = test_panic(|| {
134         let rt = runtime_without_io();
135         rt.block_on(async {
136             let _ = UnixStream::from_std(std_stream);
137         });
138     });
139 
140     // The panic location should be in this file
141     assert_eq!(&panic_location_file.unwrap(), file!());
142 
143     Ok(())
144 }
145 
146 #[test]
147 #[cfg(unix)]
148 #[cfg_attr(miri, ignore)] // No `socket` in miri.
unix_datagram_from_std_panic_caller() -> Result<(), Box<dyn Error>>149 fn unix_datagram_from_std_panic_caller() -> Result<(), Box<dyn Error>> {
150     use std::os::unix::net::UnixDatagram as StdUDS;
151     use tokio::net::UnixDatagram;
152 
153     let dir = tempfile::tempdir().unwrap();
154     let sock_path = dir.path().join("socket");
155 
156     // Bind the socket to a filesystem path
157     // /let socket_path = tmp.path().join("socket");
158     let std_socket = StdUDS::bind(sock_path).unwrap();
159     std_socket.set_nonblocking(true).unwrap();
160 
161     let panic_location_file = test_panic(move || {
162         let rt = runtime_without_io();
163         rt.block_on(async {
164             let _ = UnixDatagram::from_std(std_socket);
165         });
166     });
167 
168     // The panic location should be in this file
169     assert_eq!(&panic_location_file.unwrap(), file!());
170 
171     Ok(())
172 }
173 
174 #[test]
175 #[cfg(windows)]
server_options_max_instances_panic_caller() -> Result<(), Box<dyn Error>>176 fn server_options_max_instances_panic_caller() -> Result<(), Box<dyn Error>> {
177     use tokio::net::windows::named_pipe::ServerOptions;
178 
179     let panic_location_file = test_panic(move || {
180         let rt = runtime_without_io();
181         rt.block_on(async {
182             let mut options = ServerOptions::new();
183             options.max_instances(255);
184         });
185     });
186 
187     // The panic location should be in this file
188     assert_eq!(&panic_location_file.unwrap(), file!());
189 
190     Ok(())
191 }
192 
193 // Runtime without `enable_io` so it has no IO driver set.
runtime_without_io() -> Runtime194 fn runtime_without_io() -> Runtime {
195     Builder::new_current_thread().build().unwrap()
196 }
197