diff --git a/tests/integration_tests/Cargo.toml b/tests/integration_tests/Cargo.toml
index 96863abba..8a6b86a22 100644
--- a/tests/integration_tests/Cargo.toml
+++ b/tests/integration_tests/Cargo.toml
@@ -12,7 +12,7 @@ version = "0.1.0"
bytes = "1.0"
futures-util = "0.3"
prost = "0.9"
-tokio = {version = "1.0", features = ["macros", "rt-multi-thread", "net"]}
+tokio = {version = "1.0", features = ["fs", "macros", "rt-multi-thread", "net"]}
tonic = {path = "../../tonic"}
[dev-dependencies]
diff --git a/tests/integration_tests/tests/connect_info.rs b/tests/integration_tests/tests/connect_info.rs
index 936eedac1..2a4cf7f10 100644
--- a/tests/integration_tests/tests/connect_info.rs
+++ b/tests/integration_tests/tests/connect_info.rs
@@ -48,3 +48,80 @@ async fn getting_connect_info() {
jh.await.unwrap();
}
+
+#[cfg(unix)]
+pub mod unix {
+ use std::{convert::TryFrom as _, path::Path};
+
+ use futures_util::FutureExt;
+ use tokio::{
+ net::{UnixListener, UnixStream},
+ sync::oneshot,
+ };
+ use tokio_stream::wrappers::UnixListenerStream;
+ use tonic::{
+ transport::{server::UdsConnectInfo, Endpoint, Server, Uri},
+ Request, Response, Status,
+ };
+ use tower::service_fn;
+
+ use integration_tests::pb::{test_client, test_server, Input, Output};
+
+ struct Svc {}
+
+ #[tonic::async_trait]
+ impl test_server::Test for Svc {
+ async fn unary_call(&self, req: Request) -> Result, Status> {
+ let conn_info = req.extensions().get::().unwrap();
+
+ // Client-side unix sockets are unnamed.
+ assert!(req.remote_addr().is_none());
+ assert!(conn_info.peer_addr.as_ref().unwrap().is_unnamed());
+ // This should contain process credentials for the client socket.
+ assert!(conn_info.peer_cred.as_ref().is_some());
+
+ Ok(Response::new(Output {}))
+ }
+ }
+
+ #[tokio::test]
+ async fn getting_connect_info() {
+ let unix_socket_path = "/tmp/tonic/uds-integration-test";
+ tokio::fs::create_dir_all(Path::new(unix_socket_path).parent().unwrap())
+ .await
+ .unwrap();
+
+ let uds = UnixListener::bind(unix_socket_path).unwrap();
+ let uds_stream = UnixListenerStream::new(uds);
+
+ let service = test_server::TestServer::new(Svc {});
+ let (tx, rx) = oneshot::channel::<()>();
+
+ let jh = tokio::spawn(async move {
+ Server::builder()
+ .add_service(service)
+ .serve_with_incoming_shutdown(uds_stream, rx.map(drop))
+ .await
+ .unwrap();
+ });
+
+ let channel = Endpoint::try_from("http://[::]:50051")
+ .unwrap()
+ .connect_with_connector(service_fn(move |_: Uri| {
+ UnixStream::connect(unix_socket_path)
+ }))
+ .await
+ .unwrap();
+
+ let mut client = test_client::TestClient::new(channel);
+
+ client.unary_call(Input {}).await.unwrap();
+
+ tx.send(()).unwrap();
+ jh.await.unwrap();
+
+ // tokio's `UnixListener` does not cleanup the socket automatically - we need to manually
+ // remove the file at the end of the test.
+ tokio::fs::remove_file(unix_socket_path).await.unwrap();
+ }
+}