summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon McVittie <simon.mcvittie@collabora.co.uk>2014-09-15 15:53:20 +0100
committerSimon McVittie <smcv@collabora.com>2018-12-03 15:12:07 +0000
commit869433227a4f54209d0be5f4cbda275394607d73 (patch)
tree229a5d8e7b2d37a9b03652fbfc65e05661a02e7f
parent9c038151b491dead7b9f9ca2d1a70c16417966a0 (diff)
downloaddbus-glib-869433227a4f54209d0be5f4cbda275394607d73.tar.gz
Add a regression test for fd.o#80557
Signed-off-by: Simon McVittie <smcv@collabora.com>
-rw-r--r--test/core/Makefile.am7
-rw-r--r--test/core/my-object.c3
-rw-r--r--test/core/my-object.h1
-rwxr-xr-xtest/core/run-test.sh1
-rw-r--r--test/core/unsupported-type.c334
5 files changed, 346 insertions, 0 deletions
diff --git a/test/core/Makefile.am b/test/core/Makefile.am
index 91c3772..35defa9 100644
--- a/test/core/Makefile.am
+++ b/test/core/Makefile.am
@@ -71,6 +71,7 @@ noinst_PROGRAMS = \
test-proxy-noc \
test-proxy-peer \
test-registrations \
+ test-unsupported-type \
test-variant-recursion \
test-gvariant \
test-shared-bus \
@@ -162,6 +163,12 @@ test_peer_on_bus_SOURCES = peer-on-bus.c
test_shared_bus_SOURCES = shared-bus.c
+test_unsupported_type_SOURCES = \
+ my-object.c \
+ my-object.h \
+ unsupported-type.c \
+ $(NULL)
+
CLEANFILES = \
$(BUILT_SOURCES) \
run-with-tmp-session-bus.conf
diff --git a/test/core/my-object.c b/test/core/my-object.c
index 4a0002e..62cb55a 100644
--- a/test/core/my-object.c
+++ b/test/core/my-object.c
@@ -659,6 +659,9 @@ gboolean
my_object_echo_variant (MyObject *obj, GValue *variant, GValue *ret, GError **error)
{
GType t;
+
+ obj->echo_variant_called++;
+
t = G_VALUE_TYPE(variant);
g_value_init (ret, t);
g_value_copy (variant, ret);
diff --git a/test/core/my-object.h b/test/core/my-object.h
index 416610e..95d84e2 100644
--- a/test/core/my-object.h
+++ b/test/core/my-object.h
@@ -18,6 +18,7 @@ struct MyObject
guint val;
gdouble super_studly;
gboolean should_be_hidden;
+ gsize echo_variant_called;
};
struct MyObjectClass
diff --git a/test/core/run-test.sh b/test/core/run-test.sh
index fe0d3f8..3d01e46 100755
--- a/test/core/run-test.sh
+++ b/test/core/run-test.sh
@@ -52,4 +52,5 @@ else
${DBUS_TOP_BUILDDIR}/libtool --mode=execute $DEBUG $DBUS_TOP_BUILDDIR/test/core/test-private || die "test-private failed"
${DBUS_TOP_BUILDDIR}/libtool --mode=execute $DEBUG $DBUS_TOP_BUILDDIR/test/core/test-error-mapping || die "test-error-mapping failed"
${DBUS_TOP_BUILDDIR}/libtool --mode=execute $DEBUG $DBUS_TOP_BUILDDIR/test/core/test-peer-on-bus || die "test-peer-on-bus failed"
+ ${DBUS_TOP_BUILDDIR}/libtool --mode=execute $DEBUG $DBUS_TOP_BUILDDIR/test/core/test-unsupported-type || die "test-unsupported-type failed"
fi
diff --git a/test/core/unsupported-type.c b/test/core/unsupported-type.c
new file mode 100644
index 0000000..f8dca7c
--- /dev/null
+++ b/test/core/unsupported-type.c
@@ -0,0 +1,334 @@
+/*
+ * Copyright © 2009-2014 Collabora Ltd. <http://www.collabora.co.uk/>
+ * Copyright © 2009-2011 Nokia Corporation
+ *
+ * In preparation for dbus-glib relicensing (if it ever happens), this file is
+ * licensed under (at your option) either the AFL v2.1, the GPL v2 or later,
+ * or an MIT/X11-style license:
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <glib.h>
+#include <glib/gstdio.h>
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+#ifdef G_OS_UNIX
+# include <errno.h>
+# include <fcntl.h>
+# include <sys/stat.h>
+# include <unistd.h>
+#endif
+
+#include "my-object.h"
+
+GMainLoop *loop = NULL;
+
+typedef struct {
+ DBusGConnection *bus;
+ GObject *object;
+ DBusGProxy *proxy;
+ DBusGProxyCall *call;
+ gsize in_flight;
+ int fd;
+} Fixture;
+
+#ifdef G_OS_UNIX
+static void
+call_cb (DBusGProxy *proxy,
+ DBusGProxyCall *call,
+ gpointer user_data)
+{
+ Fixture *f = user_data;
+
+ g_assert (proxy == f->proxy);
+ g_assert (call == f->call);
+
+ f->in_flight--;
+}
+
+static void
+setup (Fixture *f,
+ gconstpointer path_to_use)
+{
+ DBusConnection *libdbus;
+
+ f->bus = dbus_g_bus_get_private (DBUS_BUS_SESSION,
+ g_main_context_default (), NULL);
+ g_assert (f->bus != NULL);
+ libdbus = dbus_g_connection_get_connection (f->bus);
+ dbus_connection_set_exit_on_disconnect (libdbus, FALSE);
+
+ f->object = g_object_new (MY_TYPE_OBJECT, NULL);
+ g_assert (MY_IS_OBJECT (f->object));
+ dbus_g_connection_register_g_object (f->bus, "/object",
+ (GObject *) f->object);
+
+ f->proxy = dbus_g_proxy_new_for_name (f->bus,
+ dbus_bus_get_unique_name (libdbus),
+ "/notdbusglib", "org.freedesktop.DBus.GLib.Tests.Example");
+
+ f->fd = g_open ("/dev/null", O_RDONLY, 0);
+
+ if (f->fd < 0)
+ g_error ("unable to open /dev/null: %s", g_strerror (errno));
+}
+
+static void
+teardown (Fixture *f,
+ gconstpointer test_data G_GNUC_UNUSED)
+{
+ g_clear_object (&f->proxy);
+
+ if (f->object != NULL)
+ {
+ dbus_g_connection_unregister_g_object (f->bus, f->object);
+ g_object_unref (f->object);
+ }
+
+ if (f->bus != NULL)
+ {
+ dbus_connection_close (dbus_g_connection_get_connection (f->bus));
+ dbus_g_connection_unref (f->bus);
+ }
+
+ if (f->fd >= 0)
+ {
+ close (f->fd);
+ f->fd = -1;
+ }
+}
+
+static void
+pending_call_store_reply (DBusPendingCall *pc,
+ void *data)
+{
+ DBusMessage **message_p = data;
+
+ g_assert (*message_p == NULL);
+ *message_p = dbus_pending_call_steal_reply (pc);
+ g_assert (*message_p != NULL);
+}
+
+/*
+ * Exercise a call to a dbus-glib method with an unsupported parameter
+ * type. The only unsupported parameter type we know is 'h', a Unix fd,
+ * which is why this test is Unix-only.
+ */
+static void
+test_call (Fixture *f,
+ gconstpointer test_data G_GNUC_UNUSED)
+{
+ DBusConnection *libdbus = dbus_g_connection_get_connection (f->bus);
+ const char *unique = dbus_bus_get_unique_name (libdbus);
+ DBusMessage *m = dbus_message_new_method_call (unique,
+ "/object", "org.freedesktop.DBus.GLib.Tests.MyObject",
+ "EchoVariant");
+ DBusPendingCall *pc;
+ DBusMessageIter iter;
+ DBusMessageIter var_iter;
+ DBusMessage *reply = NULL;
+
+ if (m == NULL)
+ g_error ("OOM");
+
+ dbus_message_iter_init_append (m, &iter);
+
+ if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_VARIANT,
+ DBUS_TYPE_UNIX_FD_AS_STRING, &var_iter))
+ g_error ("OOM");
+
+ if (!dbus_message_iter_append_basic (&var_iter, DBUS_TYPE_UNIX_FD,
+ &f->fd))
+ {
+ /* FIXME: cannot distinguish between inability to use fd and OOM */
+ dbus_message_iter_abandon_container (&iter, &var_iter);
+ dbus_message_unref (m);
+ g_test_skip ("Unix fd-passing does not appear to be supported");
+ return;
+ }
+
+ if (!dbus_message_iter_close_container (&iter, &var_iter))
+ g_error ("OOM");
+
+ if (!dbus_connection_send_with_reply (libdbus, m, &pc, -1) || pc == NULL)
+ g_error ("OOM");
+
+ if (dbus_pending_call_get_completed (pc))
+ pending_call_store_reply (pc, &reply);
+ else if (!dbus_pending_call_set_notify (pc, pending_call_store_reply,
+ &reply, NULL))
+ g_error ("OOM");
+
+ dbus_message_unref (m);
+
+ while (reply == NULL)
+ g_main_context_iteration (NULL, TRUE);
+
+ dbus_pending_call_unref (pc);
+
+ /* it didn't work */
+#if 0
+ /* this is what it should be */
+ g_assert_cmpstr (dbus_message_get_error_name (reply), ==,
+ DBUS_ERROR_INVALID_SIGNATURE);
+#else
+ /* this is what it is right now */
+ g_assert_cmpstr (dbus_message_get_error_name (reply), ==,
+ "org.freedesktop.DBus.GLib.ErrorError");
+#endif
+ /* it didn't call the into the user-supplied C code */
+ g_assert_cmpuint (MY_OBJECT (f->object)->echo_variant_called, ==, 0);
+
+ dbus_message_unref (reply);
+}
+
+/*
+ * Exercise a call from dbus-glib to a method returning an unsupported
+ * parameter type. Again, the only unsupported parameter type we know is 'h'.
+ */
+static void
+unregister_cb (DBusConnection *conn,
+ void *user_data)
+{
+}
+
+static DBusHandlerResult
+message_cb (DBusConnection *conn,
+ DBusMessage *m,
+ void *user_data)
+{
+ Fixture *f = user_data;
+ DBusMessage *reply = dbus_message_new_method_return (m);
+ DBusMessageIter iter;
+ DBusMessageIter var_iter;
+
+ if (reply == NULL)
+ g_error ("OOM");
+
+ dbus_message_iter_init_append (reply, &iter);
+
+ if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_VARIANT,
+ DBUS_TYPE_UNIX_FD_AS_STRING, &var_iter))
+ g_error ("OOM");
+
+ if (dbus_message_iter_append_basic (&var_iter, DBUS_TYPE_UNIX_FD,
+ &f->fd))
+ {
+ if (!dbus_message_iter_close_container (&iter, &var_iter))
+ g_error ("OOM");
+ }
+ else
+ {
+ /* FIXME: cannot distinguish between inability to use fd and OOM */
+ dbus_message_iter_abandon_container (&iter, &var_iter);
+ dbus_message_unref (reply);
+ reply = dbus_message_new_error (m,
+ DBUS_ERROR_NOT_SUPPORTED, "Unable to append Unix fd");
+
+ if (reply == NULL)
+ g_error ("OOM");
+ }
+
+ if (!dbus_connection_send (conn, reply, NULL))
+ g_error ("OOM");
+
+ return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static DBusObjectPathVTable vtable = {
+ unregister_cb,
+ message_cb,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+static void
+test_ret (Fixture *f,
+ gconstpointer test_data G_GNUC_UNUSED)
+{
+ DBusConnection *libdbus = dbus_g_connection_get_connection (f->bus);
+ GError *error = NULL;
+ GValue value;
+
+ dbus_connection_register_object_path (libdbus, "/notdbusglib",
+ &vtable, f);
+
+ f->in_flight = 1;
+ f->call = dbus_g_proxy_begin_call (f->proxy, "ReturnUnixFd",
+ call_cb, f, NULL,
+ G_TYPE_INVALID);
+
+ while (f->in_flight > 0)
+ g_main_context_iteration (NULL, TRUE);
+
+ if (dbus_g_proxy_end_call (f->proxy, f->call, &error,
+ G_TYPE_VALUE, &value,
+ G_TYPE_INVALID))
+ {
+ g_error ("that shouldn't have worked!");
+ }
+
+ if (g_error_matches (error, DBUS_GERROR, DBUS_GERROR_NOT_SUPPORTED))
+ {
+ g_test_skip ("couldn't send a Unix fd");
+ }
+ else
+ {
+ g_assert_error (error, DBUS_GERROR, DBUS_GERROR_INVALID_ARGS);
+ }
+
+ g_clear_error (&error);
+ dbus_connection_unregister_object_path (libdbus, "/notdbusglib");
+}
+#endif
+
+int
+main (int argc,
+ char **argv)
+{
+ g_type_init ();
+ dbus_g_type_specialized_init ();
+
+ g_test_init (&argc, &argv, NULL);
+
+#ifdef G_OS_UNIX
+ g_test_add ("/unsupported-type/call",
+ Fixture, NULL, setup, test_call, teardown);
+ g_test_add ("/unsupported-type/ret",
+ Fixture, NULL, setup, test_ret, teardown);
+#endif
+
+ return g_test_run ();
+}