1 #![warn(rust_2018_idioms)]
2 #![cfg(feature = "full")]
3 #![cfg(unix)]
4 
5 use futures::future::try_join;
6 use std::io;
7 use tokio::{
8     io::{AsyncReadExt, AsyncWriteExt},
9     net::UnixSocket,
10 };
11 
12 #[tokio::test]
13 #[cfg_attr(miri, ignore)] // No `socket` in miri.
datagram_echo_server() -> io::Result<()>14 async fn datagram_echo_server() -> io::Result<()> {
15     let dir = tempfile::tempdir().unwrap();
16     let server_path = dir.path().join("server.sock");
17     let client_path = dir.path().join("client.sock");
18 
19     let server_socket = {
20         let socket = UnixSocket::new_datagram()?;
21         socket.bind(&server_path)?;
22         socket.datagram()?
23     };
24 
25     tokio::spawn(async move {
26         let mut recv_buf = vec![0u8; 1024];
27         loop {
28             let (len, peer_addr) = server_socket.recv_from(&mut recv_buf[..]).await?;
29             if let Some(path) = peer_addr.as_pathname() {
30                 server_socket.send_to(&recv_buf[..len], path).await?;
31             }
32         }
33 
34         #[allow(unreachable_code)]
35         Ok::<(), io::Error>(())
36     });
37 
38     {
39         let socket = UnixSocket::new_datagram()?;
40         socket.bind(&client_path).unwrap();
41         let socket = socket.datagram()?;
42 
43         socket.connect(server_path)?;
44         socket.send(b"ECHO").await?;
45 
46         let mut recv_buf = [0u8; 16];
47         let len = socket.recv(&mut recv_buf[..]).await?;
48         assert_eq!(&recv_buf[..len], b"ECHO");
49     }
50 
51     Ok(())
52 }
53 
54 #[tokio::test]
55 #[cfg_attr(miri, ignore)] // No `socket` in miri.
listen_and_stream() -> std::io::Result<()>56 async fn listen_and_stream() -> std::io::Result<()> {
57     let dir = tempfile::Builder::new().tempdir().unwrap();
58     let sock_path = dir.path().join("connect.sock");
59     let peer_path = dir.path().join("peer.sock");
60 
61     let listener = {
62         let sock = UnixSocket::new_stream()?;
63         sock.bind(&sock_path)?;
64         sock.listen(1024)?
65     };
66 
67     let accept = listener.accept();
68     let connect = {
69         let sock = UnixSocket::new_stream()?;
70         sock.bind(&peer_path)?;
71         sock.connect(&sock_path)
72     };
73 
74     let ((mut server, _), mut client) = try_join(accept, connect).await?;
75 
76     assert_eq!(
77         server.peer_addr().unwrap().as_pathname().unwrap(),
78         &peer_path
79     );
80 
81     // Write to the client.
82     client.write_all(b"hello").await?;
83     drop(client);
84 
85     // Read from the server.
86     let mut buf = vec![];
87     server.read_to_end(&mut buf).await?;
88     assert_eq!(&buf, b"hello");
89     let len = server.read(&mut buf).await?;
90     assert_eq!(len, 0);
91     Ok(())
92 }
93 
94 #[tokio::test]
95 #[cfg_attr(miri, ignore)] // No `socket` in miri.
assert_usage() -> std::io::Result<()>96 async fn assert_usage() -> std::io::Result<()> {
97     let datagram_socket = UnixSocket::new_datagram()?;
98     let result = datagram_socket
99         .connect(std::path::PathBuf::new().join("invalid.sock"))
100         .await;
101     assert_eq!(
102         result.unwrap_err().to_string(),
103         "connect cannot be called on a datagram socket"
104     );
105 
106     let datagram_socket = UnixSocket::new_datagram()?;
107     let result = datagram_socket.listen(1024);
108     assert_eq!(
109         result.unwrap_err().to_string(),
110         "listen cannot be called on a datagram socket"
111     );
112 
113     let stream_socket = UnixSocket::new_stream()?;
114     let result = stream_socket.datagram();
115     assert_eq!(
116         result.unwrap_err().to_string(),
117         "datagram cannot be called on a stream socket"
118     );
119 
120     Ok(())
121 }
122