185 lines
5.1 KiB
Rust
185 lines
5.1 KiB
Rust
|
|
#![warn(rust_2018_idioms)]
|
||
|
|
#![cfg(all(feature = "full", not(target_os = "wasi"), not(miri)))] // Wasi doesn't support bind
|
||
|
|
// No `socket` on miri.
|
||
|
|
|
||
|
|
use std::time::Duration;
|
||
|
|
use tokio::net::TcpSocket;
|
||
|
|
use tokio_test::assert_ok;
|
||
|
|
|
||
|
|
#[tokio::test]
|
||
|
|
async fn basic_usage_v4() {
|
||
|
|
// Create server
|
||
|
|
let addr = assert_ok!("127.0.0.1:0".parse());
|
||
|
|
let srv = assert_ok!(TcpSocket::new_v4());
|
||
|
|
assert_ok!(srv.bind(addr));
|
||
|
|
|
||
|
|
let srv = assert_ok!(srv.listen(128));
|
||
|
|
|
||
|
|
// Create client & connect
|
||
|
|
let addr = srv.local_addr().unwrap();
|
||
|
|
let cli = assert_ok!(TcpSocket::new_v4());
|
||
|
|
let _cli = assert_ok!(cli.connect(addr).await);
|
||
|
|
|
||
|
|
// Accept
|
||
|
|
let _ = assert_ok!(srv.accept().await);
|
||
|
|
}
|
||
|
|
|
||
|
|
#[tokio::test]
|
||
|
|
async fn basic_usage_v6() {
|
||
|
|
// Create server
|
||
|
|
let addr = assert_ok!("[::1]:0".parse());
|
||
|
|
let srv = assert_ok!(TcpSocket::new_v6());
|
||
|
|
assert_ok!(srv.bind(addr));
|
||
|
|
|
||
|
|
let srv = assert_ok!(srv.listen(128));
|
||
|
|
|
||
|
|
// Create client & connect
|
||
|
|
let addr = srv.local_addr().unwrap();
|
||
|
|
let cli = assert_ok!(TcpSocket::new_v6());
|
||
|
|
let _cli = assert_ok!(cli.connect(addr).await);
|
||
|
|
|
||
|
|
// Accept
|
||
|
|
let _ = assert_ok!(srv.accept().await);
|
||
|
|
}
|
||
|
|
|
||
|
|
#[tokio::test]
|
||
|
|
async fn bind_before_connect() {
|
||
|
|
// Create server
|
||
|
|
let any_addr = assert_ok!("127.0.0.1:0".parse());
|
||
|
|
let srv = assert_ok!(TcpSocket::new_v4());
|
||
|
|
assert_ok!(srv.bind(any_addr));
|
||
|
|
|
||
|
|
let srv = assert_ok!(srv.listen(128));
|
||
|
|
|
||
|
|
// Create client & connect
|
||
|
|
let addr = srv.local_addr().unwrap();
|
||
|
|
let cli = assert_ok!(TcpSocket::new_v4());
|
||
|
|
assert_ok!(cli.bind(any_addr));
|
||
|
|
let _cli = assert_ok!(cli.connect(addr).await);
|
||
|
|
|
||
|
|
// Accept
|
||
|
|
let _ = assert_ok!(srv.accept().await);
|
||
|
|
}
|
||
|
|
|
||
|
|
#[tokio::test]
|
||
|
|
async fn basic_linger() {
|
||
|
|
// Create server
|
||
|
|
let addr = assert_ok!("127.0.0.1:0".parse());
|
||
|
|
let srv = assert_ok!(TcpSocket::new_v4());
|
||
|
|
assert_ok!(srv.bind(addr));
|
||
|
|
|
||
|
|
assert!(srv.linger().unwrap().is_none());
|
||
|
|
|
||
|
|
srv.set_zero_linger().unwrap();
|
||
|
|
assert_eq!(srv.linger().unwrap(), Some(Duration::new(0, 0)));
|
||
|
|
}
|
||
|
|
|
||
|
|
/// Macro to create a simple test to set and get a socket option.
|
||
|
|
macro_rules! test {
|
||
|
|
// Test using the `arg`ument as expected return value.
|
||
|
|
($( #[ $attr: meta ] )* $get_fn: ident, $set_fn: ident ( $arg: expr ) ) => {
|
||
|
|
test!($( #[$attr] )* $get_fn, $set_fn($arg), $arg);
|
||
|
|
};
|
||
|
|
($( #[ $attr: meta ] )* $get_fn: ident, $set_fn: ident ( $arg: expr ), $expected: expr ) => {
|
||
|
|
#[test]
|
||
|
|
$( #[$attr] )*
|
||
|
|
fn $get_fn() {
|
||
|
|
test!(__ new_v4, $get_fn, $set_fn($arg), $expected);
|
||
|
|
#[cfg(not(target_os = "vita"))]
|
||
|
|
test!(__ new_v6, $get_fn, $set_fn($arg), $expected);
|
||
|
|
}
|
||
|
|
};
|
||
|
|
// Only test using a IPv4 socket.
|
||
|
|
(IPv4 $get_fn: ident, $set_fn: ident ( $arg: expr ) ) => {
|
||
|
|
#[test]
|
||
|
|
fn $get_fn() {
|
||
|
|
test!(__ new_v4, $get_fn, $set_fn($arg), $arg);
|
||
|
|
}
|
||
|
|
};
|
||
|
|
// Only test using a IPv6 socket.
|
||
|
|
(IPv6 $get_fn: ident, $set_fn: ident ( $arg: expr ) ) => {
|
||
|
|
#[test]
|
||
|
|
fn $get_fn() {
|
||
|
|
test!(__ new_v6, $get_fn, $set_fn($arg), $arg);
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
// Internal to this macro.
|
||
|
|
(__ $constructor: ident, $get_fn: ident, $set_fn: ident ( $arg: expr ), $expected: expr ) => {
|
||
|
|
let socket = TcpSocket::$constructor().expect("failed to create `TcpSocket`");
|
||
|
|
|
||
|
|
let initial = socket.$get_fn().expect("failed to get initial value");
|
||
|
|
let arg = $arg;
|
||
|
|
assert_ne!(initial, arg, "initial value and argument are the same");
|
||
|
|
|
||
|
|
socket.$set_fn(arg).expect("failed to set option");
|
||
|
|
let got = socket.$get_fn().expect("failed to get value");
|
||
|
|
let expected = $expected;
|
||
|
|
assert_eq!(got, expected, "set and get values differ");
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
const SET_BUF_SIZE: u32 = 4096;
|
||
|
|
// Linux doubles the buffer size for kernel usage, and exposes that when
|
||
|
|
// retrieving the buffer size.
|
||
|
|
|
||
|
|
#[cfg(not(any(target_os = "android", target_os = "linux")))]
|
||
|
|
const GET_BUF_SIZE: u32 = SET_BUF_SIZE;
|
||
|
|
|
||
|
|
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||
|
|
const GET_BUF_SIZE: u32 = 2 * SET_BUF_SIZE;
|
||
|
|
|
||
|
|
test!(keepalive, set_keepalive(true));
|
||
|
|
|
||
|
|
test!(reuseaddr, set_reuseaddr(true));
|
||
|
|
|
||
|
|
#[cfg(all(
|
||
|
|
unix,
|
||
|
|
not(target_os = "solaris"),
|
||
|
|
not(target_os = "illumos"),
|
||
|
|
not(target_os = "cygwin"),
|
||
|
|
))]
|
||
|
|
test!(reuseport, set_reuseport(true));
|
||
|
|
|
||
|
|
test!(
|
||
|
|
send_buffer_size,
|
||
|
|
set_send_buffer_size(SET_BUF_SIZE),
|
||
|
|
GET_BUF_SIZE
|
||
|
|
);
|
||
|
|
|
||
|
|
test!(
|
||
|
|
recv_buffer_size,
|
||
|
|
set_recv_buffer_size(SET_BUF_SIZE),
|
||
|
|
GET_BUF_SIZE
|
||
|
|
);
|
||
|
|
|
||
|
|
test!(
|
||
|
|
#[expect(deprecated, reason = "set_linger is deprecated")]
|
||
|
|
linger,
|
||
|
|
set_linger(Some(Duration::from_secs(10)))
|
||
|
|
);
|
||
|
|
|
||
|
|
test!(nodelay, set_nodelay(true));
|
||
|
|
|
||
|
|
#[cfg(any(
|
||
|
|
target_os = "android",
|
||
|
|
target_os = "dragonfly",
|
||
|
|
target_os = "freebsd",
|
||
|
|
target_os = "fuchsia",
|
||
|
|
target_os = "linux",
|
||
|
|
target_os = "macos",
|
||
|
|
target_os = "netbsd",
|
||
|
|
target_os = "openbsd",
|
||
|
|
target_os = "cygwin",
|
||
|
|
))]
|
||
|
|
test!(IPv6 tclass_v6, set_tclass_v6(96));
|
||
|
|
|
||
|
|
#[cfg(not(any(
|
||
|
|
target_os = "fuchsia",
|
||
|
|
target_os = "redox",
|
||
|
|
target_os = "solaris",
|
||
|
|
target_os = "illumos",
|
||
|
|
target_os = "haiku"
|
||
|
|
)))]
|
||
|
|
test!(IPv4 tos_v4, set_tos_v4(96));
|