blob: 3c9963dce22ea5b646c3c088811322eae92fd8f0 [file] [log] [blame]
// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#![cfg(test)]
use {
fuchsia_async as fasync,
fuchsia_zircon::{self as zx, HandleBased as _},
futures::stream::StreamExt as _,
tcp_stream_ext::TcpStreamExt as _,
};
const TCP_USER_TIMEOUT_OPTION_VALUE: i32 = -13;
fn with_tcp_stream(f: impl FnOnce(std::net::TcpStream) -> ()) {
let (client, server) =
fidl::endpoints::create_endpoints::<fidl_fuchsia_posix_socket::StreamSocketMarker>()
.expect("create stream socket endpoints");
// fdio::create_fd isn't async, so we need a dedicated thread for FIDL dispatch.
let handle = std::thread::spawn(|| {
fasync::Executor::new().expect("new executor").run_singlethreaded(
server.into_stream().expect("endpoint into stream").for_each(move |request| {
futures::future::ready(match request.expect("stream socket request stream") {
fidl_fuchsia_posix_socket::StreamSocketRequest::Close { responder } => {
let () = responder.control_handle().shutdown();
let () =
responder.send(zx::Status::OK.into_raw()).expect("send Close response");
}
fidl_fuchsia_posix_socket::StreamSocketRequest::Describe { responder } => {
let (s0, _s1) =
zx::Socket::create(zx::SocketOpts::STREAM).expect("create zx socket");
let () = responder
.send(&mut fidl_fuchsia_io::NodeInfo::StreamSocket(
fidl_fuchsia_io::StreamSocket { socket: s0 },
))
.expect("send Describe response");
}
fidl_fuchsia_posix_socket::StreamSocketRequest::GetSockOpt {
level,
optname,
responder,
} => {
let () = assert_eq!(i32::from(level), libc::IPPROTO_TCP);
let () = assert_eq!(i32::from(optname), libc::TCP_USER_TIMEOUT);
let () = responder
.send(&mut Ok(TCP_USER_TIMEOUT_OPTION_VALUE.to_le_bytes().to_vec()))
.expect("send GetSockOpt response");
}
fidl_fuchsia_posix_socket::StreamSocketRequest::GetTcpUserTimeout {
responder,
} => {
let () = responder
.send(&mut Ok(TCP_USER_TIMEOUT_OPTION_VALUE as u32))
.expect("send TcpUserTimeout response");
}
request => panic!("unhandled StreamSocketRequest: {:?}", request),
})
}),
)
});
let () = f(fdio::create_fd(client.into_handle()).expect("endpoint into handle"));
handle.join().expect("thread join")
}
#[test]
fn user_timeout_errors_on_negative_duration() {
with_tcp_stream(|stream| {
matches::assert_matches!(
stream.user_timeout(),
Err(tcp_stream_ext::Error::NegativeDuration(TCP_USER_TIMEOUT_OPTION_VALUE))
)
})
}