Commit f1faafd5 authored by Simon McVittie's avatar Simon McVittie

test: Skip TCP tests if getaddrinfo doesn't work

For example, this can be the case in bubblewrap or Debian pbuilder after
unsharing the network namespace:

    bwrap \
    --bind / / \
    --dev-bind /dev /dev \
    --bind /dev/shm /dev/shm \
    --bind /dev/pts /dev/pts \
    --unshare-net \
    ${builddir}/test/test-loopback --tap
    ...
    ok 1 /connect/tcp # SKIP Name resolution does not work here:
    getaddrinfo("127.0.0.1", "0", {flags=ADDRCONFIG, family=INET,
    socktype=STREAM, protocol=TCP}): Name or service not known

On some systems this can be circumvented by using nss_wrapper from
<https://cwrap.org/nss_wrapper.html>:

    cat > hosts <<EOF
    127.0.0.1 localhost
    EOF
    bwrap \
    ... \
    env \
    LD_PRELOAD=libnss_wrapper.so \
    NSS_WRAPPER_HOSTS=$(pwd)/hosts \
    ${builddir}/test/test-loopback --tap
    ...
    # listening at tcp:host=127.0.0.1,port=39219,family=ipv4,guid=...

but for systems where that does't work, we should be prepared to skip
the affected tests.
Signed-off-by: Simon McVittie's avatarSimon McVittie <smcv@collabora.com>
Reviewed-by: Philip Withnall's avatarPhilip Withnall <withnall@endlessm.com>
Bug: https://bugs.freedesktop.org/show_bug.cgi?id=106812
parent 4cfc7de3
......@@ -36,6 +36,7 @@
typedef struct {
DBusError e;
TestMainContext *ctx;
gboolean skip;
DBusServer *server;
DBusConnection *server_conn;
......@@ -85,6 +86,14 @@ setup (Fixture *f,
dbus_error_init (&f->e);
g_queue_init (&f->client_messages);
if ((g_str_has_prefix (addr, "tcp:") ||
g_str_has_prefix (addr, "nonce-tcp:")) &&
!test_check_tcp_works ())
{
f->skip = TRUE;
return;
}
f->server = dbus_server_listen (addr, &f->e);
assert_no_error (&f->e);
g_assert (f->server != NULL);
......@@ -101,6 +110,9 @@ test_connect (Fixture *f,
dbus_bool_t have_mem;
char *address = NULL;
if (f->skip)
return;
g_assert (f->server_conn == NULL);
address = dbus_server_get_address (f->server);
......@@ -129,6 +141,9 @@ test_message (Fixture *f,
dbus_uint32_t serial;
DBusMessage *outgoing, *incoming;
if (f->skip)
return;
test_connect (f, addr);
outgoing = dbus_message_new_signal ("/com/example/Hello",
......@@ -213,6 +228,9 @@ test_corrupt (Fixture *f,
int fd;
DBusMessage *incoming;
if (f->skip)
return;
test_message (f, addr);
dbus_connection_flush (f->server_conn);
......@@ -277,6 +295,9 @@ test_byte_order (Fixture *f,
DBusMessage *message;
dbus_bool_t mem;
if (f->skip)
return;
test_message (f, addr);
message = dbus_message_new_signal ("/", "a.b", "c");
......
......@@ -79,6 +79,7 @@ _DBUS_STATIC_ASSERT (MAX_MESSAGE_UNIX_FDS < TOO_MANY_FDS);
typedef struct {
TestMainContext *ctx;
DBusError e;
gboolean skip;
DBusServer *server;
......@@ -172,6 +173,9 @@ test_connect (Fixture *f,
{
char *address;
if (f->skip)
return;
g_assert (f->left_server_conn == NULL);
g_assert (f->right_server_conn == NULL);
......@@ -251,6 +255,14 @@ setup_common (Fixture *f,
dbus_error_init (&f->e);
g_queue_init (&f->messages);
if ((g_str_has_prefix (address, "tcp:") ||
g_str_has_prefix (address, "nonce-tcp:")) &&
!test_check_tcp_works ())
{
f->skip = TRUE;
return;
}
f->server = dbus_server_listen (address, &f->e);
assert_no_error (&f->e);
g_assert (f->server != NULL);
......@@ -289,6 +301,9 @@ static void
test_unsupported (Fixture *f,
gconstpointer data)
{
if (f->skip)
return;
test_connect (f, FALSE);
if (dbus_connection_can_send_type (f->left_client_conn,
......@@ -321,6 +336,9 @@ test_relay (Fixture *f,
struct stat stat_before;
struct stat stat_after;
if (f->skip)
return;
test_connect (f, TRUE);
outgoing = dbus_message_new_signal ("/com/example/Hello",
......@@ -403,6 +421,9 @@ test_limit (Fixture *f,
DBusMessage *outgoing, *incoming;
int i;
if (f->skip)
return;
test_connect (f, TRUE);
outgoing = dbus_message_new_signal ("/com/example/Hello",
......@@ -461,6 +482,9 @@ test_too_many (Fixture *f,
DBusMessage *outgoing;
unsigned int i;
if (f->skip)
return;
test_connect (f, TRUE);
outgoing = dbus_message_new_signal ("/com/example/Hello",
......@@ -513,6 +537,12 @@ test_too_many_split (Fixture *f,
DBusString buffer;
int fds[TOO_MANY_FDS];
int done;
#ifdef HAVE_GETRLIMIT
struct rlimit lim;
#endif
if (f->skip)
return;
/* This test deliberately pushes up against OS limits, so skip it
* if we don't have enough fds. 4 times the maximum per message
......@@ -520,8 +550,6 @@ test_too_many_split (Fixture *f,
* we actually send, the copy that we potentially receive, and some
* spare capacity for everything else. */
#ifdef HAVE_GETRLIMIT
struct rlimit lim;
if (getrlimit (RLIMIT_NOFILE, &lim) == 0)
{
if (lim.rlim_cur != RLIM_INFINITY &&
......@@ -643,6 +671,9 @@ test_flood (Fixture *f,
DBusMessage *outgoing[SOME_MESSAGES];
dbus_uint32_t serial;
if (f->skip)
return;
test_connect (f, TRUE);
for (j = 0; j < SOME_MESSAGES; j++)
......@@ -715,6 +746,9 @@ test_odd_limit (Fixture *f,
DBusMessage *outgoing;
int i;
if (f->skip)
return;
test_connect (f, TRUE);
dbus_connection_set_max_message_unix_fds (f->left_server_conn, 7);
dbus_connection_set_max_message_unix_fds (f->right_server_conn, 7);
......
......@@ -85,6 +85,11 @@ test_oom_wrapper (gconstpointer data)
{
const OOMTestCase *test = data;
if ((g_str_has_prefix (test->data, "tcp:") ||
g_str_has_prefix (test->data, "nonce-tcp:")) &&
!test_check_tcp_works ())
return;
if (!_dbus_test_oom_handling (test->name, test->function,
(void *) test->data))
{
......
......@@ -41,6 +41,7 @@
typedef struct {
TestMainContext *ctx;
DBusError e;
gboolean skip;
DBusServer *server;
DBusConnection *server_conn;
......@@ -98,6 +99,14 @@ setup (Fixture *f,
dbus_error_init (&f->e);
g_queue_init (&f->server_messages);
if ((g_str_has_prefix (addr, "tcp:") ||
g_str_has_prefix (addr, "nonce-tcp:")) &&
!test_check_tcp_works ())
{
f->skip = TRUE;
return;
}
f->server = dbus_server_listen (addr, &f->e);
assert_no_error (&f->e);
g_assert (f->server != NULL);
......@@ -125,6 +134,9 @@ setup_runtime (Fixture *f,
setup (f, addr);
if (f->skip)
return;
listening_at = dbus_server_get_address (f->server);
g_test_message ("listening at %s", listening_at);
g_assert (g_str_has_prefix (listening_at, "unix:path="));
......@@ -147,6 +159,9 @@ setup_no_runtime (Fixture *f,
setup (f, addr);
if (f->skip)
return;
listening_at = dbus_server_get_address (f->server);
g_test_message ("listening at %s", listening_at);
/* we have fallen back to something in /tmp, either abstract or not */
......@@ -169,6 +184,9 @@ test_connect (Fixture *f,
int n_entries;
dbus_bool_t ok;
if (f->skip)
return;
g_assert (f->server_conn == NULL);
address = dbus_server_get_address (f->server);
......@@ -294,13 +312,17 @@ test_bad_guid (Fixture *f,
gconstpointer addr G_GNUC_UNUSED)
{
DBusMessage *incoming;
char *address = dbus_server_get_address (f->server);
char *address;
gchar *guid;
if (f->skip)
return;
g_test_bug ("39720");
g_assert (f->server_conn == NULL);
address = dbus_server_get_address (f->server);
g_assert (strstr (address, "guid=") != NULL);
guid = strstr (address, "guid=");
g_assert_cmpuint (strlen (guid), >=, 5 + 32);
......@@ -356,6 +378,9 @@ test_message (Fixture *f,
dbus_uint32_t serial;
DBusMessage *outgoing, *incoming;
if (f->skip)
return;
test_connect (f, addr);
outgoing = dbus_message_new_signal ("/com/example/Hello",
......
......@@ -46,6 +46,7 @@
typedef struct {
TestMainContext *ctx;
DBusError e;
gboolean skip;
DBusServer *server;
......@@ -128,6 +129,14 @@ setup (Fixture *f,
dbus_error_init (&f->e);
g_queue_init (&f->messages);
if ((g_str_has_prefix (address, "tcp:") ||
g_str_has_prefix (address, "nonce-tcp:")) &&
!test_check_tcp_works ())
{
f->skip = TRUE;
return;
}
f->server = dbus_server_listen (address, &f->e);
assert_no_error (&f->e);
g_assert (f->server != NULL);
......@@ -144,6 +153,9 @@ test_connect (Fixture *f,
dbus_bool_t have_mem;
char *address;
if (f->skip)
return;
g_assert (f->left_server_conn == NULL);
g_assert (f->right_server_conn == NULL);
......@@ -205,6 +217,9 @@ test_relay (Fixture *f,
{
DBusMessage *incoming;
if (f->skip)
return;
test_connect (f, data);
send_one (f, "First");
......@@ -237,6 +252,9 @@ test_limit (Fixture *f,
DBusMessage *incoming;
guint i;
if (f->skip)
return;
test_connect (f, data);
/* This was an attempt to reproduce fd.o #34393. It didn't work. */
......
......@@ -34,8 +34,10 @@
# include <io.h>
# include <windows.h>
#else
# include <netdb.h>
# include <signal.h>
# include <unistd.h>
# include <sys/socket.h>
# include <sys/types.h>
# include <pwd.h>
#endif
......@@ -762,3 +764,58 @@ test_main_context_call_and_wait (TestMainContext *ctx,
dbus_clear_pending_call (&pc);
return g_steal_pointer (&reply);
}
gboolean
test_check_tcp_works (void)
{
#ifdef DBUS_UNIX
/* In pathological container environments, we might not have a
* working 127.0.0.1 */
int res;
struct addrinfo *addrs = NULL;
struct addrinfo hints;
int saved_errno;
_DBUS_ZERO (hints);
#ifdef AI_ADDRCONFIG
hints.ai_flags |= AI_ADDRCONFIG;
#endif
hints.ai_flags = AI_ADDRCONFIG;
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
res = getaddrinfo ("127.0.0.1", "0", &hints, &addrs);
saved_errno = errno;
if (res != 0)
{
const gchar *system_message;
gchar *skip_message;
#ifdef EAI_SYSTEM
if (res == EAI_SYSTEM)
system_message = g_strerror (saved_errno);
else
#endif
system_message = gai_strerror (res);
skip_message = g_strdup_printf ("Name resolution does not work here: "
"getaddrinfo(\"127.0.0.1\", \"0\", "
"{flags=ADDRCONFIG, family=INET,"
"socktype=STREAM, protocol=TCP}): "
"%s",
system_message);
g_test_skip (skip_message);
free (skip_message);
}
if (addrs != NULL)
freeaddrinfo (addrs);
return (res == 0);
#else
/* Assume that on Windows, TCP always works */
return TRUE;
#endif
}
......@@ -121,4 +121,6 @@ backported_g_steal_pointer (gpointer pointer_to_pointer)
}
#endif
gboolean test_check_tcp_works (void);
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment