Add regression test for keepalive and tcp nodelay

This commit is contained in:
jiangjianfeng
2024-12-05 06:31:19 +00:00
committed by Tate, Hongliang Tian
parent 74a59206d7
commit 8b07a68e9e

View File

@ -6,22 +6,58 @@
#include <netinet/in.h> #include <netinet/in.h>
#include <netinet/tcp.h> #include <netinet/tcp.h>
#include <unistd.h> #include <unistd.h>
#include <arpa/inet.h>
#include "test.h" #include "test.h"
int sockfd; int sk_unbound;
int option; int sk_listen;
int sk_connected;
int sk_accepted;
struct sockaddr_in listen_addr;
#define LISTEN_PORT htons(0x1242)
FN_SETUP(general) FN_SETUP(general)
{ {
sockfd = CHECK(socket(AF_INET, SOCK_STREAM, 0)); sk_unbound = CHECK(socket(AF_INET, SOCK_STREAM, 0));
listen_addr.sin_family = AF_INET;
listen_addr.sin_port = LISTEN_PORT;
CHECK(inet_aton("127.0.0.1", &listen_addr.sin_addr));
sk_listen = CHECK(socket(AF_INET, SOCK_STREAM, 0));
CHECK(bind(sk_listen, (struct sockaddr *)&listen_addr,
sizeof(listen_addr)));
CHECK(listen(sk_listen, 3));
sk_connected = CHECK(socket(AF_INET, SOCK_STREAM, 0));
CHECK(connect(sk_connected, (struct sockaddr *)&listen_addr,
sizeof(listen_addr)));
sk_accepted = CHECK(accept(sk_listen, NULL, NULL));
} }
END_SETUP() END_SETUP()
int refresh_connection()
{
close(sk_connected);
close(sk_accepted);
sk_connected = CHECK(socket(AF_INET, SOCK_STREAM, 0));
CHECK(connect(sk_connected, (struct sockaddr *)&listen_addr,
sizeof(listen_addr)));
sk_accepted = CHECK(accept(sk_listen, NULL, NULL));
return 0;
}
FN_TEST(buffer_size) FN_TEST(buffer_size)
{ {
int sendbuf; int sendbuf;
socklen_t sendbuf_len = sizeof(sendbuf); socklen_t sendbuf_len = sizeof(sendbuf);
TEST_RES(getsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, &sendbuf,
TEST_RES(getsockopt(sk_unbound, SOL_SOCKET, SO_SNDBUF, &sendbuf,
&sendbuf_len), &sendbuf_len),
sendbuf_len == sizeof(sendbuf)); sendbuf_len == sizeof(sendbuf));
} }
@ -31,39 +67,166 @@ FN_TEST(socket_error)
{ {
int error; int error;
socklen_t error_len = sizeof(error); socklen_t error_len = sizeof(error);
TEST_RES(getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &error_len),
TEST_RES(getsockopt(sk_unbound, SOL_SOCKET, SO_ERROR, &error,
&error_len),
error_len == sizeof(error) && error == 0); error_len == sizeof(error) && error == 0);
} }
END_TEST() END_TEST()
FN_TEST(nagle) FN_TEST(nagle)
{ {
// Disable Nagle algorithm int option = 1;
option = 1;
CHECK(setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &option,
sizeof(option)));
// Get new value
int nagle; int nagle;
socklen_t nagle_len = sizeof(nagle); socklen_t nagle_len = sizeof(nagle);
TEST_RES(getsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &nagle,
// 1. Check default values
refresh_connection();
TEST_RES(getsockopt(sk_connected, IPPROTO_TCP, TCP_NODELAY, &nagle,
&nagle_len),
nagle == 0);
TEST_RES(getsockopt(sk_accepted, IPPROTO_TCP, TCP_NODELAY, &nagle,
&nagle_len),
nagle == 0);
// 2. Disable Nagle algorithm on unbound socket
CHECK(setsockopt(sk_unbound, IPPROTO_TCP, TCP_NODELAY, &option,
sizeof(option)));
TEST_RES(getsockopt(sk_unbound, IPPROTO_TCP, TCP_NODELAY, &nagle,
&nagle_len), &nagle_len),
nagle == 1); nagle == 1);
// 3. Disable Nagle algorithm on connected socket
CHECK(setsockopt(sk_connected, IPPROTO_TCP, TCP_NODELAY, &option,
sizeof(option)));
TEST_RES(getsockopt(sk_connected, IPPROTO_TCP, TCP_NODELAY, &nagle,
&nagle_len),
nagle == 1);
// 4. Disable Nagle algorithm on listening socket before connection
CHECK(setsockopt(sk_listen, IPPROTO_TCP, TCP_NODELAY, &option,
sizeof(option)));
TEST_RES(getsockopt(sk_listen, IPPROTO_TCP, TCP_NODELAY, &nagle,
&nagle_len),
nagle == 1);
refresh_connection();
TEST_RES(getsockopt(sk_connected, IPPROTO_TCP, TCP_NODELAY, &nagle,
&nagle_len),
nagle == 0);
TEST_RES(getsockopt(sk_accepted, IPPROTO_TCP, TCP_NODELAY, &nagle,
&nagle_len),
nagle == 1);
// 5. Disable Nagle algorithm on listening socket after connection
option = 0;
CHECK(setsockopt(sk_listen, IPPROTO_TCP, TCP_NODELAY, &option,
sizeof(option)));
close(sk_connected);
close(sk_accepted);
sk_connected = CHECK(socket(AF_INET, SOCK_STREAM, 0));
CHECK(connect(sk_connected, (struct sockaddr *)&listen_addr,
sizeof(listen_addr)));
option = 1;
CHECK(setsockopt(sk_listen, IPPROTO_TCP, TCP_NODELAY, &option,
sizeof(option)));
sk_accepted = CHECK(accept(sk_listen, NULL, NULL));
TEST_RES(getsockopt(sk_connected, IPPROTO_TCP, TCP_NODELAY, &nagle,
&nagle_len),
nagle == 0);
TEST_RES(getsockopt(sk_accepted, IPPROTO_TCP, TCP_NODELAY, &nagle,
&nagle_len),
nagle == 0);
} }
END_TEST() END_TEST()
FN_TEST(reuseaddr) FN_TEST(reuseaddr)
{ {
// Enable reuse address int option = 1;
option = 1; CHECK(setsockopt(sk_unbound, SOL_SOCKET, SO_REUSEADDR, &option,
CHECK(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &option,
sizeof(option))); sizeof(option)));
// Get new value
int reuseaddr; int reuseaddr;
socklen_t reuseaddr_len = sizeof(reuseaddr); socklen_t reuseaddr_len = sizeof(reuseaddr);
TEST_RES(getsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr,
TEST_RES(getsockopt(sk_unbound, SOL_SOCKET, SO_REUSEADDR, &reuseaddr,
&reuseaddr_len), &reuseaddr_len),
reuseaddr == 1); reuseaddr == 1);
} }
END_TEST() END_TEST()
FN_TEST(keepalive)
{
int option = 1;
int keepalive;
socklen_t keepalive_len = sizeof(keepalive);
// 1. Check default values
refresh_connection();
TEST_RES(getsockopt(sk_connected, SOL_SOCKET, SO_KEEPALIVE, &keepalive,
&keepalive_len),
keepalive == 0);
TEST_RES(getsockopt(sk_accepted, SOL_SOCKET, SO_KEEPALIVE, &keepalive,
&keepalive_len),
keepalive == 0);
// 2. Enable keepalive on unbound socket
CHECK(setsockopt(sk_unbound, SOL_SOCKET, SO_KEEPALIVE, &option,
sizeof(option)));
TEST_RES(getsockopt(sk_unbound, SOL_SOCKET, SO_KEEPALIVE, &keepalive,
&keepalive_len),
keepalive == 1);
// 3. Enable keepalive on connected socket
CHECK(setsockopt(sk_connected, SOL_SOCKET, SO_KEEPALIVE, &option,
sizeof(option)));
TEST_RES(getsockopt(sk_connected, SOL_SOCKET, SO_KEEPALIVE, &keepalive,
&keepalive_len),
keepalive == 1);
// 4. Enable keepalive on listening socket
CHECK(setsockopt(sk_listen, SOL_SOCKET, SO_KEEPALIVE, &option,
sizeof(option)));
TEST_RES(getsockopt(sk_listen, SOL_SOCKET, SO_KEEPALIVE, &keepalive,
&keepalive_len),
keepalive == 1);
refresh_connection();
TEST_RES(getsockopt(sk_connected, SOL_SOCKET, SO_KEEPALIVE, &keepalive,
&keepalive_len),
keepalive == 0);
TEST_RES(getsockopt(sk_accepted, SOL_SOCKET, SO_KEEPALIVE, &keepalive,
&keepalive_len),
keepalive == 1);
// 5. Setting keepalive after connection comes
option = 0;
CHECK(setsockopt(sk_listen, SOL_SOCKET, SO_KEEPALIVE, &option,
sizeof(option)));
close(sk_connected);
close(sk_accepted);
sk_connected = CHECK(socket(AF_INET, SOCK_STREAM, 0));
CHECK(connect(sk_connected, (struct sockaddr *)&listen_addr,
sizeof(listen_addr)));
option = 1;
CHECK(setsockopt(sk_listen, SOL_SOCKET, SO_KEEPALIVE, &option,
sizeof(option)));
sk_accepted = CHECK(accept(sk_listen, NULL, NULL));
TEST_RES(getsockopt(sk_connected, SOL_SOCKET, SO_KEEPALIVE, &keepalive,
&keepalive_len),
keepalive == 0);
TEST_RES(getsockopt(sk_accepted, SOL_SOCKET, SO_KEEPALIVE, &keepalive,
&keepalive_len),
keepalive == 0);
}
END_TEST()