@@ -496,7 +496,7 @@ fn udp_pair_connected() -> (Socket, Socket) {
496496}
497497
498498#[ test]
499- fn keepalive ( ) {
499+ fn tcp_keepalive ( ) {
500500 let socket = Socket :: new ( Domain :: IPV4 , Type :: STREAM , None ) . unwrap ( ) ;
501501 let params = TcpKeepalive :: new ( ) . with_time ( Duration :: from_secs ( 200 ) ) ;
502502
@@ -588,3 +588,105 @@ fn device() {
588588 break ;
589589 }
590590}
591+
592+ /// Macro to create a simple test to set and get a socket option.
593+ macro_rules! test {
594+ // Test using the `arg`ument as expected return value.
595+ ( $( #[ $attr: meta ] ) * $get_fn: ident, $set_fn: ident ( $arg: expr ) ) => {
596+ test!( $( #[ $attr] ) * $get_fn, $set_fn( $arg) , $arg) ;
597+ } ;
598+ ( $( #[ $attr: meta ] ) * $get_fn: ident, $set_fn: ident ( $arg: expr ) , $expected: expr ) => {
599+ #[ test]
600+ $( #[ $attr] ) *
601+ fn $get_fn( ) {
602+ test!( __ Domain :: IPV4 , $get_fn, $set_fn( $arg) , $expected) ;
603+ test!( __ Domain :: IPV6 , $get_fn, $set_fn( $arg) , $expected) ;
604+ }
605+ } ;
606+ // Only test using a IPv4 socket.
607+ ( IPv4 $get_fn: ident, $set_fn: ident ( $arg: expr ) ) => {
608+ #[ test]
609+ fn $get_fn( ) {
610+ test!( __ Domain :: IPV4 , $get_fn, $set_fn( $arg) , $arg) ;
611+ }
612+ } ;
613+ // Only test using a IPv6 socket.
614+ ( IPv6 $get_fn: ident, $set_fn: ident ( $arg: expr ) ) => {
615+ #[ test]
616+ fn $get_fn( ) {
617+ test!( __ Domain :: IPV6 , $get_fn, $set_fn( $arg) , $arg) ;
618+ }
619+ } ;
620+
621+ // Internal to this macro.
622+ ( __ $ty: expr, $get_fn: ident, $set_fn: ident ( $arg: expr ) , $expected: expr ) => {
623+ let socket = Socket :: new( $ty, Type :: STREAM , None ) . expect( "failed to create `Socket`" ) ;
624+
625+ let initial = socket. $get_fn( ) . expect( "failed to get initial value" ) ;
626+ let arg = $arg;
627+ let expected = $expected;
628+ assert_ne!( initial, arg, "initial value and argument are the same" ) ;
629+
630+ socket. $set_fn( arg) . expect( "failed to set option" ) ;
631+ let got = socket. $get_fn( ) . expect( "failed to get value" ) ;
632+ assert_eq!( got, expected, "set and get values differ" ) ;
633+ } ;
634+ }
635+
636+ const SET_BUF_SIZE : usize = 4096 ;
637+ // Linux doubles the buffer size for kernel usage, and exposes that when
638+ // retrieving the buffer size.
639+ #[ cfg( not( target_os = "linux" ) ) ]
640+ const GET_BUF_SIZE : usize = SET_BUF_SIZE ;
641+ #[ cfg( target_os = "linux" ) ]
642+ const GET_BUF_SIZE : usize = 2 * SET_BUF_SIZE ;
643+
644+ test ! ( nodelay, set_nodelay( true ) ) ;
645+ test ! (
646+ recv_buffer_size,
647+ set_recv_buffer_size( SET_BUF_SIZE ) ,
648+ GET_BUF_SIZE
649+ ) ;
650+ test ! (
651+ send_buffer_size,
652+ set_send_buffer_size( SET_BUF_SIZE ) ,
653+ GET_BUF_SIZE
654+ ) ;
655+ #[ cfg( not( target_os = "redox" ) ) ]
656+ test ! ( out_of_band_inline, set_out_of_band_inline( true ) ) ;
657+ test ! ( reuse_address, set_reuse_address( true ) ) ;
658+ #[ cfg( all(
659+ feature = "all" ,
660+ not( any( windows, target_os = "solaris" , target_os = "illumos" ) )
661+ ) ) ]
662+ test ! ( reuse_port, set_reuse_port( true ) ) ;
663+ #[ cfg( all( feature = "all" , unix) ) ]
664+ test ! (
665+ #[ cfg_attr( target_os = "linux" , ignore = "Different value returned" ) ]
666+ mss,
667+ set_mss( 256 )
668+ ) ;
669+ #[ cfg( all( feature = "all" , target_os = "linux" ) ) ]
670+ test ! (
671+ #[ ignore = "setting `SO_MARK` requires the `CAP_NET_ADMIN` capability (works when running as root)" ]
672+ mark,
673+ set_mark( 123 )
674+ ) ;
675+ test ! ( linger, set_linger( Some ( Duration :: from_secs( 10 ) ) ) ) ;
676+ test ! (
677+ read_timeout,
678+ set_read_timeout( Some ( Duration :: from_secs( 10 ) ) )
679+ ) ;
680+ test ! ( keepalive, set_keepalive( true ) ) ;
681+ #[ cfg( all( feature = "all" , target_os = "linux" ) ) ]
682+ test ! ( freebind, set_freebind( true ) ) ;
683+
684+ test ! ( IPv4 ttl, set_ttl( 40 ) ) ;
685+ #[ cfg( not( windows) ) ] // TODO: returns `WSAENOPROTOOPT` (10042) on Windows.
686+ test ! ( IPv4 broadcast, set_broadcast( true ) ) ;
687+
688+ test ! ( IPv6 unicast_hops_v6, set_unicast_hops_v6( 20 ) ) ;
689+ #[ cfg( not( windows) ) ]
690+ test ! ( IPv6 only_v6, set_only_v6( true ) ) ;
691+ #[ cfg( windows) ] // IPv6 socket are already IPv6 only on Windows.
692+ test ! ( IPv6 only_v6, set_only_v6( false ) ) ;
0 commit comments