diff options
| author | Dirk Engling <erdgeist@erdgeist.org> | 2026-10-25 18:51:51 +0100 |
|---|---|---|
| committer | Dirk Engling <erdgeist@erdgeist.org> | 2026-10-25 18:51:51 +0100 |
| commit | 2c7659ec930277981b6333b5b3aff7840d11933c (patch) | |
| tree | 1c363ce905ef1a62395f398335a94a47916af278 /tests/t_socket.c | |
| parent | 632960a33eb8d23925b2bbef24d5065de7280aef (diff) | |
Decouple config parsing from binding and worker spawning
* Options are parsed now into a listener description list before
binding them at once and starting the workers later
* UDP workers can now be configured per connection
* socket reuse is now done more sensibly, mcast sockets always
reused
* Hold-off logic after spawning udp workers removed
Diffstat (limited to 'tests/t_socket.c')
| -rw-r--r-- | tests/t_socket.c | 34 |
1 files changed, 15 insertions, 19 deletions
diff --git a/tests/t_socket.c b/tests/t_socket.c index bbc9e5e..8eef7fd 100644 --- a/tests/t_socket.c +++ b/tests/t_socket.c | |||
| @@ -91,14 +91,14 @@ static void case_socket_options(void) { | |||
| 91 | int udp, tcp; | 91 | int udp, tcp; |
| 92 | 92 | ||
| 93 | test_case("a bound udp socket is non blocking and serves both families"); | 93 | test_case("a bound udp socket is non blocking and serves both families"); |
| 94 | udp = socket_udp_bind(ip_any, 0); | 94 | udp = socket_udp_bind(ip_any, 0, SOCKET_EXCLUSIVE); |
| 95 | CHECK(udp != -1); | 95 | CHECK(udp != -1); |
| 96 | CHECK_INT(is_nonblocking(udp), 1); | 96 | CHECK_INT(is_nonblocking(udp), 1); |
| 97 | CHECK_INT(sock_flag(udp, IPPROTO_IPV6, IPV6_V6ONLY), 0); | 97 | CHECK_INT(sock_flag(udp, IPPROTO_IPV6, IPV6_V6ONLY), 0); |
| 98 | close(udp); | 98 | close(udp); |
| 99 | 99 | ||
| 100 | test_case("a listening tcp socket is non blocking and serves both families"); | 100 | test_case("a listening tcp socket is non blocking and serves both families"); |
| 101 | tcp = socket_tcp_listen(ip_any, 0); | 101 | tcp = socket_tcp_listen(ip_any, 0, SOCKET_EXCLUSIVE); |
| 102 | CHECK(tcp != -1); | 102 | CHECK(tcp != -1); |
| 103 | CHECK_INT(is_nonblocking(tcp), 1); | 103 | CHECK_INT(is_nonblocking(tcp), 1); |
| 104 | CHECK_INT(sock_flag(tcp, IPPROTO_IPV6, IPV6_V6ONLY), 0); | 104 | CHECK_INT(sock_flag(tcp, IPPROTO_IPV6, IPV6_V6ONLY), 0); |
| @@ -106,24 +106,20 @@ static void case_socket_options(void) { | |||
| 106 | } | 106 | } |
| 107 | 107 | ||
| 108 | #ifdef SO_REUSEPORT | 108 | #ifdef SO_REUSEPORT |
| 109 | static void case_reuseport_is_opt_in(void) { | 109 | static void case_sharing_is_opt_in(void) { |
| 110 | int s; | 110 | int s; |
| 111 | 111 | ||
| 112 | test_case("reuseport stays off unless the operator asks for it"); | 112 | test_case("an address is exclusive unless sharing is asked for"); |
| 113 | g_socket_reuseport = 0; | 113 | s = socket_udp_bind(ip_loopback, 0, SOCKET_EXCLUSIVE); |
| 114 | s = socket_udp_bind(ip_loopback, 0); | ||
| 115 | CHECK(s != -1); | 114 | CHECK(s != -1); |
| 116 | CHECK_INT(sock_flag(s, SOL_SOCKET, SO_REUSEPORT), 0); | 115 | CHECK_INT(sock_flag(s, SOL_SOCKET, SO_REUSEPORT), 0); |
| 117 | close(s); | 116 | close(s); |
| 118 | 117 | ||
| 119 | test_case("reuseport reaches the socket when it is asked for"); | 118 | test_case("and shared when it is"); |
| 120 | g_socket_reuseport = 1; | 119 | s = socket_udp_bind(ip_loopback, 0, SOCKET_SHARED); |
| 121 | s = socket_udp_bind(ip_loopback, 0); | ||
| 122 | CHECK(s != -1); | 120 | CHECK(s != -1); |
| 123 | CHECK_INT(sock_flag(s, SOL_SOCKET, SO_REUSEPORT), 1); | 121 | CHECK_INT(sock_flag(s, SOL_SOCKET, SO_REUSEPORT), 1); |
| 124 | close(s); | 122 | close(s); |
| 125 | |||
| 126 | g_socket_reuseport = 0; | ||
| 127 | } | 123 | } |
| 128 | #endif | 124 | #endif |
| 129 | 125 | ||
| @@ -135,7 +131,7 @@ static void case_udp_roundtrip(void) { | |||
| 135 | int s; | 131 | int s; |
| 136 | 132 | ||
| 137 | test_case("a datagram comes back with the sender's address and port"); | 133 | test_case("a datagram comes back with the sender's address and port"); |
| 138 | s = socket_udp_bind(ip_loopback, 0); | 134 | s = socket_udp_bind(ip_loopback, 0, SOCKET_EXCLUSIVE); |
| 139 | CHECK(s != -1); | 135 | CHECK(s != -1); |
| 140 | bound_address(s, own_ip, &own_port); | 136 | bound_address(s, own_ip, &own_port); |
| 141 | CHECK(own_port != 0); | 137 | CHECK(own_port != 0); |
| @@ -158,9 +154,9 @@ static void case_udp_v4mapped(void) { | |||
| 158 | int receiver, sender; | 154 | int receiver, sender; |
| 159 | 155 | ||
| 160 | test_case("an IPv4 sender is reported in its v4 mapped form"); | 156 | test_case("an IPv4 sender is reported in its v4 mapped form"); |
| 161 | receiver = socket_udp_bind(ip_v4_loopback, 0); | 157 | receiver = socket_udp_bind(ip_v4_loopback, 0, SOCKET_EXCLUSIVE); |
| 162 | CHECK(receiver != -1); | 158 | CHECK(receiver != -1); |
| 163 | sender = socket_udp_bind(ip_v4_loopback, 0); | 159 | sender = socket_udp_bind(ip_v4_loopback, 0, SOCKET_EXCLUSIVE); |
| 164 | CHECK(sender != -1); | 160 | CHECK(sender != -1); |
| 165 | bound_address(receiver, receiver_ip, &receiver_port); | 161 | bound_address(receiver, receiver_ip, &receiver_port); |
| 166 | bound_address(sender, sender_ip, &sender_port); | 162 | bound_address(sender, sender_ip, &sender_port); |
| @@ -184,7 +180,7 @@ static void case_tcp_roundtrip(void) { | |||
| 184 | int listener, client, accepted; | 180 | int listener, client, accepted; |
| 185 | 181 | ||
| 186 | test_case("a connection is accepted and carries the caller's address"); | 182 | test_case("a connection is accepted and carries the caller's address"); |
| 187 | listener = socket_tcp_listen(ip_loopback, 0); | 183 | listener = socket_tcp_listen(ip_loopback, 0, SOCKET_EXCLUSIVE); |
| 188 | CHECK(listener != -1); | 184 | CHECK(listener != -1); |
| 189 | bound_address(listener, listener_ip, &listener_port); | 185 | bound_address(listener, listener_ip, &listener_port); |
| 190 | CHECK(listener_port != 0); | 186 | CHECK(listener_port != 0); |
| @@ -216,7 +212,7 @@ static void case_connect_refused(void) { | |||
| 216 | 212 | ||
| 217 | test_case("a refused connection is reported by socket_is_connected"); | 213 | test_case("a refused connection is reported by socket_is_connected"); |
| 218 | /* Take a port, then drop it, so nothing is listening on it any more */ | 214 | /* Take a port, then drop it, so nothing is listening on it any more */ |
| 219 | listener = socket_tcp_listen(ip_loopback, 0); | 215 | listener = socket_tcp_listen(ip_loopback, 0, SOCKET_EXCLUSIVE); |
| 220 | CHECK(listener != -1); | 216 | CHECK(listener != -1); |
| 221 | bound_address(listener, listener_ip, &port); | 217 | bound_address(listener, listener_ip, &port); |
| 222 | close(listener); | 218 | close(listener); |
| @@ -247,8 +243,8 @@ static void case_bind_failure(void) { | |||
| 247 | test_case("binding an address no interface carries fails"); | 243 | test_case("binding an address no interface carries fails"); |
| 248 | before = next_descriptor(); | 244 | before = next_descriptor(); |
| 249 | CHECK(before != -1); | 245 | CHECK(before != -1); |
| 250 | CHECK_INT(socket_tcp_listen(ip_unassigned, 0), -1); | 246 | CHECK_INT(socket_tcp_listen(ip_unassigned, 0, SOCKET_EXCLUSIVE), -1); |
| 251 | CHECK_INT(socket_udp_bind(ip_unassigned, 0), -1); | 247 | CHECK_INT(socket_udp_bind(ip_unassigned, 0, SOCKET_EXCLUSIVE), -1); |
| 252 | 248 | ||
| 253 | test_case("a failed bind leaves no socket behind"); | 249 | test_case("a failed bind leaves no socket behind"); |
| 254 | CHECK_INT(next_descriptor(), before); | 250 | CHECK_INT(next_descriptor(), before); |
| @@ -294,7 +290,7 @@ static void case_mcast_sender(void) { | |||
| 294 | void test_socket(void) { | 290 | void test_socket(void) { |
| 295 | case_socket_options(); | 291 | case_socket_options(); |
| 296 | #ifdef SO_REUSEPORT | 292 | #ifdef SO_REUSEPORT |
| 297 | case_reuseport_is_opt_in(); | 293 | case_sharing_is_opt_in(); |
| 298 | #endif | 294 | #endif |
| 299 | case_udp_roundtrip(); | 295 | case_udp_roundtrip(); |
| 300 | case_udp_v4mapped(); | 296 | case_udp_v4mapped(); |
