blob: d05c6d19ed628c0912be3dd47417474b7f2a2a6d [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 option_value = match i32::from(optname) {
libc::TCP_USER_TIMEOUT => TCP_USER_TIMEOUT_OPTION_VALUE,
optname => panic!("unhandled GetSockOpt option name: {}", optname),
};
let () = responder
.send(&mut Ok(option_value.to_le_bytes().to_vec()))
.expect("send GetSockOpt 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))
)
})
}