qemu/tests/qtest/netdev-socket.c
Peter Maydell 417296c8d8 tests/qtest/netdev-socket: Raise connection timeout to 60 seconds
The netdev-socket test intermittently fails on our s390x CI runner:

633/659 ERROR:../tests/qtest/netdev-socket.c:197:test_stream_unix:
assertion failed (resp == expect): ("st0: index=0,type=stream,connection error\r\n" == "st0: index=0,type=stream,unix:/tmp/netdev-socket.GZUG01/stream_unix\r\n")
ERROR
633/659 qemu:qtest+qtest-xtensa / qtest-xtensa/netdev-socket
ERROR           5.47s   killed by signal 6 SIGABRT

This may just be because when the machine is under heavy load
running the CI tests it hits the timeout before the QEMU
under test has started to the point of being able to respond
to HMP queries.

Bump the timeout to 60 seconds to see if the intermittent
goes away.

Acked-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 20230207165119.1479132-1-peter.maydell@linaro.org
2023-02-09 11:23:53 +00:00

449 lines
12 KiB
C

/*
* QTest testcase for netdev stream and dgram
*
* Copyright (c) 2022 Red Hat, Inc.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "qemu/osdep.h"
#include "qemu/sockets.h"
#include <glib/gstdio.h>
#include "../unit/socket-helpers.h"
#include "libqtest.h"
#define CONNECTION_TIMEOUT 60
#define EXPECT_STATE(q, e, t) \
do { \
char *resp = NULL; \
g_test_timer_start(); \
do { \
g_free(resp); \
resp = qtest_hmp(q, "info network"); \
if (t) { \
strrchr(resp, t)[0] = 0; \
} \
if (g_str_equal(resp, e)) { \
break; \
} \
} while (g_test_timer_elapsed() < CONNECTION_TIMEOUT); \
g_assert_cmpstr(resp, ==, e); \
g_free(resp); \
} while (0)
static gchar *tmpdir;
static int inet_get_free_port_socket_ipv4(int sock)
{
struct sockaddr_in addr;
socklen_t len;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = 0;
if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
return -1;
}
len = sizeof(addr);
if (getsockname(sock, (struct sockaddr *)&addr, &len) < 0) {
return -1;
}
return ntohs(addr.sin_port);
}
static int inet_get_free_port_socket_ipv6(int sock)
{
struct sockaddr_in6 addr;
socklen_t len;
memset(&addr, 0, sizeof(addr));
addr.sin6_family = AF_INET6;
addr.sin6_addr = in6addr_any;
addr.sin6_port = 0;
if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
return -1;
}
len = sizeof(addr);
if (getsockname(sock, (struct sockaddr *)&addr, &len) < 0) {
return -1;
}
return ntohs(addr.sin6_port);
}
static int inet_get_free_port_multiple(int nb, int *port, bool ipv6)
{
int sock[nb];
int i;
for (i = 0; i < nb; i++) {
sock[i] = socket(ipv6 ? AF_INET6 : AF_INET, SOCK_STREAM, 0);
if (sock[i] < 0) {
break;
}
port[i] = ipv6 ? inet_get_free_port_socket_ipv6(sock[i]) :
inet_get_free_port_socket_ipv4(sock[i]);
if (port[i] == -1) {
break;
}
}
nb = i;
for (i = 0; i < nb; i++) {
closesocket(sock[i]);
}
return nb;
}
static int inet_get_free_port(bool ipv6)
{
int nb, port;
nb = inet_get_free_port_multiple(1, &port, ipv6);
g_assert_cmpint(nb, ==, 1);
return port;
}
static void test_stream_inet_ipv4(void)
{
QTestState *qts0, *qts1;
char *expect;
int port;
port = inet_get_free_port(false);
qts0 = qtest_initf("-nodefaults -M none "
"-netdev stream,id=st0,server=true,addr.type=inet,"
"addr.ipv4=on,addr.ipv6=off,"
"addr.host=127.0.0.1,addr.port=%d", port);
EXPECT_STATE(qts0, "st0: index=0,type=stream,\r\n", 0);
qts1 = qtest_initf("-nodefaults -M none "
"-netdev stream,server=false,id=st0,addr.type=inet,"
"addr.ipv4=on,addr.ipv6=off,"
"addr.host=127.0.0.1,addr.port=%d", port);
expect = g_strdup_printf("st0: index=0,type=stream,tcp:127.0.0.1:%d\r\n",
port);
EXPECT_STATE(qts1, expect, 0);
g_free(expect);
/* the port is unknown, check only the address */
EXPECT_STATE(qts0, "st0: index=0,type=stream,tcp:127.0.0.1", ':');
qtest_quit(qts1);
qtest_quit(qts0);
}
static void test_stream_inet_ipv6(void)
{
QTestState *qts0, *qts1;
char *expect;
int port;
port = inet_get_free_port(true);
qts0 = qtest_initf("-nodefaults -M none "
"-netdev stream,id=st0,server=true,addr.type=inet,"
"addr.ipv4=off,addr.ipv6=on,"
"addr.host=::1,addr.port=%d", port);
EXPECT_STATE(qts0, "st0: index=0,type=stream,\r\n", 0);
qts1 = qtest_initf("-nodefaults -M none "
"-netdev stream,server=false,id=st0,addr.type=inet,"
"addr.ipv4=off,addr.ipv6=on,"
"addr.host=::1,addr.port=%d", port);
expect = g_strdup_printf("st0: index=0,type=stream,tcp:::1:%d\r\n",
port);
EXPECT_STATE(qts1, expect, 0);
g_free(expect);
/* the port is unknown, check only the address */
EXPECT_STATE(qts0, "st0: index=0,type=stream,tcp:::1", ':');
qtest_quit(qts1);
qtest_quit(qts0);
}
static void test_stream_unix(void)
{
QTestState *qts0, *qts1;
char *expect;
gchar *path;
path = g_strconcat(tmpdir, "/stream_unix", NULL);
qts0 = qtest_initf("-nodefaults -M none "
"-netdev stream,id=st0,server=true,"
"addr.type=unix,addr.path=%s,",
path);
EXPECT_STATE(qts0, "st0: index=0,type=stream,\r\n", 0);
qts1 = qtest_initf("-nodefaults -M none "
"-netdev stream,id=st0,server=false,"
"addr.type=unix,addr.path=%s",
path);
expect = g_strdup_printf("st0: index=0,type=stream,unix:%s\r\n", path);
EXPECT_STATE(qts1, expect, 0);
EXPECT_STATE(qts0, expect, 0);
g_free(expect);
g_free(path);
qtest_quit(qts1);
qtest_quit(qts0);
}
#ifdef CONFIG_LINUX
static void test_stream_unix_abstract(void)
{
QTestState *qts0, *qts1;
char *expect;
gchar *path;
path = g_strconcat(tmpdir, "/stream_unix_abstract", NULL);
qts0 = qtest_initf("-nodefaults -M none "
"-netdev stream,id=st0,server=true,"
"addr.type=unix,addr.path=%s,"
"addr.abstract=on",
path);
EXPECT_STATE(qts0, "st0: index=0,type=stream,\r\n", 0);
qts1 = qtest_initf("-nodefaults -M none "
"-netdev stream,id=st0,server=false,"
"addr.type=unix,addr.path=%s,addr.abstract=on",
path);
expect = g_strdup_printf("st0: index=0,type=stream,unix:%s\r\n", path);
EXPECT_STATE(qts1, expect, 0);
EXPECT_STATE(qts0, expect, 0);
g_free(expect);
g_free(path);
qtest_quit(qts1);
qtest_quit(qts0);
}
#endif
#ifndef _WIN32
static void test_stream_fd(void)
{
QTestState *qts0, *qts1;
int sock[2];
int ret;
ret = socketpair(AF_LOCAL, SOCK_STREAM, 0, sock);
g_assert_true(ret == 0);
qts0 = qtest_initf("-nodefaults -M none "
"-netdev stream,id=st0,addr.type=fd,addr.str=%d",
sock[0]);
EXPECT_STATE(qts0, "st0: index=0,type=stream,unix:\r\n", 0);
qts1 = qtest_initf("-nodefaults -M none "
"-netdev stream,id=st0,addr.type=fd,addr.str=%d",
sock[1]);
EXPECT_STATE(qts1, "st0: index=0,type=stream,unix:\r\n", 0);
EXPECT_STATE(qts0, "st0: index=0,type=stream,unix:\r\n", 0);
qtest_quit(qts1);
qtest_quit(qts0);
closesocket(sock[0]);
closesocket(sock[1]);
}
#endif
static void test_dgram_inet(void)
{
QTestState *qts0, *qts1;
char *expect;
int port[2];
int nb;
nb = inet_get_free_port_multiple(2, port, false);
g_assert_cmpint(nb, ==, 2);
qts0 = qtest_initf("-nodefaults -M none "
"-netdev dgram,id=st0,"
"local.type=inet,local.host=127.0.0.1,local.port=%d,"
"remote.type=inet,remote.host=127.0.0.1,remote.port=%d",
port[0], port[1]);
expect = g_strdup_printf("st0: index=0,type=dgram,"
"udp=127.0.0.1:%d/127.0.0.1:%d\r\n",
port[0], port[1]);
EXPECT_STATE(qts0, expect, 0);
g_free(expect);
qts1 = qtest_initf("-nodefaults -M none "
"-netdev dgram,id=st0,"
"local.type=inet,local.host=127.0.0.1,local.port=%d,"
"remote.type=inet,remote.host=127.0.0.1,remote.port=%d",
port[1], port[0]);
expect = g_strdup_printf("st0: index=0,type=dgram,"
"udp=127.0.0.1:%d/127.0.0.1:%d\r\n",
port[1], port[0]);
EXPECT_STATE(qts1, expect, 0);
g_free(expect);
qtest_quit(qts1);
qtest_quit(qts0);
}
#ifndef _WIN32
static void test_dgram_mcast(void)
{
QTestState *qts;
qts = qtest_initf("-nodefaults -M none "
"-netdev dgram,id=st0,"
"remote.type=inet,remote.host=230.0.0.1,remote.port=1234");
EXPECT_STATE(qts, "st0: index=0,type=dgram,mcast=230.0.0.1:1234\r\n", 0);
qtest_quit(qts);
}
static void test_dgram_unix(void)
{
QTestState *qts0, *qts1;
char *expect;
gchar *path0, *path1;
path0 = g_strconcat(tmpdir, "/dgram_unix0", NULL);
path1 = g_strconcat(tmpdir, "/dgram_unix1", NULL);
qts0 = qtest_initf("-nodefaults -M none "
"-netdev dgram,id=st0,local.type=unix,local.path=%s,"
"remote.type=unix,remote.path=%s",
path0, path1);
expect = g_strdup_printf("st0: index=0,type=dgram,udp=%s:%s\r\n",
path0, path1);
EXPECT_STATE(qts0, expect, 0);
g_free(expect);
qts1 = qtest_initf("-nodefaults -M none "
"-netdev dgram,id=st0,local.type=unix,local.path=%s,"
"remote.type=unix,remote.path=%s",
path1, path0);
expect = g_strdup_printf("st0: index=0,type=dgram,udp=%s:%s\r\n",
path1, path0);
EXPECT_STATE(qts1, expect, 0);
g_free(expect);
unlink(path0);
g_free(path0);
unlink(path1);
g_free(path1);
qtest_quit(qts1);
qtest_quit(qts0);
}
static void test_dgram_fd(void)
{
QTestState *qts0, *qts1;
char *expect;
int ret;
int sv[2];
ret = socketpair(PF_UNIX, SOCK_DGRAM, 0, sv);
g_assert_cmpint(ret, !=, -1);
qts0 = qtest_initf("-nodefaults -M none "
"-netdev dgram,id=st0,local.type=fd,local.str=%d",
sv[0]);
expect = g_strdup_printf("st0: index=0,type=dgram,fd=%d unix\r\n", sv[0]);
EXPECT_STATE(qts0, expect, 0);
g_free(expect);
qts1 = qtest_initf("-nodefaults -M none "
"-netdev dgram,id=st0,local.type=fd,local.str=%d",
sv[1]);
expect = g_strdup_printf("st0: index=0,type=dgram,fd=%d unix\r\n", sv[1]);
EXPECT_STATE(qts1, expect, 0);
g_free(expect);
qtest_quit(qts1);
qtest_quit(qts0);
closesocket(sv[0]);
closesocket(sv[1]);
}
#endif
int main(int argc, char **argv)
{
int ret;
bool has_ipv4, has_ipv6, has_afunix;
g_autoptr(GError) err = NULL;
socket_init();
g_test_init(&argc, &argv, NULL);
if (socket_check_protocol_support(&has_ipv4, &has_ipv6) < 0) {
g_error("socket_check_protocol_support() failed\n");
}
tmpdir = g_dir_make_tmp("netdev-socket.XXXXXX", &err);
if (tmpdir == NULL) {
g_error("Can't create temporary directory in %s: %s",
g_get_tmp_dir(), err->message);
}
if (has_ipv4) {
qtest_add_func("/netdev/stream/inet/ipv4", test_stream_inet_ipv4);
qtest_add_func("/netdev/dgram/inet", test_dgram_inet);
#ifndef _WIN32
qtest_add_func("/netdev/dgram/mcast", test_dgram_mcast);
#endif
}
if (has_ipv6) {
qtest_add_func("/netdev/stream/inet/ipv6", test_stream_inet_ipv6);
}
socket_check_afunix_support(&has_afunix);
if (has_afunix) {
#ifndef _WIN32
qtest_add_func("/netdev/dgram/unix", test_dgram_unix);
#endif
qtest_add_func("/netdev/stream/unix", test_stream_unix);
#ifdef CONFIG_LINUX
qtest_add_func("/netdev/stream/unix/abstract",
test_stream_unix_abstract);
#endif
#ifndef _WIN32
qtest_add_func("/netdev/stream/fd", test_stream_fd);
qtest_add_func("/netdev/dgram/fd", test_dgram_fd);
#endif
}
ret = g_test_run();
g_rmdir(tmpdir);
g_free(tmpdir);
return ret;
}