From e19bd552bf19a6af3342dc8f8233c84eb363d46b Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Fri, 1 Jul 2016 15:39:35 +0100 Subject: [PATCH] dbus-daemon test: exercise pending fd timeout test Signed-off-by: Simon McVittie --- configure.ac | 5 +- test/Makefile.am | 3 + .../valid-config-files/pending-fd-timeout.conf.in | 20 ++++ test/dbus-daemon.c | 128 +++++++++++++++++++++ 4 files changed, 155 insertions(+), 1 deletion(-) create mode 100644 test/data/valid-config-files/pending-fd-timeout.conf.in diff --git a/configure.ac b/configure.ac index 1d08030..f7aa6a3 100644 --- a/configure.ac +++ b/configure.ac @@ -246,7 +246,10 @@ with_glib=yes AS_IF([test "x$enable_modular_tests" != xno], [ PKG_CHECK_MODULES([GLIB], [glib-2.0 >= 2.36, gio-2.0 >= 2.36], - [], + [ + AS_IF([test "x$dbus_unix" = xyes], + [PKG_CHECK_MODULES([GIO_UNIX], [gio-unix-2.0])]) + ], [if test "x$enable_modular_tests" = xyes; then AC_MSG_NOTICE([Full test coverage (--enable-modular-tests=yes or --enable-tests=yes) requires GLib]) AC_MSG_ERROR([$GLIB_ERRORS]) diff --git a/test/Makefile.am b/test/Makefile.am index e344e54..07ea280 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -12,6 +12,7 @@ AM_CPPFLAGS = \ $(DBUS_STATIC_BUILD_CPPFLAGS) \ -DDBUS_COMPILATION \ $(GLIB_CFLAGS) \ + $(GIO_UNIX_CFLAGS) \ $(NULL) # improve backtraces from test stuff @@ -220,6 +221,7 @@ test_dbus_daemon_SOURCES = dbus-daemon.c test_dbus_daemon_LDADD = \ libdbus-testutils.la \ $(GLIB_LIBS) \ + $(GIO_UNIX_LIBS) \ $(NULL) test_dbus_daemon_eavesdrop_SOURCES = dbus-daemon-eavesdrop.c @@ -317,6 +319,7 @@ in_data = \ data/valid-config-files/max-names-per-connection.conf.in \ data/valid-config-files/max-replies-per-connection.conf.in \ data/valid-config-files/multi-user.conf.in \ + data/valid-config-files/pending-fd-timeout.conf.in \ data/valid-config-files/systemd-activation.conf.in \ data/invalid-service-files-system/org.freedesktop.DBus.TestSuiteNoExec.service.in \ data/invalid-service-files-system/org.freedesktop.DBus.TestSuiteNoService.service.in \ diff --git a/test/data/valid-config-files/pending-fd-timeout.conf.in b/test/data/valid-config-files/pending-fd-timeout.conf.in new file mode 100644 index 0000000..849d885 --- /dev/null +++ b/test/data/valid-config-files/pending-fd-timeout.conf.in @@ -0,0 +1,20 @@ + + + + + session + @TEST_LISTEN@ + + + + + + + + + + + + 500 + diff --git a/test/dbus-daemon.c b/test/dbus-daemon.c index 0ca6574..029e077 100644 --- a/test/dbus-daemon.c +++ b/test/dbus-daemon.c @@ -34,6 +34,7 @@ #include #include +#include #include "test-utils-glib.h" @@ -42,6 +43,8 @@ #ifdef DBUS_UNIX # include # include + +# include #endif /* Platforms where we know that credentials-passing passes both the @@ -913,6 +916,117 @@ test_max_names_per_connection (Fixture *f, g_assert_cmpint (ret, ==, DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER); } +#if defined(DBUS_UNIX) && defined(HAVE_UNIX_FD_PASSING) + +static DBusHandlerResult +wait_for_disconnected_cb (DBusConnection *client_conn, + DBusMessage *message, + void *data) +{ + gboolean *disconnected = data; + + if (dbus_message_is_signal (message, DBUS_INTERFACE_LOCAL, "Disconnected")) + { + *disconnected = TRUE; + return DBUS_HANDLER_RESULT_HANDLED; + } + + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +static const guchar partial_message[] = +{ + DBUS_LITTLE_ENDIAN, + DBUS_MESSAGE_TYPE_METHOD_CALL, + 0, /* flags */ + 1, /* version */ + 0xff, 0xff, 0, 0, /* length of body = 65535 bytes */ + 1, 2, 3, 4, /* cookie */ + 0xff, 0xff, 0, 0, /* length of header fields array = 65535 bytes */ + 42 /* pretending to be the beginning of the header fields array */ +}; + +static void +send_all_with_fd (GSocket *socket, + const guchar *partial_message, + gsize len, + int fd) +{ + GSocketControlMessage *fdm = g_unix_fd_message_new (); + GError *error = NULL; + gssize sent; + GOutputVector vector = { partial_message, len }; + + g_unix_fd_message_append_fd (G_UNIX_FD_MESSAGE (fdm), fd, &error); + g_assert_no_error (error); + + sent = g_socket_send_message (socket, NULL, &vector, 1, &fdm, 1, + G_SOCKET_MSG_NONE, NULL, &error); + g_assert_no_error (error); + g_assert_cmpint (sent, >=, 1); + g_assert_cmpint (sent, <=, vector.size); + + while (((gsize) sent) < vector.size) + { + vector.size -= sent; + vector.buffer = ((const guchar *) vector.buffer) + sent; + sent = g_socket_send_message (socket, NULL, &vector, 1, NULL, 0, + G_SOCKET_MSG_NONE, NULL, &error); + g_assert_no_error (error); + g_assert_cmpint (sent, >=, 1); + g_assert_cmpint (sent, <=, vector.size); + } + + g_object_unref (fdm); +} + +static void +test_pending_fd_timeout (Fixture *f, + gconstpointer context) +{ + GError *error = NULL; + gint64 start; + int fd; + GSocket *socket; + gboolean have_mem; + gboolean disconnected = FALSE; + + if (f->skip) + return; + + have_mem = dbus_connection_add_filter (f->left_conn, wait_for_disconnected_cb, + &disconnected, NULL); + g_assert (have_mem); + + /* This is not API. Never do this. */ + + if (!dbus_connection_get_socket (f->left_conn, &fd)) + g_error ("failed to steal fd from left connection"); + + socket = g_socket_new_from_fd (fd, &error); + g_assert_no_error (error); + g_assert (socket != NULL); + + /* We send part of a message that contains a fd, then stop. */ + start = g_get_monotonic_time (); + send_all_with_fd (socket, partial_message, G_N_ELEMENTS (partial_message), + fd); + + while (!disconnected) + { + test_progress ('.'); + test_main_context_iterate (f->ctx, TRUE); + + /* It should take no longer than 500ms to get disconnected. We'll + * be generous and allow 1000ms. */ + g_assert_cmpint (g_get_monotonic_time (), <=, start + G_USEC_PER_SEC); + } + + g_object_unref (socket); +} + +#endif + static void teardown (Fixture *f, gconstpointer context G_GNUC_UNUSED) @@ -1022,6 +1136,13 @@ static Config max_names_per_connection_config = { SPECIFY_ADDRESS }; +#if defined(DBUS_UNIX) && defined(HAVE_UNIX_FD_PASSING) +static Config pending_fd_timeout_config = { + NULL, 1, "valid-config-files/pending-fd-timeout.conf", + SPECIFY_ADDRESS +}; +#endif + int main (int argc, char **argv) @@ -1054,6 +1175,13 @@ main (int argc, g_test_add ("/limits/max-names-per-connection", Fixture, &max_names_per_connection_config, setup, test_max_names_per_connection, teardown); + +#if defined(DBUS_UNIX) && defined(HAVE_UNIX_FD_PASSING) + g_test_add ("/limits/pending-fd-timeout", Fixture, + &pending_fd_timeout_config, + setup, test_pending_fd_timeout, teardown); +#endif + #ifdef DBUS_UNIX /* We can't test this in loopback.c with the rest of unix:runtime=yes, * because dbus_bus_get[_private] is the only way to use the default, -- 2.8.1