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 <sys/types.h>
30 #include "gdbus-tests.h"
32 /* all tests rely on a shared mainloop */
33 static GMainLoop *loop = NULL;
35 /* ---------------------------------------------------------------------------------------------------- */
36 /* Connection life-cycle testing */
37 /* ---------------------------------------------------------------------------------------------------- */
40 test_connection_life_cycle (void)
49 * Check for correct behavior when no bus is present
52 c = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
53 _g_assert_error_domain (error, G_IO_ERROR);
54 g_assert (!g_dbus_error_is_remote_error (error));
60 * Check for correct behavior when a bus is present
64 c = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
65 g_assert_no_error (error);
67 g_assert (!g_dbus_connection_is_closed (c));
70 * Check that singleton handling work
72 c2 = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
73 g_assert_no_error (error);
74 g_assert (c2 != NULL);
79 * Check that private connections work
81 c2 = _g_bus_get_priv (G_BUS_TYPE_SESSION, NULL, &error);
82 g_assert_no_error (error);
83 g_assert (c2 != NULL);
87 c2 = _g_bus_get_priv (G_BUS_TYPE_SESSION, NULL, &error);
88 g_assert_no_error (error);
89 g_assert (c2 != NULL);
90 g_assert (!g_dbus_connection_is_closed (c2));
91 g_dbus_connection_close (c2);
92 _g_assert_signal_received (c2, "closed");
93 g_assert (g_dbus_connection_is_closed (c2));
97 * Check for correct behavior when the bus goes away
100 g_assert (!g_dbus_connection_is_closed (c));
101 g_dbus_connection_set_exit_on_close (c, FALSE);
103 if (!g_dbus_connection_is_closed (c))
104 _g_assert_signal_received (c, "closed");
105 g_assert (g_dbus_connection_is_closed (c));
107 _g_object_wait_for_single_ref (c);
111 /* ---------------------------------------------------------------------------------------------------- */
112 /* Test that sending and receiving messages work as expected */
113 /* ---------------------------------------------------------------------------------------------------- */
116 msg_cb_expect_error_disconnected (GDBusConnection *connection,
124 result = g_dbus_connection_call_finish (connection,
127 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CLOSED);
128 g_assert (!g_dbus_error_is_remote_error (error));
129 g_error_free (error);
130 g_assert (result == NULL);
132 g_main_loop_quit (loop);
136 msg_cb_expect_error_unknown_method (GDBusConnection *connection,
144 result = g_dbus_connection_call_finish (connection,
147 g_assert_error (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD);
148 g_assert (g_dbus_error_is_remote_error (error));
149 g_assert (result == NULL);
151 g_main_loop_quit (loop);
155 msg_cb_expect_success (GDBusConnection *connection,
163 result = g_dbus_connection_call_finish (connection,
166 g_assert_no_error (error);
167 g_assert (result != NULL);
168 g_variant_unref (result);
170 g_main_loop_quit (loop);
174 msg_cb_expect_error_cancelled (GDBusConnection *connection,
182 result = g_dbus_connection_call_finish (connection,
185 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
186 g_assert (!g_dbus_error_is_remote_error (error));
187 g_error_free (error);
188 g_assert (result == NULL);
190 g_main_loop_quit (loop);
194 msg_cb_expect_error_cancelled_2 (GDBusConnection *connection,
202 result = g_dbus_connection_call_finish (connection,
205 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
206 g_assert (!g_dbus_error_is_remote_error (error));
207 g_error_free (error);
208 g_assert (result == NULL);
210 g_main_loop_quit (loop);
213 /* ---------------------------------------------------------------------------------------------------- */
216 test_connection_send (void)
223 /* First, get an unopened connection */
224 c = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
225 g_assert (c != NULL);
226 g_assert (!g_dbus_connection_is_closed (c));
229 * Check that we never actually send a message if the GCancellable
230 * is already cancelled - i.e. we should get #G_IO_ERROR_CANCELLED
231 * when the actual connection is not up.
233 ca = g_cancellable_new ();
234 g_cancellable_cancel (ca);
235 g_dbus_connection_call (c,
236 "org.freedesktop.DBus", /* bus_name */
237 "/org/freedesktop/DBus", /* object path */
238 "org.freedesktop.DBus", /* interface name */
239 "GetId", /* method name */
241 G_DBUS_CALL_FLAGS_NONE,
244 (GAsyncReadyCallback) msg_cb_expect_error_cancelled,
246 g_main_loop_run (loop);
250 * Check that we get a reply to the GetId() method call.
252 g_dbus_connection_call (c,
253 "org.freedesktop.DBus", /* bus_name */
254 "/org/freedesktop/DBus", /* object path */
255 "org.freedesktop.DBus", /* interface name */
256 "GetId", /* method name */
258 G_DBUS_CALL_FLAGS_NONE,
261 (GAsyncReadyCallback) msg_cb_expect_success,
263 g_main_loop_run (loop);
266 * Check that we get an error reply to the NonExistantMethod() method call.
268 g_dbus_connection_call (c,
269 "org.freedesktop.DBus", /* bus_name */
270 "/org/freedesktop/DBus", /* object path */
271 "org.freedesktop.DBus", /* interface name */
272 "NonExistantMethod", /* method name */
274 G_DBUS_CALL_FLAGS_NONE,
277 (GAsyncReadyCallback) msg_cb_expect_error_unknown_method,
279 g_main_loop_run (loop);
282 * Check that cancellation works when the message is already in flight.
284 ca = g_cancellable_new ();
285 g_dbus_connection_call (c,
286 "org.freedesktop.DBus", /* bus_name */
287 "/org/freedesktop/DBus", /* object path */
288 "org.freedesktop.DBus", /* interface name */
289 "GetId", /* method name */
291 G_DBUS_CALL_FLAGS_NONE,
294 (GAsyncReadyCallback) msg_cb_expect_error_cancelled_2,
296 g_cancellable_cancel (ca);
297 g_main_loop_run (loop);
301 * Check that we get an error when sending to a connection that is disconnected.
303 g_dbus_connection_set_exit_on_close (c, FALSE);
305 _g_assert_signal_received (c, "closed");
306 g_assert (g_dbus_connection_is_closed (c));
308 g_dbus_connection_call (c,
309 "org.freedesktop.DBus", /* bus_name */
310 "/org/freedesktop/DBus", /* object path */
311 "org.freedesktop.DBus", /* interface name */
312 "GetId", /* method name */
314 G_DBUS_CALL_FLAGS_NONE,
317 (GAsyncReadyCallback) msg_cb_expect_error_disconnected,
319 g_main_loop_run (loop);
321 _g_object_wait_for_single_ref (c);
325 /* ---------------------------------------------------------------------------------------------------- */
326 /* Connection signal tests */
327 /* ---------------------------------------------------------------------------------------------------- */
330 test_connection_signal_handler (GDBusConnection *connection,
331 const gchar *sender_name,
332 const gchar *object_path,
333 const gchar *interface_name,
334 const gchar *signal_name,
335 GVariant *parameters,
338 gint *counter = user_data;
341 /*g_debug ("in test_connection_signal_handler (sender=%s path=%s interface=%s member=%s)",
347 g_main_loop_quit (loop);
351 test_connection_signal_quit_mainloop (gpointer user_data)
353 gboolean *quit_mainloop_fired = user_data;
354 *quit_mainloop_fired = TRUE;
355 g_main_loop_quit (loop);
360 test_connection_signals (void)
372 gint count_name_owner_changed;
380 * Bring up first separate connections
383 /* if running with dbus-monitor, it claims the name :1.0 - so if we don't run with the monitor
386 if (g_getenv ("G_DBUS_MONITOR") == NULL)
388 c1 = _g_bus_get_priv (G_BUS_TYPE_SESSION, NULL, NULL);
389 g_assert (c1 != NULL);
390 g_assert (!g_dbus_connection_is_closed (c1));
393 c1 = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
394 g_assert (c1 != NULL);
395 g_assert (!g_dbus_connection_is_closed (c1));
396 g_assert_cmpstr (g_dbus_connection_get_unique_name (c1), ==, ":1.1");
399 * Install two signal handlers for the first connection
401 * - Listen to the signal "Foo" from :1.2 (e.g. c2)
402 * - Listen to the signal "Foo" from anyone (e.g. both c2 and c3)
404 * and then count how many times this signal handler was invoked.
406 s1 = g_dbus_connection_signal_subscribe (c1,
408 "org.gtk.GDBus.ExampleInterface",
410 "/org/gtk/GDBus/ExampleInterface",
412 test_connection_signal_handler,
415 s2 = g_dbus_connection_signal_subscribe (c1,
416 NULL, /* match any sender */
417 "org.gtk.GDBus.ExampleInterface",
419 "/org/gtk/GDBus/ExampleInterface",
421 test_connection_signal_handler,
424 s3 = g_dbus_connection_signal_subscribe (c1,
425 "org.freedesktop.DBus", /* sender */
426 "org.freedesktop.DBus", /* interface */
427 "NameOwnerChanged", /* member */
428 "/org/freedesktop/DBus", /* path */
430 test_connection_signal_handler,
431 &count_name_owner_changed,
433 /* Note that s1b is *just like* s1 - this is to catch a bug where N
434 * subscriptions of the same rule causes N calls to each of the N
435 * subscriptions instead of just 1 call to each of the N subscriptions.
437 s1b = g_dbus_connection_signal_subscribe (c1,
439 "org.gtk.GDBus.ExampleInterface",
441 "/org/gtk/GDBus/ExampleInterface",
443 test_connection_signal_handler,
454 count_name_owner_changed = 0;
457 * Bring up two other connections
459 c2 = _g_bus_get_priv (G_BUS_TYPE_SESSION, NULL, NULL);
460 g_assert (c2 != NULL);
461 g_assert (!g_dbus_connection_is_closed (c2));
462 g_assert_cmpstr (g_dbus_connection_get_unique_name (c2), ==, ":1.2");
463 c3 = _g_bus_get_priv (G_BUS_TYPE_SESSION, NULL, NULL);
464 g_assert (c3 != NULL);
465 g_assert (!g_dbus_connection_is_closed (c3));
466 g_assert_cmpstr (g_dbus_connection_get_unique_name (c3), ==, ":1.3");
469 * Make c2 emit "Foo" - we should catch it twice
471 * Note that there is no way to be sure that the signal subscriptions
472 * on c1 are effective yet - for all we know, the AddMatch() messages
473 * could sit waiting in a buffer somewhere between this process and
474 * the message bus. And emitting signals on c2 (a completely other
475 * socket!) will not necessarily change this.
477 * To ensure this is not the case, do a synchronous call on c1.
479 result = g_dbus_connection_call_sync (c1,
480 "org.freedesktop.DBus", /* bus name */
481 "/org/freedesktop/DBus", /* object path */
482 "org.freedesktop.DBus", /* interface name */
483 "GetId", /* method name */
484 NULL, /* parameters */
485 NULL, /* return type */
486 G_DBUS_CALL_FLAGS_NONE,
490 g_assert_no_error (error);
491 g_assert (result != NULL);
492 g_variant_unref (result);
493 /* now, emit the signal on c2 */
494 ret = g_dbus_connection_emit_signal (c2,
495 NULL, /* destination bus name */
496 "/org/gtk/GDBus/ExampleInterface",
497 "org.gtk.GDBus.ExampleInterface",
501 g_assert_no_error (error);
503 while (!(count_s1 >= 1 && count_s2 >= 1))
504 g_main_loop_run (loop);
505 g_assert_cmpint (count_s1, ==, 1);
506 g_assert_cmpint (count_s2, ==, 1);
509 * Make c3 emit "Foo" - we should catch it only once
511 ret = g_dbus_connection_emit_signal (c3,
512 NULL, /* destination bus name */
513 "/org/gtk/GDBus/ExampleInterface",
514 "org.gtk.GDBus.ExampleInterface",
518 g_assert_no_error (error);
520 while (!(count_s1 == 1 && count_s2 == 2))
521 g_main_loop_run (loop);
522 g_assert_cmpint (count_s1, ==, 1);
523 g_assert_cmpint (count_s2, ==, 2);
526 * Also to check the total amount of NameOwnerChanged signals - use a 5 second ceiling
527 * to avoid spinning forever
529 gboolean quit_mainloop_fired;
530 guint quit_mainloop_id;
531 quit_mainloop_fired = FALSE;
532 quit_mainloop_id = g_timeout_add (5000, test_connection_signal_quit_mainloop, &quit_mainloop_fired);
533 while (count_name_owner_changed < 2 && !quit_mainloop_fired)
534 g_main_loop_run (loop);
535 g_source_remove (quit_mainloop_id);
536 g_assert_cmpint (count_s1, ==, 1);
537 g_assert_cmpint (count_s2, ==, 2);
538 g_assert_cmpint (count_name_owner_changed, ==, 2);
540 g_dbus_connection_signal_unsubscribe (c1, s1);
541 g_dbus_connection_signal_unsubscribe (c1, s2);
542 g_dbus_connection_signal_unsubscribe (c1, s3);
543 g_dbus_connection_signal_unsubscribe (c1, s1b);
545 _g_object_wait_for_single_ref (c1);
546 _g_object_wait_for_single_ref (c2);
547 _g_object_wait_for_single_ref (c3);
556 /* ---------------------------------------------------------------------------------------------------- */
566 filter_func (GDBusConnection *connection,
567 GDBusMessage *message,
571 FilterData *data = user_data;
572 guint32 reply_serial;
576 reply_serial = g_dbus_message_get_reply_serial (message);
577 if (reply_serial == data->serial)
578 data->num_handled += 1;
582 data->num_outgoing += 1;
589 test_connection_filter (void)
598 memset (&data, '\0', sizeof (FilterData));
603 c = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
604 g_assert_no_error (error);
605 g_assert (c != NULL);
607 filter_id = g_dbus_connection_add_filter (c,
612 m = g_dbus_message_new_method_call ("org.freedesktop.DBus", /* name */
613 "/org/freedesktop/DBus", /* path */
614 "org.freedesktop.DBus", /* interface */
616 g_dbus_message_set_body (m, g_variant_new ("(s)", "org.freedesktop.DBus"));
618 g_dbus_connection_send_message (c, m, &data.serial, &error);
619 g_assert_no_error (error);
621 while (data.num_handled == 0)
624 g_dbus_message_set_serial (m, 0);
625 g_dbus_connection_send_message (c, m, &data.serial, &error);
626 g_assert_no_error (error);
628 while (data.num_handled == 1)
631 g_dbus_message_set_serial (m, 0);
632 r = g_dbus_connection_send_message_with_reply_sync (c,
636 NULL, /* GCancellable */
638 g_assert_no_error (error);
639 g_assert (r != NULL);
641 g_assert_cmpint (data.num_handled, ==, 3);
643 g_dbus_connection_remove_filter (c, filter_id);
645 g_dbus_message_set_serial (m, 0);
646 r = g_dbus_connection_send_message_with_reply_sync (c,
650 NULL, /* GCancellable */
652 g_assert_no_error (error);
653 g_assert (r != NULL);
655 g_assert_cmpint (data.num_handled, ==, 3);
656 g_assert_cmpint (data.num_outgoing, ==, 3);
658 _g_object_wait_for_single_ref (c);
665 /* ---------------------------------------------------------------------------------------------------- */
668 test_connection_flush_signal_handler (GDBusConnection *connection,
669 const gchar *sender_name,
670 const gchar *object_path,
671 const gchar *interface_name,
672 const gchar *signal_name,
673 GVariant *parameters,
676 g_main_loop_quit (loop);
680 test_connection_flush_on_timeout (gpointer user_data)
682 guint iteration = GPOINTER_TO_UINT (user_data);
683 g_printerr ("Timeout waiting 1000 msec on iteration %d\n", iteration);
684 g_assert_not_reached ();
689 test_connection_flush (void)
691 GDBusConnection *connection;
694 guint signal_handler_id;
699 connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
700 g_assert_no_error (error);
701 g_assert (connection != NULL);
703 signal_handler_id = g_dbus_connection_signal_subscribe (connection,
705 "org.gtk.GDBus.FlushInterface",
707 "/org/gtk/GDBus/FlushObject",
709 test_connection_flush_signal_handler,
712 g_assert_cmpint (signal_handler_id, !=, 0);
714 for (n = 0; n < 50; n++)
718 guint timeout_mainloop_id;
721 ret = g_spawn_command_line_sync ("./gdbus-connection-flush-helper",
726 g_assert_no_error (error);
727 g_assert (WIFEXITED (exit_status));
728 g_assert_cmpint (WEXITSTATUS (exit_status), ==, 0);
731 timeout_mainloop_id = g_timeout_add (1000, test_connection_flush_on_timeout, GUINT_TO_POINTER (n));
732 g_main_loop_run (loop);
733 g_source_remove (timeout_mainloop_id);
736 g_dbus_connection_signal_unsubscribe (connection, signal_handler_id);
737 _g_object_wait_for_single_ref (connection);
738 g_object_unref (connection);
743 /* ---------------------------------------------------------------------------------------------------- */
750 g_test_init (&argc, &argv, NULL);
752 /* all the tests rely on a shared main loop */
753 loop = g_main_loop_new (NULL, FALSE);
755 /* all the tests use a session bus with a well-known address that we can bring up and down
756 * using session_bus_up() and session_bus_down().
758 g_unsetenv ("DISPLAY");
759 g_setenv ("DBUS_SESSION_BUS_ADDRESS", session_bus_get_temporary_address (), TRUE);
761 g_test_add_func ("/gdbus/connection-life-cycle", test_connection_life_cycle);
762 g_test_add_func ("/gdbus/connection-send", test_connection_send);
763 g_test_add_func ("/gdbus/connection-signals", test_connection_signals);
764 g_test_add_func ("/gdbus/connection-filter", test_connection_filter);
765 g_test_add_func ("/gdbus/connection-flush", test_connection_flush);