summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon McVittie <simon.mcvittie@collabora.co.uk>2014-03-14 18:53:53 +0000
committerSimon McVittie <simon.mcvittie@collabora.co.uk>2014-03-14 18:53:53 +0000
commit7f1c862760f371f66b0483f2dae11cd23be2de39 (patch)
tree352e5e65ac599c765f0a8574bd5d793c37c88b66
parent881e23643166d7519969f6ab53dda2231035fbc1 (diff)
parentd30d68dbb9e013cd002923608d34b8af3e1fe522 (diff)
Merge branch 'gdbus-prep2' into next
Reviewed-by: Guillaume Desmottes Bug: https://bugs.freedesktop.org/show_bug.cgi?id=76120
-rw-r--r--telepathy-glib/Makefile.am1
-rw-r--r--telepathy-glib/core-util.c183
-rw-r--r--telepathy-glib/proxy.c6
-rw-r--r--telepathy-glib/util.c148
-rw-r--r--tests/dbus/call-cancellation.c333
-rw-r--r--tests/dbus/connection.c7
-rw-r--r--tests/dbus/disconnection.c356
-rw-r--r--tests/dbus/unsupported-interface.c5
-rw-r--r--tests/dbus/with-properties.xml9
-rw-r--r--tests/lib/util.c6
-rw-r--r--tools/glib-client-gen.py50
-rw-r--r--tools/glib-ginterface-gen.py12
-rw-r--r--tools/libglibcodegen.py22
-rw-r--r--tools/libtpcodegen.py10
14 files changed, 650 insertions, 498 deletions
diff --git a/telepathy-glib/Makefile.am b/telepathy-glib/Makefile.am
index 4d2ba3438..fd16a958c 100644
--- a/telepathy-glib/Makefile.am
+++ b/telepathy-glib/Makefile.am
@@ -190,6 +190,7 @@ libtelepathy_glib_core_internal_la_LIBADD = $(ALL_LIBS)
libtelepathy_glib_core_internal_la_SOURCES = \
core-dbus.c \
core-proxy.c \
+ core-util.c \
errors.c \
$(NULL)
diff --git a/telepathy-glib/core-util.c b/telepathy-glib/core-util.c
new file mode 100644
index 000000000..91f4cb610
--- /dev/null
+++ b/telepathy-glib/core-util.c
@@ -0,0 +1,183 @@
+/*
+ * util.c - Source for telepathy-glib utility functions
+ * Copyright © 2006-2014 Collabora Ltd. <http://www.collabora.co.uk/>
+ * Copyright © 2006-2008 Nokia Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <config.h>
+#include <telepathy-glib/util.h>
+
+#include <string.h>
+#include <gobject/gvaluecollector.h>
+
+#include <telepathy-glib/defs.h>
+
+/* this is the core library, we don't have debug infrastructure yet */
+#define CRITICAL(format, ...) \
+ g_log (G_LOG_DOMAIN "/misc", G_LOG_LEVEL_CRITICAL, "%s: " format, \
+ G_STRFUNC, ##__VA_ARGS__)
+#define WARNING(format, ...) \
+ g_log (G_LOG_DOMAIN "/misc", G_LOG_LEVEL_WARNING, "%s: " format, \
+ G_STRFUNC, ##__VA_ARGS__)
+
+/**
+ * tp_value_array_build: (skip)
+ * @length: The number of elements that should be in the array
+ * @type: The type of the first argument.
+ * @...: The value of the first item in the struct followed by a list of type,
+ * value pairs terminated by G_TYPE_INVALID.
+ *
+ * Creates a new #GValueArray for use with structs, containing the values
+ * passed in as parameters. The values are copied or reffed as appropriate for
+ * their type.
+ *
+ * <example>
+ * <title> using tp_value_array_build</title>
+ * <programlisting>
+ * GValueArray *array = tp_value_array_build (2,
+ * G_TYPE_STRING, host,
+ * G_TYPE_UINT, port,
+ * G_TYPE_INVALID);
+ * </programlisting>
+ * </example>
+ *
+ * Returns: a newly created #GValueArray, free with tp_value_array_free()
+ *
+ * Since: 0.9.2
+ */
+GValueArray *
+tp_value_array_build (gsize length,
+ GType type,
+ ...)
+{
+ GValueArray *arr;
+ GType t;
+ va_list var_args;
+ char *error = NULL;
+
+ G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+ arr = g_value_array_new (length);
+ G_GNUC_END_IGNORE_DEPRECATIONS
+
+ va_start (var_args, type);
+
+ for (t = type; t != G_TYPE_INVALID; t = va_arg (var_args, GType))
+ {
+ GValue *v = arr->values + arr->n_values;
+
+ G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+ g_value_array_append (arr, NULL);
+ G_GNUC_END_IGNORE_DEPRECATIONS
+
+ g_value_init (v, t);
+
+ G_VALUE_COLLECT (v, var_args, 0, &error);
+
+ if (error != NULL)
+ {
+ CRITICAL ("%s", error);
+ g_free (error);
+
+ tp_value_array_free (arr);
+ va_end (var_args);
+ return NULL;
+ }
+ }
+
+ g_warn_if_fail (arr->n_values == length);
+
+ va_end (var_args);
+ return arr;
+}
+
+/**
+ * tp_value_array_unpack: (skip)
+ * @array: the array to unpack
+ * @len: The number of elements that should be in the array
+ * @...: a list of correctly typed pointers to store the values in
+ *
+ * Unpacks a #GValueArray into separate variables.
+ *
+ * The contents of the values aren't copied into the variables, and so become
+ * invalid when @array is freed.
+ *
+ * <example>
+ * <title>using tp_value_array_unpack</title>
+ * <programlisting>
+ * const gchar *host;
+ * guint port;
+ *
+ * tp_value_array_unpack (array, 2,
+ * &host,
+ * &port);
+ * </programlisting>
+ * </example>
+ *
+ * Since: 0.11.0
+ */
+void
+tp_value_array_unpack (GValueArray *array,
+ gsize len,
+ ...)
+{
+ va_list var_args;
+ guint i;
+
+ va_start (var_args, len);
+
+ for (i = 0; i < len; i++)
+ {
+ GValue *value;
+ char *error = NULL;
+
+ if (G_UNLIKELY (i > array->n_values))
+ {
+ WARNING ("More parameters than entries in the struct!");
+ break;
+ }
+
+ G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+ value = g_value_array_get_nth (array, i);
+ G_GNUC_END_IGNORE_DEPRECATIONS
+
+ G_VALUE_LCOPY (value, var_args, G_VALUE_NOCOPY_CONTENTS, &error);
+ if (error != NULL)
+ {
+ WARNING ("%s", error);
+ g_free (error);
+ break;
+ }
+ }
+
+ va_end (var_args);
+}
+
+/**
+ * tp_value_array_free:
+ * @va: a #GValueArray
+ *
+ * Free @va. This is exactly the same as g_value_array_free(), but does not
+ * provoke deprecation warnings from GLib when used in conjunction with
+ * tp_value_array_build() and tp_value_array_unpack().
+ *
+ * Since: 0.23.0
+ */
+void
+(tp_value_array_free) (GValueArray *va)
+{
+ _tp_value_array_free_inline (va);
+}
diff --git a/telepathy-glib/proxy.c b/telepathy-glib/proxy.c
index 8db1cf461..ed57d80b2 100644
--- a/telepathy-glib/proxy.c
+++ b/telepathy-glib/proxy.c
@@ -383,8 +383,6 @@ struct _TpProxyPrivate {
* completed */
guint pending_will_announce_calls;
- gboolean dispose_has_run;
-
TpClientFactory *factory;
};
@@ -1114,10 +1112,6 @@ tp_proxy_dispose (GObject *object)
GError e = { TP_DBUS_ERRORS, TP_DBUS_ERROR_PROXY_UNREFERENCED,
"Proxy unreferenced" };
- if (self->priv->dispose_has_run)
- return;
- self->priv->dispose_has_run = TRUE;
-
DEBUG ("%p", self);
tp_proxy_invalidate (self, &e);
diff --git a/telepathy-glib/util.c b/telepathy-glib/util.c
index 0018a38a7..6f5f5110c 100644
--- a/telepathy-glib/util.c
+++ b/telepathy-glib/util.c
@@ -919,138 +919,6 @@ _tp_quark_array_copy (const GQuark *quarks)
}
/**
- * tp_value_array_build: (skip)
- * @length: The number of elements that should be in the array
- * @type: The type of the first argument.
- * @...: The value of the first item in the struct followed by a list of type,
- * value pairs terminated by G_TYPE_INVALID.
- *
- * Creates a new #GValueArray for use with structs, containing the values
- * passed in as parameters. The values are copied or reffed as appropriate for
- * their type.
- *
- * <example>
- * <title> using tp_value_array_build</title>
- * <programlisting>
- * GValueArray *array = tp_value_array_build (2,
- * G_TYPE_STRING, host,
- * G_TYPE_UINT, port,
- * G_TYPE_INVALID);
- * </programlisting>
- * </example>
- *
- * Returns: a newly created #GValueArray, free with tp_value_array_free()
- *
- * Since: 0.9.2
- */
-GValueArray *
-tp_value_array_build (gsize length,
- GType type,
- ...)
-{
- GValueArray *arr;
- GType t;
- va_list var_args;
- char *error = NULL;
-
- G_GNUC_BEGIN_IGNORE_DEPRECATIONS
- arr = g_value_array_new (length);
- G_GNUC_END_IGNORE_DEPRECATIONS
-
- va_start (var_args, type);
-
- for (t = type; t != G_TYPE_INVALID; t = va_arg (var_args, GType))
- {
- GValue *v = arr->values + arr->n_values;
-
- G_GNUC_BEGIN_IGNORE_DEPRECATIONS
- g_value_array_append (arr, NULL);
- G_GNUC_END_IGNORE_DEPRECATIONS
-
- g_value_init (v, t);
-
- G_VALUE_COLLECT (v, var_args, 0, &error);
-
- if (error != NULL)
- {
- CRITICAL ("%s", error);
- g_free (error);
-
- tp_value_array_free (arr);
- va_end (var_args);
- return NULL;
- }
- }
-
- g_warn_if_fail (arr->n_values == length);
-
- va_end (var_args);
- return arr;
-}
-
-/**
- * tp_value_array_unpack: (skip)
- * @array: the array to unpack
- * @len: The number of elements that should be in the array
- * @...: a list of correctly typed pointers to store the values in
- *
- * Unpacks a #GValueArray into separate variables.
- *
- * The contents of the values aren't copied into the variables, and so become
- * invalid when @array is freed.
- *
- * <example>
- * <title>using tp_value_array_unpack</title>
- * <programlisting>
- * const gchar *host;
- * guint port;
- *
- * tp_value_array_unpack (array, 2,
- * &host,
- * &port);
- * </programlisting>
- * </example>
- *
- * Since: 0.11.0
- */
-void
-tp_value_array_unpack (GValueArray *array,
- gsize len,
- ...)
-{
- va_list var_args;
- guint i;
-
- va_start (var_args, len);
-
- for (i = 0; i < len; i++)
- {
- GValue *value;
- char *error = NULL;
-
- if (G_UNLIKELY (i > array->n_values))
- {
- WARNING ("More parameters than entries in the struct!");
- break;
- }
-
- G_GNUC_BEGIN_IGNORE_DEPRECATIONS
- value = g_value_array_get_nth (array, i);
- G_GNUC_END_IGNORE_DEPRECATIONS
-
- G_VALUE_LCOPY (value, var_args, G_VALUE_NOCOPY_CONTENTS, &error);
- if (error != NULL)
- {
- WARNING ("%s", error);
- g_free (error);
- break;
- }
- }
-
- va_end (var_args);
-}
-
-/**
* TpWeakRef:
*
* A simple wrapper for a weak reference to a #GObject, suitable for use in
@@ -1935,19 +1803,3 @@ _tp_g_list_copy_deep (GList *list,
return ret;
}
-
-/**
- * tp_value_array_free:
- * @va: a #GValueArray
- *
- * Free @va. This is exactly the same as g_value_array_free(), but does not
- * provoke deprecation warnings from GLib when used in conjunction with
- * tp_value_array_build() and tp_value_array_unpack().
- *
- * Since: 0.23.0
- */
-void
-(tp_value_array_free) (GValueArray *va)
-{
- _tp_value_array_free_inline (va);
-}
diff --git a/tests/dbus/call-cancellation.c b/tests/dbus/call-cancellation.c
index b54223d21..8b4ab3245 100644
--- a/tests/dbus/call-cancellation.c
+++ b/tests/dbus/call-cancellation.c
@@ -1,5 +1,8 @@
#include "config.h"
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
#include <telepathy-glib/cli-misc.h>
#include <telepathy-glib/dbus.h>
#include <telepathy-glib/debug.h>
@@ -10,6 +13,7 @@
#include <telepathy-glib/util.h>
#include "tests/lib/myassert.h"
+#include "tests/lib/simple-channel-dispatcher.h"
#include "tests/lib/stub-object.h"
#include "tests/lib/util.h"
@@ -17,19 +21,6 @@
#define PTR(ui) GUINT_TO_POINTER(ui)
/* state tracking */
-static GMainLoop *mainloop;
-static TpDBusDaemon *a;
-static TpDBusDaemon *b;
-static TpDBusDaemon *c;
-static TpDBusDaemon *d;
-static TpDBusDaemon *e;
-static TpDBusDaemon *f;
-static TpDBusDaemon *g;
-static TpDBusDaemon *h;
-static TpDBusDaemon *i;
-static TpDBusDaemon *j;
-static TpDBusDaemon *k;
-static TpDBusDaemon *z;
static TpIntset *method_ok;
static TpIntset *method_error;
static TpIntset *freed_user_data;
@@ -51,9 +42,23 @@ enum {
TEST_J,
TEST_K,
TEST_Z = 25,
- N_DAEMONS
+ N_PROXIES
};
+typedef struct {
+ TpDBusDaemon *dbus_daemon;
+ TpProxy *proxies[N_PROXIES];
+ GObject *cd_service;
+
+ DBusConnection *private_libdbus;
+ DBusGConnection *private_dbusglib;
+ TpDBusDaemon *private_dbus_daemon;
+
+ gboolean had_last_reply;
+} Fixture;
+
+static Fixture *f;
+
static void
destroy_user_data (gpointer user_data)
{
@@ -79,30 +84,30 @@ k_stub_destroyed (gpointer data,
}
static void
-listed_names (TpDBusDaemon *proxy,
- const gchar **names,
- const GError *error,
- gpointer user_data,
- GObject *weak_object)
+method_cb (TpProxy *proxy,
+ GHashTable *props,
+ const GError *error,
+ gpointer user_data,
+ GObject *weak_object)
{
guint which = GPOINTER_TO_UINT (user_data);
- TpDBusDaemon *want_proxy = NULL;
+ TpProxy *want_proxy = NULL;
GObject *want_object = NULL;
if (error == NULL)
{
- g_message ("ListNames() succeeded (first name: %s), according to "
- "user_data this was on proxy #%d '%c'", *names, which, 'a' + which);
+ g_message ("GetAll() succeeded, according to "
+ "user_data this was on proxy #%d '%c'", which, 'a' + which);
tp_intset_add (method_ok, which);
+ want_proxy = f->proxies[which];
+
switch (which)
{
case TEST_A:
- want_proxy = a;
- want_object = (GObject *) z;
+ want_object = (GObject *) f->proxies[TEST_Z];
break;
case TEST_C:
- want_proxy = c;
want_object = NULL;
break;
case TEST_D:
@@ -114,8 +119,7 @@ listed_names (TpDBusDaemon *proxy,
want_object = (GObject *) copy_of_g;
break;
case TEST_Z:
- want_proxy = z;
- want_object = (GObject *) a;
+ want_object = (GObject *) f->proxies[TEST_A];
break;
default:
MYASSERT (FALSE, ": %c (%p) method call succeeded, which shouldn't "
@@ -125,20 +129,19 @@ listed_names (TpDBusDaemon *proxy,
}
else
{
- g_message ("ListNames() failed (%s), according to "
- "user_data this was on proxy #%d '%c'", error->message,
+ g_message ("GetAll() failed, according to "
+ "user_data this was on proxy #%d '%c'",
which, 'a' + which);
tp_intset_add (method_error, which);
+ want_proxy = f->proxies[which];
+ want_object = NULL;
+
switch (which)
{
case TEST_C:
- want_proxy = c;
- want_object = NULL;
break;
case TEST_F:
- want_proxy = f;
- want_object = NULL;
break;
default:
MYASSERT (FALSE, ": %c (%p) method call failed, which shouldn't "
@@ -152,70 +155,120 @@ listed_names (TpDBusDaemon *proxy,
weak_object, want_object);
if (which == TEST_Z)
- g_main_loop_quit (mainloop);
+ f->had_last_reply = TRUE;
}
static void
-noc (TpDBusDaemon *proxy,
- const gchar *name,
- const gchar *old,
- const gchar *new,
+signal_cb (TpProxy *proxy,
+ const gchar *iface,
+ GHashTable *changed,
+ const gchar **invalidated,
gpointer user_data,
GObject *weak_object)
{
/* do nothing */
}
+static void
+setup (void)
+{
+ f->dbus_daemon = tp_tests_dbus_daemon_dup_or_die ();
+
+ /* Any random object with an interface: what matters is that it can
+ * accept a method call and emit a signal. We use the Properties
+ * interface here. */
+ f->cd_service = tp_tests_object_new_static_class (
+ TP_TESTS_TYPE_SIMPLE_CHANNEL_DISPATCHER,
+ NULL);
+ tp_dbus_daemon_register_object (f->dbus_daemon, "/", f->cd_service);
+
+ f->private_libdbus = dbus_bus_get_private (DBUS_BUS_STARTER, NULL);
+ g_assert (f->private_libdbus != NULL);
+ dbus_connection_setup_with_g_main (f->private_libdbus, NULL);
+ dbus_connection_set_exit_on_disconnect (f->private_libdbus, FALSE);
+ f->private_dbusglib = dbus_connection_get_g_connection (
+ f->private_libdbus);
+ dbus_g_connection_ref (f->private_dbusglib);
+ f->private_dbus_daemon = tp_dbus_daemon_new (f->private_dbusglib);
+ g_assert (f->private_dbus_daemon != NULL);
+}
+
+static void
+drop_private_connection (void)
+{
+ dbus_g_connection_unref (f->private_dbusglib);
+ f->private_dbusglib = NULL;
+ dbus_connection_close (f->private_libdbus);
+ dbus_connection_unref (f->private_libdbus);
+ f->private_libdbus = NULL;
+}
+
+static void
+teardown (void)
+{
+ tp_tests_assert_last_unref (&f->cd_service);
+ tp_tests_assert_last_unref (&f->dbus_daemon);
+
+ tp_tests_assert_last_unref (&f->private_dbus_daemon);
+}
+
+static TpProxy *
+new_proxy (int which)
+{
+ TpDBusDaemon *local_dbus_daemon;
+
+ if (which == TEST_F)
+ local_dbus_daemon = f->private_dbus_daemon;
+ else
+ local_dbus_daemon = f->dbus_daemon;
+
+ return tp_tests_object_new_static_class (TP_TYPE_PROXY,
+ "dbus-daemon", local_dbus_daemon,
+ "bus-name", tp_dbus_daemon_get_unique_name (f->dbus_daemon),
+ "object-path", "/",
+ NULL);
+}
+
int
main (int argc,
char **argv)
{
+ Fixture fixture = { NULL };
GObject *b_stub, *i_stub, *j_stub, *k_stub;
GError err = { TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "Because I said so" };
TpProxyPendingCall *pc;
- gpointer tmp_obj;
+ guint i;
tp_tests_abort_after (10);
tp_debug_set_flags ("all");
- freed_user_data = tp_intset_sized_new (N_DAEMONS);
- method_ok = tp_intset_sized_new (N_DAEMONS);
- method_error = tp_intset_sized_new (N_DAEMONS);
+ freed_user_data = tp_intset_sized_new (N_PROXIES);
+ method_ok = tp_intset_sized_new (N_PROXIES);
+ method_error = tp_intset_sized_new (N_PROXIES);
- mainloop = g_main_loop_new (NULL, FALSE);
+ /* it's on the stack, but it's valid until we leave main(), which will
+ * do for now... one day this test should use GTest, but this might
+ * not be that day */
+ f = &fixture;
+
+ setup ();
- /* We use TpDBusDaemon because it's a convenient concrete subclass of
- * TpProxy. */
g_message ("Creating proxies");
- a = tp_tests_dbus_daemon_dup_or_die ();
- g_message ("a=%p", a);
- b = tp_dbus_daemon_new (tp_proxy_get_dbus_connection (a));
- g_message ("b=%p", b);
- c = tp_dbus_daemon_new (tp_proxy_get_dbus_connection (a));
- g_message ("c=%p", c);
- d = tp_dbus_daemon_new (tp_proxy_get_dbus_connection (a));
- g_message ("d=%p", d);
- e = tp_dbus_daemon_new (tp_proxy_get_dbus_connection (a));
- g_message ("e=%p", e);
- f = tp_dbus_daemon_new (tp_proxy_get_dbus_connection (a));
- g_message ("f=%p", f);
- g = tp_dbus_daemon_new (tp_proxy_get_dbus_connection (a));
- g_message ("g=%p", g);
- h = tp_dbus_daemon_new (tp_proxy_get_dbus_connection (a));
- g_message ("h=%p", h);
- i = tp_dbus_daemon_new (tp_proxy_get_dbus_connection (a));
- g_message ("i=%p", i);
- j = tp_dbus_daemon_new (tp_proxy_get_dbus_connection (a));
- g_message ("j=%p", j);
- k = tp_dbus_daemon_new (tp_proxy_get_dbus_connection (a));
- g_message ("k=%p", k);
- z = tp_dbus_daemon_new (tp_proxy_get_dbus_connection (a));
- g_message ("z=%p", z);
+
+ for (i = TEST_A; i <= TEST_K; i++)
+ {
+ f->proxies[i] = new_proxy (i);
+ g_message ("%c=%p", 'a' + i, f->proxies[i]);
+ }
+
+ f->proxies[TEST_Z] = new_proxy (TEST_Z);
+ g_message ("z=%p", f->proxies[TEST_Z]);
/* a survives */
g_message ("Starting call on a");
- tp_cli_dbus_daemon_call_list_names (a, -1, listed_names, PTR (TEST_A),
- destroy_user_data, (GObject *) z);
+ tp_cli_dbus_properties_call_get_all (f->proxies[TEST_A], -1,
+ TP_IFACE_CHANNEL_DISPATCHER, method_cb, PTR (TEST_A),
+ destroy_user_data, (GObject *) f->proxies[TEST_Z]);
MYASSERT (!tp_intset_is_member (freed_user_data, TEST_A), "");
MYASSERT (!tp_intset_is_member (method_ok, TEST_A), "");
MYASSERT (!tp_intset_is_member (method_error, TEST_A), "");
@@ -225,21 +278,23 @@ main (int argc,
b_stub = tp_tests_object_new_static_class (tp_tests_stub_object_get_type (),
NULL);
g_message ("Starting call on b");
- tp_cli_dbus_daemon_call_list_names (b, -1, listed_names, PTR (TEST_B),
+ tp_cli_dbus_properties_call_get_all (f->proxies[TEST_B], -1,
+ TP_IFACE_CHANNEL_DISPATCHER, method_cb, PTR (TEST_B),
destroy_user_data, b_stub);
MYASSERT (!tp_intset_is_member (freed_user_data, TEST_B), "");
- g_object_unref (b_stub);
+ tp_tests_assert_last_unref (&b_stub);
MYASSERT (!tp_intset_is_member (method_ok, TEST_B), "");
MYASSERT (!tp_intset_is_member (method_error, TEST_B), "");
/* c is explicitly invalidated for an application-specific reason,
* but its call still proceeds */
g_message ("Starting call on c");
- tp_cli_dbus_daemon_call_list_names (c, -1, listed_names, PTR (TEST_C),
+ tp_cli_dbus_properties_call_get_all (f->proxies[TEST_C], -1,
+ TP_IFACE_CHANNEL_DISPATCHER, method_cb, PTR (TEST_C),
destroy_user_data, NULL);
MYASSERT (!tp_intset_is_member (freed_user_data, TEST_C), "");
g_message ("Forcibly invalidating c");
- tp_proxy_invalidate ((TpProxy *) c, &err);
+ tp_proxy_invalidate (f->proxies[TEST_C], &err);
MYASSERT (!tp_intset_is_member (freed_user_data, TEST_C), "");
MYASSERT (!tp_intset_is_member (method_ok, TEST_C), "");
MYASSERT (!tp_intset_is_member (method_error, TEST_C), "");
@@ -247,14 +302,14 @@ main (int argc,
/* d gets unreferenced, but survives long enough for the call to complete
* successfully later, because the pending call holds a reference */
g_message ("Starting call on d");
- tp_cli_dbus_daemon_call_list_names (d, -1, listed_names, PTR (TEST_D),
+ tp_cli_dbus_properties_call_get_all (f->proxies[TEST_D], -1,
+ TP_IFACE_CHANNEL_DISPATCHER, method_cb, PTR (TEST_D),
destroy_user_data, NULL);
MYASSERT (!tp_intset_is_member (freed_user_data, TEST_D), "");
g_message ("Unreferencing d");
- copy_of_d = d;
+ copy_of_d = f->proxies[TEST_D];
g_object_add_weak_pointer (copy_of_d, &copy_of_d);
- g_object_unref (d);
- d = NULL;
+ g_clear_object (&f->proxies[TEST_D]);
MYASSERT (copy_of_d != NULL, "");
MYASSERT (!tp_intset_is_member (freed_user_data, TEST_D), "");
MYASSERT (!tp_intset_is_member (method_ok, TEST_D), "");
@@ -262,7 +317,8 @@ main (int argc,
/* e gets its method call cancelled explicitly */
g_message ("Starting call on e");
- pc = tp_cli_dbus_daemon_call_list_names (e, -1, listed_names, PTR (TEST_E),
+ pc = tp_cli_dbus_properties_call_get_all (f->proxies[TEST_E], -1,
+ TP_IFACE_CHANNEL_DISPATCHER, method_cb, PTR (TEST_E),
destroy_user_data, NULL);
MYASSERT (!tp_intset_is_member (freed_user_data, TEST_E), "");
g_message ("Cancelling call on e");
@@ -271,24 +327,12 @@ main (int argc,
MYASSERT (!tp_intset_is_member (method_error, TEST_E), "");
/* f's method call fails with an error, because it's implicitly
- * invalidated by its DBusGProxy being destroyed.
- *
- * Note that this test case exploits implementation details of dbus-glib.
- * If it stops working after a dbus-glib upgrade, that's probably why. */
+ * invalidated by its own connection disconnecting. */
g_message ("Starting call on f");
- tp_cli_dbus_daemon_call_list_names (f, -1, listed_names, PTR (TEST_F),
+ tp_cli_dbus_properties_call_get_all (f->proxies[TEST_F], -1,
+ TP_IFACE_CHANNEL_DISPATCHER, method_cb, PTR (TEST_F),
destroy_user_data, NULL);
MYASSERT (!tp_intset_is_member (freed_user_data, TEST_F), "");
- g_message ("Forcibly disposing f's DBusGProxy to simulate name owner loss");
- tmp_obj = tp_proxy_get_interface_by_id ((TpProxy *) f,
- TP_IFACE_QUARK_DBUS_DAEMON, NULL);
- MYASSERT (tmp_obj != NULL, "");
- g_object_run_dispose (tmp_obj);
- /* the callback will be queued (to avoid reentrancy), so we don't get it
- * until the main loop runs */
- MYASSERT (!tp_intset_is_member (freed_user_data, TEST_F), "");
- MYASSERT (!tp_intset_is_member (method_ok, TEST_F), "");
- MYASSERT (!tp_intset_is_member (method_error, TEST_F), "");
/* g gets unreferenced, but survives long enough for the call to complete
* successfully later, because the pending call holds a reference;
@@ -296,14 +340,14 @@ main (int argc,
* proxy. This is never necessary, but is an interesting corner case that
* should be tested. */
g_message ("Starting call on g");
- tp_cli_dbus_daemon_call_list_names (g, -1, listed_names, PTR (TEST_G),
- destroy_user_data, (GObject *) g);
+ tp_cli_dbus_properties_call_get_all (f->proxies[TEST_G], -1,
+ TP_IFACE_CHANNEL_DISPATCHER, method_cb, PTR (TEST_G),
+ destroy_user_data, (GObject *) f->proxies[TEST_G]);
MYASSERT (!tp_intset_is_member (freed_user_data, TEST_G), "");
g_message ("Unreferencing g");
- copy_of_g = g;
+ copy_of_g = f->proxies[TEST_G];
g_object_add_weak_pointer (copy_of_g, &copy_of_g);
- g_object_unref (g);
- g = NULL;
+ g_clear_object (&f->proxies[TEST_G]);
MYASSERT (copy_of_g != NULL, "");
MYASSERT (!tp_intset_is_member (freed_user_data, TEST_G), "");
MYASSERT (!tp_intset_is_member (method_ok, TEST_G), "");
@@ -312,14 +356,14 @@ main (int argc,
/* h gets unreferenced, *and* the call is cancelled (regression test for
* fd.o #14576) */
g_message ("Starting call on h");
- pc = tp_cli_dbus_daemon_call_list_names (h, -1, listed_names, PTR (TEST_H),
+ pc = tp_cli_dbus_properties_call_get_all (f->proxies[TEST_H], -1,
+ TP_IFACE_CHANNEL_DISPATCHER, method_cb, PTR (TEST_H),
destroy_user_data, NULL);
MYASSERT (!tp_intset_is_member (freed_user_data, TEST_H), "");
g_message ("Unreferencing h");
- copy_of_h = h;
+ copy_of_h = f->proxies[TEST_H];
g_object_add_weak_pointer (copy_of_h, &copy_of_h);
- g_object_unref (h);
- h = NULL;
+ g_clear_object (&f->proxies[TEST_H]);
MYASSERT (copy_of_h != NULL, "");
MYASSERT (!tp_intset_is_member (freed_user_data, TEST_H), "");
MYASSERT (!tp_intset_is_member (method_ok, TEST_H), "");
@@ -336,24 +380,24 @@ main (int argc,
* for the minimal regression test) */
i_stub = tp_tests_object_new_static_class (tp_tests_stub_object_get_type (),
NULL);
- tp_cli_dbus_daemon_connect_to_name_owner_changed (i, noc, PTR (TEST_I),
- NULL, i_stub, NULL);
+ tp_cli_dbus_properties_connect_to_properties_changed (f->proxies[TEST_I],
+ signal_cb, PTR (TEST_I), NULL, i_stub, NULL);
g_message ("Starting call on i");
- tp_cli_dbus_daemon_call_list_names (i, -1, listed_names, PTR (TEST_I),
+ tp_cli_dbus_properties_call_get_all (f->proxies[TEST_I], -1,
+ TP_IFACE_CHANNEL_DISPATCHER, method_cb, PTR (TEST_I),
destroy_user_data, i_stub);
MYASSERT (!tp_intset_is_member (freed_user_data, TEST_I), "");
- tp_cli_dbus_daemon_connect_to_name_owner_changed (i, noc, PTR (TEST_I),
- NULL, i_stub, NULL);
+ tp_cli_dbus_properties_connect_to_properties_changed (f->proxies[TEST_I],
+ signal_cb, PTR (TEST_I), NULL, i_stub, NULL);
g_message ("Unreferencing i");
- copy_of_i = i;
+ copy_of_i = f->proxies[TEST_I];
g_object_add_weak_pointer (copy_of_i, &copy_of_i);
- g_object_unref (i);
- i = NULL;
+ g_clear_object (&f->proxies[TEST_I]);
MYASSERT (copy_of_i != NULL, "");
MYASSERT (!tp_intset_is_member (freed_user_data, TEST_I), "");
MYASSERT (!tp_intset_is_member (method_ok, TEST_I), "");
MYASSERT (!tp_intset_is_member (method_error, TEST_I), "");
- g_object_unref (i_stub);
+ tp_tests_assert_last_unref (&i_stub);
MYASSERT (!tp_intset_is_member (method_ok, TEST_I), "");
MYASSERT (!tp_intset_is_member (method_error, TEST_I), "");
@@ -363,7 +407,8 @@ main (int argc,
NULL);
g_object_weak_ref (j_stub, j_stub_destroyed, PTR (TEST_J));
g_message ("Starting call on j");
- pc = tp_cli_dbus_daemon_call_list_names (j, -1, listed_names, j_stub,
+ pc = tp_cli_dbus_properties_call_get_all (f->proxies[TEST_J], -1,
+ TP_IFACE_CHANNEL_DISPATCHER, method_cb, j_stub,
g_object_unref, j_stub);
MYASSERT (!tp_intset_is_member (freed_user_data, TEST_J), "");
g_message ("Cancelling call on j");
@@ -379,27 +424,41 @@ main (int argc,
NULL);
g_message ("Starting call on k");
g_object_weak_ref (k_stub, k_stub_destroyed, &pc);
- tp_cli_dbus_daemon_call_list_names (k, -1, listed_names, PTR (TEST_K),
+ tp_cli_dbus_properties_call_get_all (f->proxies[TEST_K], -1,
+ TP_IFACE_CHANNEL_DISPATCHER, method_cb, PTR (TEST_K),
destroy_user_data, k_stub);
MYASSERT (!tp_intset_is_member (freed_user_data, TEST_K), "");
MYASSERT (!tp_intset_is_member (method_ok, TEST_K), "");
MYASSERT (!tp_intset_is_member (method_error, TEST_K), "");
- g_object_unref (k_stub);
+ tp_tests_assert_last_unref (&k_stub);
MYASSERT (!tp_intset_is_member (method_ok, TEST_K), "");
MYASSERT (!tp_intset_is_member (method_error, TEST_K), "");
/* z survives too; we assume that method calls succeed in order,
* so when z has had its reply, we can stop the main loop */
g_message ("Starting call on z");
- tp_cli_dbus_daemon_call_list_names (z, -1, listed_names, PTR (TEST_Z),
- destroy_user_data, (GObject *) a);
+ tp_cli_dbus_properties_call_get_all (f->proxies[TEST_Z], -1,
+ TP_IFACE_CHANNEL_DISPATCHER, method_cb, PTR (TEST_Z),
+ destroy_user_data, (GObject *) f->proxies[TEST_A]);
MYASSERT (!tp_intset_is_member (freed_user_data, TEST_Z), "");
MYASSERT (!tp_intset_is_member (method_ok, TEST_Z), "");
MYASSERT (!tp_intset_is_member (method_error, TEST_Z), "");
+ g_message ("Dropping private D-Bus connection");
+ drop_private_connection ();
+ /* the callback will be queued (to avoid reentrancy), so we don't get it
+ * until the main loop runs */
+ MYASSERT (!tp_intset_is_member (freed_user_data, TEST_F), "");
+ MYASSERT (!tp_intset_is_member (method_ok, TEST_F), "");
+ MYASSERT (!tp_intset_is_member (method_error, TEST_F), "");
+
g_message ("Running main loop");
- g_main_loop_run (mainloop);
- g_main_loop_unref (mainloop);
+
+ /* There's no guarantee that proxy F will detect that its socket closed
+ * in any particular order relative to the signals, so wait for both. */
+ while (!f->had_last_reply ||
+ tp_proxy_get_invalidated (f->proxies[TEST_F]) == NULL)
+ g_main_context_iteration (NULL, TRUE);
/* now that the calls have been delivered, d will finally have gone away */
MYASSERT (tp_intset_is_member (freed_user_data, TEST_D), "");
@@ -445,26 +504,18 @@ main (int argc,
MYASSERT (!tp_intset_is_member (method_error, TEST_Z), "");
g_message ("Dereferencing remaining proxies");
- g_object_unref (a);
- a = NULL;
- g_object_unref (b);
- b = NULL;
- g_object_unref (c);
- c = NULL;
- MYASSERT (d == NULL, "");
- g_object_unref (e);
- e = NULL;
- g_object_unref (f);
- f = NULL;
- MYASSERT (g == NULL, "");
- MYASSERT (h == NULL, "");
- MYASSERT (i == NULL, "");
- g_object_unref (j);
- j = NULL;
- g_object_unref (k);
- k = NULL;
- g_object_unref (z);
- z = NULL;
+ tp_tests_assert_last_unref (&f->proxies[TEST_A]);
+ tp_tests_assert_last_unref (&f->proxies[TEST_B]);
+ tp_tests_assert_last_unref (&f->proxies[TEST_C]);
+ g_assert (f->proxies[TEST_D] == NULL);
+ tp_tests_assert_last_unref (&f->proxies[TEST_E]);
+ tp_tests_assert_last_unref (&f->proxies[TEST_F]);
+ g_assert (f->proxies[TEST_G] == NULL);
+ g_assert (f->proxies[TEST_H] == NULL);
+ g_assert (f->proxies[TEST_I] == NULL);
+ tp_tests_assert_last_unref (&f->proxies[TEST_J]);
+ tp_tests_assert_last_unref (&f->proxies[TEST_K]);
+ tp_tests_assert_last_unref (&f->proxies[TEST_Z]);
/* we should already have checked each of these at least once, but just to
* make sure we have a systematic test that all user data is freed... */
@@ -485,5 +536,7 @@ main (int argc,
tp_intset_destroy (method_ok);
tp_intset_destroy (method_error);
+ teardown ();
+
return 0;
}
diff --git a/tests/dbus/connection.c b/tests/dbus/connection.c
index 33f77fcd1..1441c48ca 100644
--- a/tests/dbus/connection.c
+++ b/tests/dbus/connection.c
@@ -280,6 +280,7 @@ test_object_path (Test *test,
"simple_protocol");
/* Register the same connection with an invalid object path */
+ tp_dbus_daemon_unregister_object (test->dbus, test->service_conn);
tp_dbus_daemon_register_object (test->dbus, invalid_path, test->service_conn);
tp_dbus_daemon_request_name (test->dbus, invalid_name, FALSE, &error);
g_assert_no_error (error);
@@ -289,6 +290,12 @@ test_object_path (Test *test,
g_assert (connection == NULL);
g_assert_error (error, TP_DBUS_ERRORS, TP_DBUS_ERROR_INVALID_OBJECT_PATH);
g_clear_error (&error);
+
+ /* Put it back where it was meant to be so we can do teardown. */
+ tp_dbus_daemon_unregister_object (test->dbus, test->service_conn);
+ tp_dbus_daemon_register_object (test->dbus,
+ tp_base_connection_get_object_path (test->service_conn_as_base),
+ test->service_conn);
}
int
diff --git a/tests/dbus/disconnection.c b/tests/dbus/disconnection.c
index d2efcfa76..edf2dfe44 100644
--- a/tests/dbus/disconnection.c
+++ b/tests/dbus/disconnection.c
@@ -1,5 +1,8 @@
#include "config.h"
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
#include <telepathy-glib/cli-misc.h>
#include <telepathy-glib/dbus.h>
#include <telepathy-glib/debug.h>
@@ -7,9 +10,11 @@
#include <telepathy-glib/interfaces.h>
#include <telepathy-glib/intset.h>
#include <telepathy-glib/proxy-subclass.h> /* for _invalidated etc. */
+#include <telepathy-glib/svc-generic.h>
#include <telepathy-glib/util.h>
#include "tests/lib/myassert.h"
+#include "tests/lib/simple-channel-dispatcher.h"
#include "tests/lib/stub-object.h"
#include "tests/lib/util.h"
@@ -17,16 +22,6 @@
#define PTR(ui) GUINT_TO_POINTER(ui)
/* state tracking */
-static GMainLoop *mainloop;
-static TpDBusDaemon *a;
-static TpDBusDaemon *b;
-static TpDBusDaemon *c;
-static TpDBusDaemon *d;
-static TpDBusDaemon *e;
-static TpDBusDaemon *f;
-static TpDBusDaemon *g;
-static TpDBusDaemon *h;
-static TpDBusDaemon *z;
static TpIntset *caught_signal;
static TpIntset *freed_user_data;
@@ -40,9 +35,21 @@ enum {
TEST_G,
TEST_H,
TEST_Z = 25,
- N_DAEMONS
+ N_PROXIES
};
+typedef struct {
+ TpDBusDaemon *dbus_daemon;
+ TpProxy *proxies[N_PROXIES];
+ GObject *cd_service;
+
+ DBusConnection *private_libdbus;
+ DBusGConnection *private_dbusglib;
+ TpDBusDaemon *private_dbus_daemon;
+} Fixture;
+
+static Fixture *f;
+
static void
h_stub_destroyed (gpointer data,
GObject *stub)
@@ -62,58 +69,44 @@ destroy_user_data (gpointer user_data)
}
static void
-requested_name (TpDBusDaemon *proxy,
- guint result,
- const GError *error,
- gpointer user_data,
- GObject *weak_object)
+unwanted_signal_cb (TpProxy *proxy,
+ const gchar *iface,
+ GHashTable *changed,
+ const gchar **invalidated,
+ gpointer user_data,
+ GObject *weak_object)
{
- g_message ("RequestName raised %s",
- (error == NULL ? "no error" : error->message));
- /* we're on a private bus, so certainly nobody else should own this name */
- g_assert_no_error ((GError *) error);
- MYASSERT (result == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER, ": %u", result);
-}
-
-static void
-dummy_noc (TpDBusDaemon *proxy,
- const gchar *name,
- const gchar *old,
- const gchar *new,
- gpointer user_data,
- GObject *weak_object)
-{
- g_error ("dummy_noc called - a signal connection which should have "
+ g_error ("unwanted_signal_cb called - a signal connection which should have "
"failed has succeeded. Args: proxy=%p user_data=%p", proxy, user_data);
}
static void
-noc (TpDBusDaemon *proxy,
- const gchar *name,
- const gchar *old,
- const gchar *new,
- gpointer user_data,
- GObject *weak_object)
+signal_cb (TpProxy *proxy,
+ const gchar *iface,
+ GHashTable *changed,
+ const gchar **invalidated,
+ gpointer user_data,
+ GObject *weak_object)
{
guint which = GPOINTER_TO_UINT (user_data);
- TpDBusDaemon *want_proxy = NULL;
+ TpProxy *want_proxy = NULL;
GObject *want_object = NULL;
- g_message ("Caught signal (%s: %s -> %s) with proxy #%d '%c' according to "
- "user_data", name, old, new, which, 'a' + which);
+ g_message ("Caught signal with proxy #%d '%c' according to "
+ "user_data", which, 'a' + which);
g_message ("Proxy is %p, weak object is %p", proxy,
weak_object);
tp_intset_add (caught_signal, which);
+ want_proxy = f->proxies[which];
+
switch (which)
{
case TEST_A:
- want_proxy = a;
- want_object = (GObject *) z;
+ want_object = (GObject *) f->proxies[TEST_Z];
break;
case TEST_Z:
- want_proxy = z;
- want_object = (GObject *) a;
+ want_object = (GObject *) f->proxies[TEST_A];
break;
default:
g_error ("%c (%p) got the signal, which shouldn't have happened",
@@ -125,13 +118,6 @@ noc (TpDBusDaemon *proxy,
MYASSERT (proxy == want_proxy, ": %p != %p", proxy, want_proxy);
MYASSERT (weak_object == want_object, ": %p != %p", weak_object,
want_object);
-
- if (tp_intset_is_member (caught_signal, TEST_A) &&
- tp_intset_is_member (caught_signal, TEST_Z))
- {
- /* we've had all the signals we're going to */
- g_main_loop_quit (mainloop);
- }
}
static void
@@ -143,51 +129,108 @@ set_freed (gpointer user_data)
*boolptr = TRUE;
}
+static void
+setup (void)
+{
+ f->dbus_daemon = tp_tests_dbus_daemon_dup_or_die ();
+
+ /* Any random object with an interface: what matters is that it can
+ * accept a method call and emit a signal. We use the Properties
+ * interface here. */
+ f->cd_service = tp_tests_object_new_static_class (
+ TP_TESTS_TYPE_SIMPLE_CHANNEL_DISPATCHER,
+ NULL);
+ tp_dbus_daemon_register_object (f->dbus_daemon, "/", f->cd_service);
+
+ f->private_libdbus = dbus_bus_get_private (DBUS_BUS_STARTER, NULL);
+ g_assert (f->private_libdbus != NULL);
+ dbus_connection_setup_with_g_main (f->private_libdbus, NULL);
+ dbus_connection_set_exit_on_disconnect (f->private_libdbus, FALSE);
+ f->private_dbusglib = dbus_connection_get_g_connection (
+ f->private_libdbus);
+ dbus_g_connection_ref (f->private_dbusglib);
+ f->private_dbus_daemon = tp_dbus_daemon_new (f->private_dbusglib);
+ g_assert (f->private_dbus_daemon != NULL);
+}
+
+static void
+drop_private_connection (void)
+{
+ dbus_g_connection_unref (f->private_dbusglib);
+ f->private_dbusglib = NULL;
+ dbus_connection_close (f->private_libdbus);
+ dbus_connection_unref (f->private_libdbus);
+ f->private_libdbus = NULL;
+}
+
+static void
+teardown (void)
+{
+ tp_tests_assert_last_unref (&f->cd_service);
+ tp_tests_assert_last_unref (&f->dbus_daemon);
+
+ tp_tests_assert_last_unref (&f->private_dbus_daemon);
+}
+
+static TpProxy *
+new_proxy (int which)
+{
+ TpDBusDaemon *local_dbus_daemon;
+
+ if (which == TEST_F)
+ local_dbus_daemon = f->private_dbus_daemon;
+ else
+ local_dbus_daemon = f->dbus_daemon;
+
+ return tp_tests_object_new_static_class (TP_TYPE_PROXY,
+ "dbus-daemon", local_dbus_daemon,
+ "bus-name", tp_dbus_daemon_get_unique_name (f->dbus_daemon),
+ "object-path", "/",
+ NULL);
+}
+
int
main (int argc,
char **argv)
{
+ Fixture fixture = { NULL };
GObject *stub;
GError *error_out = NULL;
GError err = { TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "Because I said so" };
TpProxySignalConnection *sc;
- gpointer tmp_obj;
gboolean freed = FALSE;
+ GHashTable *empty_asv;
+ int i;
tp_tests_abort_after (10);
tp_debug_set_flags ("all");
- freed_user_data = tp_intset_sized_new (N_DAEMONS);
- caught_signal = tp_intset_sized_new (N_DAEMONS);
+ freed_user_data = tp_intset_sized_new (N_PROXIES);
+ caught_signal = tp_intset_sized_new (N_PROXIES);
+
+ /* it's on the stack, but it's valid until we leave main(), which will
+ * do for now... one day this test should use GTest, but this might
+ * not be that day */
+ f = &fixture;
- mainloop = g_main_loop_new (NULL, FALSE);
+ setup ();
- /* We use TpDBusDaemon because it's a convenient concrete subclass of
- * TpProxy. */
g_message ("Creating proxies");
- a = tp_tests_dbus_daemon_dup_or_die ();
- g_message ("a=%p", a);
- b = tp_dbus_daemon_new (tp_proxy_get_dbus_connection (a));
- g_message ("b=%p", b);
- c = tp_dbus_daemon_new (tp_proxy_get_dbus_connection (a));
- g_message ("c=%p", c);
- d = tp_dbus_daemon_new (tp_proxy_get_dbus_connection (a));
- g_message ("d=%p", d);
- e = tp_dbus_daemon_new (tp_proxy_get_dbus_connection (a));
- g_message ("e=%p", e);
- f = tp_dbus_daemon_new (tp_proxy_get_dbus_connection (a));
- g_message ("f=%p", f);
- g = tp_dbus_daemon_new (tp_proxy_get_dbus_connection (a));
- g_message ("g=%p", g);
- h = tp_dbus_daemon_new (tp_proxy_get_dbus_connection (a));
- g_message ("h=%p", h);
- z = tp_dbus_daemon_new (tp_proxy_get_dbus_connection (a));
- g_message ("z=%p", z);
+
+ for (i = TEST_A; i <= TEST_H; i++)
+ {
+ f->proxies[i] = new_proxy (i);
+ g_message ("%c=%p", 'a' + i, f->proxies[i]);
+ }
+
+ f->proxies[TEST_Z] = new_proxy (TEST_Z);
+ g_message ("z=%p", f->proxies[TEST_Z]);
/* a survives */
g_message ("Connecting signal to a");
- tp_cli_dbus_daemon_connect_to_name_owner_changed (a, noc, PTR (TEST_A),
- destroy_user_data, (GObject *) z, &error_out);
+ tp_cli_dbus_properties_connect_to_properties_changed (f->proxies[TEST_A],
+ signal_cb, PTR (TEST_A),
+ destroy_user_data, (GObject *) f->proxies[TEST_Z], &error_out);
g_assert_no_error (error_out);
/* b gets its signal connection cancelled because stub is
@@ -195,24 +238,27 @@ main (int argc,
stub = tp_tests_object_new_static_class (tp_tests_stub_object_get_type (),
NULL);
g_message ("Connecting signal to b");
- tp_cli_dbus_daemon_connect_to_name_owner_changed (b, noc, PTR (TEST_B),
+ tp_cli_dbus_properties_connect_to_properties_changed (f->proxies[TEST_B],
+ signal_cb, PTR (TEST_B),
destroy_user_data, stub, &error_out);
g_assert_no_error (error_out);
MYASSERT (!tp_intset_is_member (freed_user_data, TEST_B), "");
- g_object_unref (stub);
+ tp_tests_assert_last_unref (&stub);
/* c gets its signal connection cancelled because it's explicitly
* invalidated */
g_message ("Connecting signal to c");
- tp_cli_dbus_daemon_connect_to_name_owner_changed (c, noc, PTR (TEST_C),
+ tp_cli_dbus_properties_connect_to_properties_changed (f->proxies[TEST_C],
+ signal_cb, PTR (TEST_C),
destroy_user_data, NULL, &error_out);
g_assert_no_error (error_out);
MYASSERT (!tp_intset_is_member (freed_user_data, TEST_C), "");
g_message ("Forcibly invalidating c");
- tp_proxy_invalidate ((TpProxy *) c, &err);
+ tp_proxy_invalidate ((TpProxy *) f->proxies[TEST_C], &err);
/* assert that connecting to a signal on an invalid proxy fails */
freed = FALSE;
- tp_cli_dbus_daemon_connect_to_name_owner_changed (c, dummy_noc, &freed,
+ tp_cli_dbus_properties_connect_to_properties_changed (f->proxies[TEST_C],
+ unwanted_signal_cb, &freed,
set_freed, NULL, &error_out);
MYASSERT (freed, "");
MYASSERT (error_out != NULL, "");
@@ -226,20 +272,18 @@ main (int argc,
/* d gets its signal connection cancelled because it's
* implicitly invalidated by being destroyed */
g_message ("Connecting signal to d");
- tp_cli_dbus_daemon_connect_to_name_owner_changed (d, noc, PTR (TEST_D),
+ tp_cli_dbus_properties_connect_to_properties_changed (f->proxies[TEST_D],
+ signal_cb, PTR (TEST_D),
destroy_user_data, NULL, &error_out);
g_assert_no_error (error_out);
MYASSERT (!tp_intset_is_member (freed_user_data, TEST_D), "");
g_message ("Destroying d");
- tmp_obj = d;
- g_object_add_weak_pointer (tmp_obj, &tmp_obj);
- g_object_unref (d);
- MYASSERT (tmp_obj == NULL, "");
- d = NULL;
+ tp_tests_assert_last_unref (&f->proxies[TEST_D]);
/* e gets its signal connection cancelled explicitly */
g_message ("Connecting signal to e");
- sc = tp_cli_dbus_daemon_connect_to_name_owner_changed (e, noc, PTR (TEST_E),
+ sc = tp_cli_dbus_properties_connect_to_properties_changed (
+ f->proxies[TEST_E], signal_cb, PTR (TEST_E),
destroy_user_data, NULL, &error_out);
g_assert_no_error (error_out);
MYASSERT (!tp_intset_is_member (freed_user_data, TEST_E), "");
@@ -247,45 +291,26 @@ main (int argc,
tp_proxy_signal_connection_disconnect (sc);
/* f gets its signal connection cancelled because it's implicitly
- * invalidated by its DBusGProxy being destroyed.
- *
- * Note that this test case exploits implementation details of dbus-glib.
- * If it stops working after a dbus-glib upgrade, that's probably why. */
+ * invalidated by its own connection disconnecting. */
g_message ("Connecting signal to f");
- tp_cli_dbus_daemon_connect_to_name_owner_changed (f, noc, PTR (TEST_F),
+ tp_cli_dbus_properties_connect_to_properties_changed (f->proxies[TEST_F],
+ signal_cb, PTR (TEST_F),
destroy_user_data, NULL, &error_out);
g_assert_no_error (error_out);
MYASSERT (!tp_intset_is_member (freed_user_data, TEST_F), "");
- g_message ("Forcibly disposing f's DBusGProxy to simulate name owner loss");
- tmp_obj = tp_proxy_get_interface_by_id ((TpProxy *) f,
- TP_IFACE_QUARK_DBUS_DAEMON, NULL);
- MYASSERT (tmp_obj != NULL, "");
- g_object_run_dispose (tmp_obj);
- /* assert that connecting to a signal on an invalid proxy fails */
- freed = FALSE;
- tp_cli_dbus_daemon_connect_to_name_owner_changed (f, dummy_noc, &freed,
- set_freed, NULL, &error_out);
- MYASSERT (freed, "");
- MYASSERT (error_out != NULL, "");
- MYASSERT (error_out->code == DBUS_GERROR_NAME_HAS_NO_OWNER, "");
- g_error_free (error_out);
- error_out = NULL;
/* g gets its signal connection cancelled because it's
* implicitly invalidated by being destroyed; unlike d, the signal
* connection weakly references the proxy. This is never necessary, but is
* an interesting corner case that should be tested. */
g_message ("Connecting signal to g");
- tp_cli_dbus_daemon_connect_to_name_owner_changed (g, noc, PTR (TEST_G),
- destroy_user_data, (GObject *) g, &error_out);
+ tp_cli_dbus_properties_connect_to_properties_changed (f->proxies[TEST_G],
+ signal_cb, PTR (TEST_G),
+ destroy_user_data, (GObject *) f->proxies[TEST_G], &error_out);
g_assert_no_error (error_out);
MYASSERT (!tp_intset_is_member (freed_user_data, TEST_G), "");
g_message ("Destroying g");
- tmp_obj = g;
- g_object_add_weak_pointer (tmp_obj, &tmp_obj);
- g_object_unref (g);
- MYASSERT (tmp_obj == NULL, "");
- g = NULL;
+ tp_tests_assert_last_unref (&f->proxies[TEST_G]);
/* h gets its signal connection cancelled because its weak object is
* destroyed, meaning there are simultaneously two reasons for it to become
@@ -294,38 +319,74 @@ main (int argc,
NULL);
g_object_weak_ref (stub, h_stub_destroyed, &sc);
g_message ("Connecting signal to h");
- tp_cli_dbus_daemon_connect_to_name_owner_changed (h, noc, PTR (TEST_H),
+ tp_cli_dbus_properties_connect_to_properties_changed (f->proxies[TEST_H],
+ signal_cb, PTR (TEST_H),
destroy_user_data, stub, &error_out);
g_assert_no_error (error_out);
MYASSERT (!tp_intset_is_member (freed_user_data, TEST_H), "");
- g_object_unref (stub);
+ tp_tests_assert_last_unref (&stub);
/* z survives; we assume that the signals are delivered in either
* forward or reverse order, so if both a and z have had their signal, we
* can stop the main loop */
g_message ("Connecting signal to z");
- tp_cli_dbus_daemon_connect_to_name_owner_changed (z, noc, PTR (TEST_Z),
- destroy_user_data, (GObject *) a, &error_out);
+ tp_cli_dbus_properties_connect_to_properties_changed (f->proxies[TEST_Z],
+ signal_cb, PTR (TEST_Z),
+ destroy_user_data, (GObject *) f->proxies[TEST_A], &error_out);
g_assert_no_error (error_out);
- /* make sure a NameOwnerChanged signal occurs */
- g_message ("Requesting name");
- tp_cli_dbus_daemon_call_request_name (a, -1, "com.example.NameTest",
- 0, requested_name, NULL, NULL, NULL);
+ g_message ("Emitting signal");
+ empty_asv = tp_asv_new (NULL, NULL);
+ tp_svc_dbus_properties_emit_properties_changed (f->cd_service,
+ TP_IFACE_CHANNEL_DISPATCHER, empty_asv, NULL);
+ g_hash_table_unref (empty_asv);
+
+ g_message ("Dropping private D-Bus connection");
+ drop_private_connection ();
+ /* wait for everything to happen */
g_message ("Running main loop");
- g_main_loop_run (mainloop);
- g_main_loop_unref (mainloop);
- /* Now that the main loop has run, cancelled signal connections have been
- * freed */
- MYASSERT (tp_intset_is_member (freed_user_data, TEST_B), "");
- MYASSERT (tp_intset_is_member (freed_user_data, TEST_C), "");
- MYASSERT (tp_intset_is_member (freed_user_data, TEST_D), "");
- MYASSERT (tp_intset_is_member (freed_user_data, TEST_E), "");
- MYASSERT (tp_intset_is_member (freed_user_data, TEST_F), "");
- MYASSERT (tp_intset_is_member (freed_user_data, TEST_G), "");
- MYASSERT (tp_intset_is_member (freed_user_data, TEST_H), "");
+ /* There's no guarantee that proxy F will detect that its socket closed
+ * in any particular order relative to the signals, so wait for both. */
+ while (!tp_intset_is_member (caught_signal, TEST_A) ||
+ !tp_intset_is_member (caught_signal, TEST_Z) ||
+ tp_proxy_get_invalidated (f->proxies[TEST_F]) == NULL)
+ g_main_context_iteration (NULL, TRUE);
+
+ /* assert that connecting to a signal on an invalid proxy fails */
+ freed = FALSE;
+ tp_cli_dbus_properties_connect_to_properties_changed (f->proxies[TEST_F],
+ unwanted_signal_cb, &freed, set_freed, NULL, &error_out);
+ MYASSERT (freed, "");
+ MYASSERT (error_out != NULL, "");
+ MYASSERT (error_out->code == DBUS_GERROR_NAME_HAS_NO_OWNER, "");
+ g_error_free (error_out);
+ error_out = NULL;
+
+ /* It might take a little longer to free all the user-data, because it
+ * happens in an idle */
+
+ while (!tp_intset_is_member (freed_user_data, TEST_B))
+ g_main_context_iteration (NULL, TRUE);
+
+ while (!tp_intset_is_member (freed_user_data, TEST_C))
+ g_main_context_iteration (NULL, TRUE);
+
+ while (!tp_intset_is_member (freed_user_data, TEST_D))
+ g_main_context_iteration (NULL, TRUE);
+
+ while (!tp_intset_is_member (freed_user_data, TEST_E))
+ g_main_context_iteration (NULL, TRUE);
+
+ while (!tp_intset_is_member (freed_user_data, TEST_F))
+ g_main_context_iteration (NULL, TRUE);
+
+ while (!tp_intset_is_member (freed_user_data, TEST_G))
+ g_main_context_iteration (NULL, TRUE);
+
+ while (!tp_intset_is_member (freed_user_data, TEST_H))
+ g_main_context_iteration (NULL, TRUE);
/* both A and Z are still listening for signals, so their user data is
* still held */
@@ -333,14 +394,21 @@ main (int argc,
MYASSERT (!tp_intset_is_member (freed_user_data, TEST_Z), "");
g_message ("Dereferencing remaining proxies");
- g_object_unref (a);
- g_object_unref (b);
- g_object_unref (c);
- MYASSERT (d == NULL, "");
- g_object_unref (e);
- g_object_unref (f);
- MYASSERT (g == NULL, "");
- g_object_unref (z);
+ tp_tests_assert_last_unref (&f->proxies[TEST_A]);
+ tp_tests_assert_last_unref (&f->proxies[TEST_B]);
+ tp_tests_assert_last_unref (&f->proxies[TEST_C]);
+ g_assert (f->proxies[TEST_D] == NULL);
+ tp_tests_assert_last_unref (&f->proxies[TEST_E]);
+ tp_tests_assert_last_unref (&f->proxies[TEST_F]);
+ g_assert (f->proxies[TEST_G] == NULL);
+ tp_tests_assert_last_unref (&f->proxies[TEST_H]);
+ tp_tests_assert_last_unref (&f->proxies[TEST_Z]);
+
+ while (!tp_intset_is_member (freed_user_data, TEST_A))
+ g_main_context_iteration (NULL, TRUE);
+
+ while (!tp_intset_is_member (freed_user_data, TEST_Z))
+ g_main_context_iteration (NULL, TRUE);
/* we should already have checked each of these at least once, but just to
* make sure we have a systematic test that all user data is freed... */
@@ -357,5 +425,7 @@ main (int argc,
tp_intset_destroy (freed_user_data);
tp_intset_destroy (caught_signal);
+ teardown ();
+
return 0;
}
diff --git a/tests/dbus/unsupported-interface.c b/tests/dbus/unsupported-interface.c
index 818e40f2e..7ff94d777 100644
--- a/tests/dbus/unsupported-interface.c
+++ b/tests/dbus/unsupported-interface.c
@@ -196,7 +196,10 @@ test_supported_signal (Fixture *f,
g_assert (!f->freed);
tp_proxy_signal_connection_disconnect (sc);
- g_assert (f->freed);
+
+ /* GDBus invokes destructors in an idle */
+ while (!f->freed)
+ g_main_context_iteration (NULL, TRUE);
}
static void
diff --git a/tests/dbus/with-properties.xml b/tests/dbus/with-properties.xml
index 5047a737e..b2befb12b 100644
--- a/tests/dbus/with-properties.xml
+++ b/tests/dbus/with-properties.xml
@@ -10,9 +10,12 @@
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal"
value="true"/>
- <property name="ReadOnly" access="read" type="u"/>
- <property name="WriteOnly" access="write" type="u"/>
- <property name="ReadWrite" access="readwrite" type="u">
+ <property name="ReadOnly" access="read" type="u"
+ tp:name-for-bindings="Read_Only"/>
+ <property name="WriteOnly" access="write" type="u"
+ tp:name-for-bindings="Write_Only"/>
+ <property name="ReadWrite" access="readwrite" type="u"
+ tp:name-for-bindings="Read_Write">
<!-- … and that this overrides the global annotation. -->
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal"
value="invalidates"/>
diff --git a/tests/lib/util.c b/tests/lib/util.c
index 7f23fd4b9..f1c0fc464 100644
--- a/tests/lib/util.c
+++ b/tests/lib/util.c
@@ -265,6 +265,7 @@ tp_tests_create_conn (GType conn_type,
gchar *name;
gchar *conn_path;
GError *error = NULL;
+ gboolean ok;
g_assert (service_conn != NULL);
g_assert (client_conn != NULL);
@@ -278,9 +279,10 @@ tp_tests_create_conn (GType conn_type,
NULL);
g_assert (*service_conn != NULL);
- g_assert (tp_base_connection_register (*service_conn, "simple",
- &name, &conn_path, &error));
+ ok = tp_base_connection_register (*service_conn, "simple",
+ &name, &conn_path, &error);
g_assert_no_error (error);
+ g_assert (ok);
*client_conn = tp_tests_connection_new (dbus, NULL, conn_path, &error);
g_assert (*client_conn != NULL);
diff --git a/tools/glib-client-gen.py b/tools/glib-client-gen.py
index cd420a16a..db87741d6 100644
--- a/tools/glib-client-gen.py
+++ b/tools/glib-client-gen.py
@@ -29,8 +29,8 @@ from getopt import gnu_getopt
from libtpcodegen import file_set_contents, key_by_name, u
from libglibcodegen import (Signature, type_to_gtype,
- get_docstring, xml_escape, get_deprecated, copy_into_gvalue)
-
+ get_docstring, xml_escape, get_deprecated, copy_into_gvalue,
+ value_getter)
NS_TP = "http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0"
@@ -236,31 +236,12 @@ class Generator(object):
self.b(' if (callback != NULL)')
self.b(' callback (g_object_ref (tpproxy),')
- # FIXME: factor out into a function
for i, arg in enumerate(args):
name, info, tp_type, elt = arg
ctype, gtype, marshaller, pointer = info
- if marshaller == 'BOXED':
- self.b(' g_value_get_boxed (args->values + %d),' % i)
- elif gtype == 'G_TYPE_STRING':
- self.b(' g_value_get_string (args->values + %d),' % i)
- elif gtype == 'G_TYPE_UCHAR':
- self.b(' g_value_get_uchar (args->values + %d),' % i)
- elif gtype == 'G_TYPE_BOOLEAN':
- self.b(' g_value_get_boolean (args->values + %d),' % i)
- elif gtype == 'G_TYPE_UINT':
- self.b(' g_value_get_uint (args->values + %d),' % i)
- elif gtype == 'G_TYPE_INT':
- self.b(' g_value_get_int (args->values + %d),' % i)
- elif gtype == 'G_TYPE_UINT64':
- self.b(' g_value_get_uint64 (args->values + %d),' % i)
- elif gtype == 'G_TYPE_INT64':
- self.b(' g_value_get_int64 (args->values + %d),' % i)
- elif gtype == 'G_TYPE_DOUBLE':
- self.b(' g_value_get_double (args->values + %d),' % i)
- else:
- assert False, "Don't know how to get %s from a GValue" % gtype
+ getter = value_getter(gtype, marshaller)
+ self.b(' %s (args->values + %d),' % (getter, i))
self.b(' user_data,')
self.b(' weak_object);')
@@ -623,31 +604,12 @@ class Generator(object):
self.b(' callback ((%s) self,' % self.proxy_cls)
- # FIXME: factor out into a function
for i, arg in enumerate(out_args):
name, info, tp_type, elt = arg
ctype, gtype, marshaller, pointer = info
- if marshaller == 'BOXED':
- self.b(' g_value_get_boxed (args->values + %d),' % i)
- elif gtype == 'G_TYPE_STRING':
- self.b(' g_value_get_string (args->values + %d),' % i)
- elif gtype == 'G_TYPE_UCHAR':
- self.b(' g_value_get_uchar (args->values + %d),' % i)
- elif gtype == 'G_TYPE_BOOLEAN':
- self.b(' g_value_get_boolean (args->values + %d),' % i)
- elif gtype == 'G_TYPE_UINT':
- self.b(' g_value_get_uint (args->values + %d),' % i)
- elif gtype == 'G_TYPE_INT':
- self.b(' g_value_get_int (args->values + %d),' % i)
- elif gtype == 'G_TYPE_UINT64':
- self.b(' g_value_get_uint64 (args->values + %d),' % i)
- elif gtype == 'G_TYPE_INT64':
- self.b(' g_value_get_int64 (args->values + %d),' % i)
- elif gtype == 'G_TYPE_DOUBLE':
- self.b(' g_value_get_double (args->values + %d),' % i)
- else:
- assert False, "Don't know how to get %s from a GValue" % gtype
+ getter = value_getter(gtype, marshaller)
+ self.b(' %s (args->values + %d),' % (getter, i))
self.b(' error, user_data, weak_object);')
self.b('')
diff --git a/tools/glib-ginterface-gen.py b/tools/glib-ginterface-gen.py
index 6ef9f4a02..8cdb18fdb 100644
--- a/tools/glib-ginterface-gen.py
+++ b/tools/glib-ginterface-gen.py
@@ -26,23 +26,13 @@ import sys
import os.path
import xml.dom.minidom
-from libtpcodegen import file_set_contents, key_by_name, u
+from libtpcodegen import file_set_contents, key_by_name, u, get_emits_changed
from libglibcodegen import Signature, type_to_gtype, \
NS_TP, dbus_gutils_wincaps_to_uscore
NS_TP = "http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0"
-def get_emits_changed(node):
- try:
- return [
- annotation.getAttribute('value')
- for annotation in node.getElementsByTagName('annotation')
- if annotation.getAttribute('name') == 'org.freedesktop.DBus.Property.EmitsChangedSignal'
- ][0]
- except IndexError:
- return None
-
class Generator(object):
def __init__(self, dom, prefix, basename, signal_marshal_prefix,
diff --git a/tools/libglibcodegen.py b/tools/libglibcodegen.py
index 0b703a5a8..c03544fe2 100644
--- a/tools/libglibcodegen.py
+++ b/tools/libglibcodegen.py
@@ -193,3 +193,25 @@ def copy_into_gvalue(gvaluep, gtype, marshaller, name):
return 'g_value_set_double (%s, %s);' % (gvaluep, name)
else:
raise AssertionError("Don't know how to put %s in a GValue" % gtype)
+
+def value_getter(gtype, marshaller):
+ if marshaller == 'BOXED':
+ return 'g_value_get_boxed'
+ elif gtype == 'G_TYPE_STRING':
+ return 'g_value_get_string'
+ elif gtype == 'G_TYPE_UCHAR':
+ return 'g_value_get_uchar'
+ elif gtype == 'G_TYPE_BOOLEAN':
+ return 'g_value_get_boolean'
+ elif gtype == 'G_TYPE_UINT':
+ return 'g_value_get_uint'
+ elif gtype == 'G_TYPE_INT':
+ return 'g_value_get_int'
+ elif gtype == 'G_TYPE_UINT64':
+ return 'g_value_get_uint64'
+ elif gtype == 'G_TYPE_INT64':
+ return 'g_value_get_int64'
+ elif gtype == 'G_TYPE_DOUBLE':
+ return 'g_value_get_double'
+ else:
+ raise AssertionError("Don't know how to get %s from a GValue" % marshaller)
diff --git a/tools/libtpcodegen.py b/tools/libtpcodegen.py
index 99de66340..021a82be4 100644
--- a/tools/libtpcodegen.py
+++ b/tools/libtpcodegen.py
@@ -245,3 +245,13 @@ class Signature(str):
def xml_escape(s):
s = s.replace('&', '&amp;').replace("'", '&apos;').replace('"', '&quot;')
return s.replace('<', '&lt;').replace('>', '&gt;')
+
+def get_emits_changed(node):
+ try:
+ return [
+ annotation.getAttribute('value')
+ for annotation in node.getElementsByTagName('annotation')
+ if annotation.getAttribute('name') == 'org.freedesktop.DBus.Property.EmitsChangedSignal'
+ ][0]
+ except IndexError:
+ return None