1 /* GLib testing framework examples and tests
3 * Copyright (C) 2008-2010 Red Hat, Inc.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General
16 * Public License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18 * Boston, MA 02111-1307, USA.
20 * Author: David Zeuthen <davidz@redhat.com>
27 #include "gdbus-tests.h"
29 /* all tests rely on a shared mainloop */
30 static GMainLoop *loop = NULL;
32 /* ---------------------------------------------------------------------------------------------------- */
33 /* Connection life-cycle testing */
34 /* ---------------------------------------------------------------------------------------------------- */
37 test_connection_life_cycle (void)
46 * Check for correct behavior when no bus is present
49 c = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
50 _g_assert_error_domain (error, G_IO_ERROR);
51 g_assert (!g_dbus_error_is_remote_error (error));
57 * Check for correct behavior when a bus is present
61 c = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
62 g_assert_no_error (error);
64 g_assert (!g_dbus_connection_is_closed (c));
67 * Check that singleton handling work
69 c2 = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
70 g_assert_no_error (error);
71 g_assert (c2 != NULL);
76 * Check that private connections work
78 c2 = _g_bus_get_priv (G_BUS_TYPE_SESSION, NULL, &error);
79 g_assert_no_error (error);
80 g_assert (c2 != NULL);
84 c2 = _g_bus_get_priv (G_BUS_TYPE_SESSION, NULL, &error);
85 g_assert_no_error (error);
86 g_assert (c2 != NULL);
87 g_assert (!g_dbus_connection_is_closed (c2));
88 g_dbus_connection_close (c2);
89 _g_assert_signal_received (c2, "closed");
90 g_assert (g_dbus_connection_is_closed (c2));
94 * Check for correct behavior when the bus goes away
97 g_assert (!g_dbus_connection_is_closed (c));
98 g_dbus_connection_set_exit_on_close (c, FALSE);
100 if (!g_dbus_connection_is_closed (c))
101 _g_assert_signal_received (c, "closed");
102 g_assert (g_dbus_connection_is_closed (c));
104 _g_object_wait_for_single_ref (c);
108 /* ---------------------------------------------------------------------------------------------------- */
109 /* Test that sending and receiving messages work as expected */
110 /* ---------------------------------------------------------------------------------------------------- */
113 msg_cb_expect_error_disconnected (GDBusConnection *connection,
121 result = g_dbus_connection_invoke_method_finish (connection,
124 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CLOSED);
125 g_assert (!g_dbus_error_is_remote_error (error));
126 g_error_free (error);
127 g_assert (result == NULL);
129 g_main_loop_quit (loop);
133 msg_cb_expect_error_unknown_method (GDBusConnection *connection,
141 result = g_dbus_connection_invoke_method_finish (connection,
144 g_assert_error (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD);
145 g_assert (g_dbus_error_is_remote_error (error));
146 g_assert (result == NULL);
148 g_main_loop_quit (loop);
152 msg_cb_expect_success (GDBusConnection *connection,
160 result = g_dbus_connection_invoke_method_finish (connection,
163 g_assert_no_error (error);
164 g_assert (result != NULL);
165 g_variant_unref (result);
167 g_main_loop_quit (loop);
171 msg_cb_expect_error_cancelled (GDBusConnection *connection,
179 result = g_dbus_connection_invoke_method_finish (connection,
182 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
183 g_assert (!g_dbus_error_is_remote_error (error));
184 g_error_free (error);
185 g_assert (result == NULL);
187 g_main_loop_quit (loop);
191 msg_cb_expect_error_cancelled_2 (GDBusConnection *connection,
199 result = g_dbus_connection_invoke_method_finish (connection,
202 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
203 g_assert (!g_dbus_error_is_remote_error (error));
204 g_error_free (error);
205 g_assert (result == NULL);
207 g_main_loop_quit (loop);
210 /* ---------------------------------------------------------------------------------------------------- */
213 test_connection_send (void)
220 /* First, get an unopened connection */
221 c = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
222 g_assert (c != NULL);
223 g_assert (!g_dbus_connection_is_closed (c));
226 * Check that we never actually send a message if the GCancellable
227 * is already cancelled - i.e. we should get #G_IO_ERROR_CANCELLED
228 * when the actual connection is not up.
230 ca = g_cancellable_new ();
231 g_cancellable_cancel (ca);
232 g_dbus_connection_invoke_method (c,
233 "org.freedesktop.DBus", /* bus_name */
234 "/org/freedesktop/DBus", /* object path */
235 "org.freedesktop.DBus", /* interface name */
236 "GetId", /* method name */
238 G_DBUS_INVOKE_METHOD_FLAGS_NONE,
241 (GAsyncReadyCallback) msg_cb_expect_error_cancelled,
243 g_main_loop_run (loop);
247 * Check that we get a reply to the GetId() method call.
249 g_dbus_connection_invoke_method (c,
250 "org.freedesktop.DBus", /* bus_name */
251 "/org/freedesktop/DBus", /* object path */
252 "org.freedesktop.DBus", /* interface name */
253 "GetId", /* method name */
255 G_DBUS_INVOKE_METHOD_FLAGS_NONE,
258 (GAsyncReadyCallback) msg_cb_expect_success,
260 g_main_loop_run (loop);
263 * Check that we get an error reply to the NonExistantMethod() method call.
265 g_dbus_connection_invoke_method (c,
266 "org.freedesktop.DBus", /* bus_name */
267 "/org/freedesktop/DBus", /* object path */
268 "org.freedesktop.DBus", /* interface name */
269 "NonExistantMethod", /* method name */
271 G_DBUS_INVOKE_METHOD_FLAGS_NONE,
274 (GAsyncReadyCallback) msg_cb_expect_error_unknown_method,
276 g_main_loop_run (loop);
279 * Check that cancellation works when the message is already in flight.
281 ca = g_cancellable_new ();
282 g_dbus_connection_invoke_method (c,
283 "org.freedesktop.DBus", /* bus_name */
284 "/org/freedesktop/DBus", /* object path */
285 "org.freedesktop.DBus", /* interface name */
286 "GetId", /* method name */
288 G_DBUS_INVOKE_METHOD_FLAGS_NONE,
291 (GAsyncReadyCallback) msg_cb_expect_error_cancelled_2,
293 g_cancellable_cancel (ca);
294 g_main_loop_run (loop);
298 * Check that we get an error when sending to a connection that is disconnected.
300 g_dbus_connection_set_exit_on_close (c, FALSE);
302 _g_assert_signal_received (c, "closed");
303 g_assert (g_dbus_connection_is_closed (c));
305 g_dbus_connection_invoke_method (c,
306 "org.freedesktop.DBus", /* bus_name */
307 "/org/freedesktop/DBus", /* object path */
308 "org.freedesktop.DBus", /* interface name */
309 "GetId", /* method name */
311 G_DBUS_INVOKE_METHOD_FLAGS_NONE,
314 (GAsyncReadyCallback) msg_cb_expect_error_disconnected,
316 g_main_loop_run (loop);
318 _g_object_wait_for_single_ref (c);
322 /* ---------------------------------------------------------------------------------------------------- */
323 /* Connection signal tests */
324 /* ---------------------------------------------------------------------------------------------------- */
327 test_connection_signal_handler (GDBusConnection *connection,
328 const gchar *sender_name,
329 const gchar *object_path,
330 const gchar *interface_name,
331 const gchar *signal_name,
332 GVariant *parameters,
335 gint *counter = user_data;
338 /*g_debug ("in test_connection_signal_handler (sender=%s path=%s interface=%s member=%s)",
344 g_main_loop_quit (loop);
348 test_connection_signal_quit_mainloop (gpointer user_data)
350 gboolean *quit_mainloop_fired = user_data;
351 *quit_mainloop_fired = TRUE;
352 g_main_loop_quit (loop);
357 test_connection_signals (void)
367 gint count_name_owner_changed;
375 * Bring up first separate connections
378 /* if running with dbus-monitor, it claims the name :1.0 - so if we don't run with the monitor
381 if (g_getenv ("G_DBUS_MONITOR") == NULL)
383 c1 = _g_bus_get_priv (G_BUS_TYPE_SESSION, NULL, NULL);
384 g_assert (c1 != NULL);
385 g_assert (!g_dbus_connection_is_closed (c1));
388 c1 = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
389 g_assert (c1 != NULL);
390 g_assert (!g_dbus_connection_is_closed (c1));
391 g_assert_cmpstr (g_dbus_connection_get_unique_name (c1), ==, ":1.1");
394 * Install two signal handlers for the first connection
396 * - Listen to the signal "Foo" from :1.2 (e.g. c2)
397 * - Listen to the signal "Foo" from anyone (e.g. both c2 and c3)
399 * and then count how many times this signal handler was invoked.
401 s1 = g_dbus_connection_signal_subscribe (c1,
403 "org.gtk.GDBus.ExampleInterface",
405 "/org/gtk/GDBus/ExampleInterface",
407 test_connection_signal_handler,
410 s2 = g_dbus_connection_signal_subscribe (c1,
411 NULL, /* match any sender */
412 "org.gtk.GDBus.ExampleInterface",
414 "/org/gtk/GDBus/ExampleInterface",
416 test_connection_signal_handler,
419 s3 = g_dbus_connection_signal_subscribe (c1,
420 "org.freedesktop.DBus", /* sender */
421 "org.freedesktop.DBus", /* interface */
422 "NameOwnerChanged", /* member */
423 "/org/freedesktop/DBus", /* path */
425 test_connection_signal_handler,
426 &count_name_owner_changed,
434 count_name_owner_changed = 0;
437 * Bring up two other connections
439 c2 = _g_bus_get_priv (G_BUS_TYPE_SESSION, NULL, NULL);
440 g_assert (c2 != NULL);
441 g_assert (!g_dbus_connection_is_closed (c2));
442 g_assert_cmpstr (g_dbus_connection_get_unique_name (c2), ==, ":1.2");
443 c3 = _g_bus_get_priv (G_BUS_TYPE_SESSION, NULL, NULL);
444 g_assert (c3 != NULL);
445 g_assert (!g_dbus_connection_is_closed (c3));
446 g_assert_cmpstr (g_dbus_connection_get_unique_name (c3), ==, ":1.3");
449 * Make c2 emit "Foo" - we should catch it twice
451 * Note that there is no way to be sure that the signal subscriptions
452 * on c1 are effective yet - for all we know, the AddMatch() messages
453 * could sit waiting in a buffer somewhere between this process and
454 * the message bus. And emitting signals on c2 (a completely other
455 * socket!) will not necessarily change this.
457 * To ensure this is not the case, do a synchronous call on c1.
459 result = g_dbus_connection_invoke_method_sync (c1,
460 "org.freedesktop.DBus", /* bus name */
461 "/org/freedesktop/DBus", /* object path */
462 "org.freedesktop.DBus", /* interface name */
463 "GetId", /* method name */
464 NULL, /* parameters */
465 G_DBUS_INVOKE_METHOD_FLAGS_NONE,
469 g_assert_no_error (error);
470 g_assert (result != NULL);
471 g_variant_unref (result);
472 /* now, emit the signal on c2 */
473 ret = g_dbus_connection_emit_signal (c2,
474 NULL, /* destination bus name */
475 "/org/gtk/GDBus/ExampleInterface",
476 "org.gtk.GDBus.ExampleInterface",
480 g_assert_no_error (error);
482 while (!(count_s1 == 1 && count_s2 == 1))
483 g_main_loop_run (loop);
484 g_assert_cmpint (count_s1, ==, 1);
485 g_assert_cmpint (count_s2, ==, 1);
488 * Make c3 emit "Foo" - we should catch it only once
490 ret = g_dbus_connection_emit_signal (c3,
491 NULL, /* destination bus name */
492 "/org/gtk/GDBus/ExampleInterface",
493 "org.gtk.GDBus.ExampleInterface",
497 g_assert_no_error (error);
499 while (!(count_s1 == 1 && count_s2 == 2))
500 g_main_loop_run (loop);
501 g_assert_cmpint (count_s1, ==, 1);
502 g_assert_cmpint (count_s2, ==, 2);
505 * Also to check the total amount of NameOwnerChanged signals - use a 5 second ceiling
506 * to avoid spinning forever
508 gboolean quit_mainloop_fired;
509 guint quit_mainloop_id;
510 quit_mainloop_fired = FALSE;
511 quit_mainloop_id = g_timeout_add (5000, test_connection_signal_quit_mainloop, &quit_mainloop_fired);
512 while (count_name_owner_changed != 2 && !quit_mainloop_fired)
513 g_main_loop_run (loop);
514 g_source_remove (quit_mainloop_id);
515 g_assert_cmpint (count_s1, ==, 1);
516 g_assert_cmpint (count_s2, ==, 2);
517 g_assert_cmpint (count_name_owner_changed, ==, 2);
519 g_dbus_connection_signal_unsubscribe (c1, s1);
520 g_dbus_connection_signal_unsubscribe (c1, s2);
521 g_dbus_connection_signal_unsubscribe (c1, s3);
523 _g_object_wait_for_single_ref (c1);
524 _g_object_wait_for_single_ref (c2);
525 _g_object_wait_for_single_ref (c3);
534 /* ---------------------------------------------------------------------------------------------------- */
543 filter_func (GDBusConnection *connection,
544 GDBusMessage *message,
547 FilterData *data = user_data;
548 guint32 reply_serial;
550 reply_serial = g_dbus_message_get_reply_serial (message);
551 if (reply_serial == data->serial)
552 data->num_handled += 1;
558 test_connection_filter (void)
567 memset (&data, '\0', sizeof (FilterData));
572 c = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
573 g_assert_no_error (error);
574 g_assert (c != NULL);
576 filter_id = g_dbus_connection_add_filter (c,
581 m = g_dbus_message_new_method_call ("org.freedesktop.DBus", /* name */
582 "/org/freedesktop/DBus", /* path */
583 "org.freedesktop.DBus", /* interface */
585 g_dbus_message_set_body (m, g_variant_new ("(s)", "org.freedesktop.DBus"));
587 g_dbus_connection_send_message (c, m, &data.serial, &error);
588 g_assert_no_error (error);
590 while (data.num_handled == 0)
593 g_dbus_connection_send_message (c, m, &data.serial, &error);
594 g_assert_no_error (error);
596 while (data.num_handled == 1)
599 r = g_dbus_connection_send_message_with_reply_sync (c,
603 NULL, /* GCancellable */
605 g_assert_no_error (error);
606 g_assert (r != NULL);
608 g_assert_cmpint (data.num_handled, ==, 3);
610 g_dbus_connection_remove_filter (c, filter_id);
612 r = g_dbus_connection_send_message_with_reply_sync (c,
616 NULL, /* GCancellable */
618 g_assert_no_error (error);
619 g_assert (r != NULL);
621 g_assert_cmpint (data.num_handled, ==, 3);
623 _g_object_wait_for_single_ref (c);
630 /* ---------------------------------------------------------------------------------------------------- */
637 g_test_init (&argc, &argv, NULL);
639 /* all the tests rely on a shared main loop */
640 loop = g_main_loop_new (NULL, FALSE);
642 /* all the tests use a session bus with a well-known address that we can bring up and down
643 * using session_bus_up() and session_bus_down().
645 g_unsetenv ("DISPLAY");
646 g_setenv ("DBUS_SESSION_BUS_ADDRESS", session_bus_get_temporary_address (), TRUE);
648 g_test_add_func ("/gdbus/connection-life-cycle", test_connection_life_cycle);
649 g_test_add_func ("/gdbus/connection-send", test_connection_send);
650 g_test_add_func ("/gdbus/connection-signals", test_connection_signals);
651 g_test_add_func ("/gdbus/connection-filter", test_connection_filter);