From 8189bedbc983851a4d1b304cc8bd3365db09e80d Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Mon, 30 May 2011 13:29:10 +0100 Subject: [PATCH] registrations test: add a test case for an object with many locations Also use type='signal' in the match rule, to avoid replying to dbus-daemon method calls with an error. --- test/core/registrations.c | 134 ++++++++++++++++++++++++++++++++++++++------- 1 files changed, 113 insertions(+), 21 deletions(-) diff --git a/test/core/registrations.c b/test/core/registrations.c index 8da8d14..296d00c 100644 --- a/test/core/registrations.c +++ b/test/core/registrations.c @@ -44,23 +44,31 @@ GMainLoop *loop = NULL; +#define N_BUSES 5 + typedef struct { DBusGConnection *bus; - DBusGConnection *bus2; + DBusGConnection *buses[N_BUSES]; GObject *object; DBusMessage *frobnicate1_message; DBusMessage *frobnicate2_message; + GHashTable *frobnicated_set; + gsize stopped; } Fixture; static void setup (Fixture *f, gconstpointer path_to_use) { - f->bus = dbus_g_bus_get_private (DBUS_BUS_SESSION, NULL, NULL); - g_assert (f->bus != NULL); + guint i; + + for (i = 0; i < N_BUSES; i++) + { + f->buses[i] = dbus_g_bus_get_private (DBUS_BUS_SESSION, NULL, NULL); + g_assert (f->buses[i] != NULL); + } - f->bus2 = dbus_g_bus_get_private (DBUS_BUS_SESSION, NULL, NULL); - g_assert (f->bus2 != NULL); + f->bus = f->buses[0]; f->object = g_object_new (MY_TYPE_OBJECT, NULL); g_assert (MY_IS_OBJECT (f->object)); @@ -70,18 +78,17 @@ static void teardown (Fixture *f, gconstpointer test_data G_GNUC_UNUSED) { + guint i; + /* we close the connection before releasing the object, to test fd.o #5688 * in test_lookup() */ - if (f->bus != NULL) - { - dbus_connection_close (dbus_g_connection_get_connection (f->bus)); - dbus_g_connection_unref (f->bus); - } - - if (f->bus2 != NULL) + for (i = 0; i < N_BUSES; i++) { - dbus_connection_close (dbus_g_connection_get_connection (f->bus2)); - dbus_g_connection_unref (f->bus2); + if (f->buses[i] != NULL) + { + dbus_connection_close (dbus_g_connection_get_connection (f->buses[i])); + dbus_g_connection_unref (f->buses[i]); + } } if (f->object != NULL) @@ -204,7 +211,7 @@ frobnicate_cb (DBusConnection *conn, { g_assert_cmpstr (path, ==, "/bar"); g_assert_cmpstr (sender, ==, dbus_bus_get_unique_name ( - dbus_g_connection_get_connection (f->bus2))); + dbus_g_connection_get_connection (f->buses[1]))); g_assert (f->frobnicate2_message == NULL); f->frobnicate2_message = dbus_message_ref (message); @@ -224,15 +231,15 @@ test_twice (Fixture *f, dbus_g_connection_register_g_object (f->bus, "/foo", f->object); - dbus_g_connection_register_g_object (f->bus2, "/bar", f->object); + dbus_g_connection_register_g_object (f->buses[1], "/bar", f->object); g_assert (dbus_g_connection_lookup_g_object (f->bus, "/foo") == f->object); - g_assert (dbus_g_connection_lookup_g_object (f->bus2, "/bar") == + g_assert (dbus_g_connection_lookup_g_object (f->buses[1], "/bar") == f->object); dbus_bus_add_match (dbus_g_connection_get_connection (f->bus), - "", NULL); + "type='signal'", NULL); mem = dbus_connection_add_filter (dbus_g_connection_get_connection (f->bus), frobnicate_cb, f, NULL); g_assert (mem); @@ -269,7 +276,7 @@ test_clean_slate (Fixture *f, dbus_bool_t mem; dbus_bus_add_match (dbus_g_connection_get_connection (f->bus), - "", NULL); + "type='signal'", NULL); mem = dbus_connection_add_filter (dbus_g_connection_get_connection (f->bus), frobnicate_cb, f, NULL); g_assert (mem); @@ -306,8 +313,8 @@ test_clean_slate (Fixture *f, /* unregister the object from its last object path, then put it back * at a different location */ dbus_g_connection_unregister_g_object (f->bus, f->object); - dbus_g_connection_register_g_object (f->bus2, "/bar", f->object); - g_assert (dbus_g_connection_lookup_g_object (f->bus2, "/bar") == + dbus_g_connection_register_g_object (f->buses[1], "/bar", f->object); + g_assert (dbus_g_connection_lookup_g_object (f->buses[1], "/bar") == f->object); my_object_emit_frobnicate ((MyObject *) f->object, NULL); @@ -324,6 +331,89 @@ test_clean_slate (Fixture *f, f->frobnicate2_message = NULL; } +static DBusHandlerResult +multiplicity_cb (DBusConnection *conn, + DBusMessage *message, + void *user_data) +{ + Fixture *f = user_data; + + if (dbus_message_is_signal (message, + "org.freedesktop.DBus.GLib.Tests.MyObject", "Frobnicate")) + { + gchar *key = g_strdup_printf ("%s:%s", + dbus_message_get_sender (message), dbus_message_get_path (message)); + + if (g_hash_table_lookup (f->frobnicated_set, key) != NULL) + g_error ("duplicate signal emission from %s", key); + else + g_hash_table_insert (f->frobnicated_set, key, key); + } + else if (dbus_message_is_signal (message, + "com.example.Finite", "Stop")) + { + ++f->stopped; + } + + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +static void +test_multiplicity (Fixture *f, + gconstpointer test_data G_GNUC_UNUSED) +{ + dbus_bool_t mem; + guint i, j; +#define N_PATHS 5 + const gchar *paths[N_PATHS] = { "/a", "/b", "/c", "/d", "/e" }; + + g_test_bug ("32087#c9"); + + for (i = 0; i < N_BUSES; i++) + { + for (j = 0; j < N_PATHS; j++) + { + dbus_g_connection_register_g_object (f->buses[i], paths[j], f->object); + g_assert (dbus_g_connection_lookup_g_object (f->buses[i], + paths[j]) == f->object); + } + } + + f->frobnicated_set = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, + NULL); + + dbus_bus_add_match (dbus_g_connection_get_connection (f->bus), + "type='signal'", NULL); + mem = dbus_connection_add_filter (dbus_g_connection_get_connection (f->bus), + multiplicity_cb, f, NULL); + g_assert (mem); + + my_object_emit_frobnicate ((MyObject *) f->object, NULL); + + /* follow the Frobnicate signals with one other signal, so we can assert that + * Frobnicate was emitted no more times than necessary */ + for (i = 0; i < N_BUSES; i++) + { + DBusMessage *stop; + + stop = dbus_message_new_signal ("/", "com.example.Finite", "Stop"); + g_assert (stop != NULL); + mem = dbus_connection_send ( + dbus_g_connection_get_connection (f->buses[i]), stop, NULL); + g_assert (mem); + dbus_message_unref (stop); + } + + /* The object should emit the signal once onto each connection from each + * location */ + while (f->stopped < N_BUSES) + g_main_context_iteration (NULL, TRUE); + + g_assert_cmpuint (g_hash_table_size (f->frobnicated_set), ==, + N_BUSES * N_PATHS); + g_hash_table_unref (f->frobnicated_set); +} + int main (int argc, char **argv) { @@ -349,6 +439,8 @@ main (int argc, char **argv) setup, test_twice, teardown); g_test_add ("/registrations/clean-slate", Fixture, NULL, setup, test_clean_slate, teardown); + g_test_add ("/registrations/multiplicity", Fixture, NULL, + setup, test_multiplicity, teardown); return g_test_run (); } -- 1.7.5.3