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, see <http://www.gnu.org/licenses/>.
18 * Author: David Zeuthen <davidz@redhat.com>
25 #include <sys/types.h>
27 #include "gdbus-tests.h"
29 /* all tests rely on a shared mainloop */
30 static GMainLoop
*loop
= NULL
;
33 G_GNUC_UNUSED
static void
34 _log (const gchar
*format
, ...)
43 va_start (var_args
, format
);
44 str
= g_strdup_vprintf (format
, var_args
);
47 g_get_current_time (&now
);
48 now_time
= (time_t) now
.tv_sec
;
49 now_tm
= localtime (&now_time
);
50 strftime (time_buf
, sizeof time_buf
, "%H:%M:%S", now_tm
);
52 g_printerr ("%s.%06d: %s\n",
53 time_buf
, (gint
) now
.tv_usec
/ 1000,
62 test_connection_quit_mainloop (gpointer user_data
)
64 volatile gboolean
*quit_mainloop_fired
= user_data
;
65 _log ("quit_mainloop_fired");
66 *quit_mainloop_fired
= TRUE
;
67 g_main_loop_quit (loop
);
71 /* ---------------------------------------------------------------------------------------------------- */
72 /* Connection life-cycle testing */
73 /* ---------------------------------------------------------------------------------------------------- */
75 static const GDBusInterfaceInfo boo_interface_info
=
79 (GDBusMethodInfo
**) NULL
,
80 (GDBusSignalInfo
**) NULL
,
81 (GDBusPropertyInfo
**) NULL
,
85 static const GDBusInterfaceVTable boo_vtable
=
87 NULL
, /* _method_call */
88 NULL
, /* _get_property */
89 NULL
/* _set_property */
93 some_filter_func (GDBusConnection
*connection
,
94 GDBusMessage
*message
,
102 on_name_owner_changed (GDBusConnection
*connection
,
103 const gchar
*sender_name
,
104 const gchar
*object_path
,
105 const gchar
*interface_name
,
106 const gchar
*signal_name
,
107 GVariant
*parameters
,
113 a_gdestroynotify_that_sets_a_gboolean_to_true_and_quits_loop (gpointer user_data
)
115 volatile gboolean
*val
= user_data
;
117 _log ("destroynotify fired for %p", val
);
118 g_main_loop_quit (loop
);
122 test_connection_bus_failure (void)
125 GError
*error
= NULL
;
128 * Check for correct behavior when no bus is present
131 c
= g_bus_get_sync (G_BUS_TYPE_SESSION
, NULL
, &error
);
132 g_assert (error
!= NULL
);
133 g_assert (!g_dbus_error_is_remote_error (error
));
134 g_assert (c
== NULL
);
135 g_error_free (error
);
139 test_connection_life_cycle (void)
145 volatile gboolean on_signal_registration_freed_called
;
146 volatile gboolean on_filter_freed_called
;
147 volatile gboolean on_register_object_freed_called
;
148 volatile gboolean quit_mainloop_fired
;
149 guint quit_mainloop_id
;
150 guint registration_id
;
155 * Check for correct behavior when a bus is present
160 c
= g_bus_get_sync (G_BUS_TYPE_SESSION
, NULL
, &error
);
161 g_assert_no_error (error
);
162 g_assert (c
!= NULL
);
163 g_assert (!g_dbus_connection_is_closed (c
));
166 * Check that singleton handling work
169 c2
= g_bus_get_sync (G_BUS_TYPE_SESSION
, NULL
, &error
);
170 g_assert_no_error (error
);
171 g_assert (c2
!= NULL
);
176 * Check that private connections work
178 c2
= _g_bus_get_priv (G_BUS_TYPE_SESSION
, NULL
, &error
);
179 g_assert_no_error (error
);
180 g_assert (c2
!= NULL
);
184 c2
= _g_bus_get_priv (G_BUS_TYPE_SESSION
, NULL
, &error
);
185 g_assert_no_error (error
);
186 g_assert (c2
!= NULL
);
187 g_assert (!g_dbus_connection_is_closed (c2
));
188 ret
= g_dbus_connection_close_sync (c2
, NULL
, &error
);
189 g_assert_no_error (error
);
191 _g_assert_signal_received (c2
, "closed");
192 g_assert (g_dbus_connection_is_closed (c2
));
193 ret
= g_dbus_connection_close_sync (c2
, NULL
, &error
);
194 g_assert_error (error
, G_IO_ERROR
, G_IO_ERROR_CLOSED
);
195 g_error_free (error
);
200 * Check that the finalization code works
202 * (and that the GDestroyNotify for filters and objects and signal
203 * registrations are run as expected)
206 c2
= _g_bus_get_priv (G_BUS_TYPE_SESSION
, NULL
, &error
);
207 g_assert_no_error (error
);
208 g_assert (c2
!= NULL
);
209 /* signal registration */
210 on_signal_registration_freed_called
= FALSE
;
211 g_dbus_connection_signal_subscribe (c2
,
212 "org.freedesktop.DBus", /* bus name */
213 "org.freedesktop.DBus", /* interface */
214 "NameOwnerChanged", /* member */
215 "/org/freesktop/DBus", /* path */
217 G_DBUS_SIGNAL_FLAGS_NONE
,
218 on_name_owner_changed
,
219 (gpointer
) &on_signal_registration_freed_called
,
220 a_gdestroynotify_that_sets_a_gboolean_to_true_and_quits_loop
);
222 on_filter_freed_called
= FALSE
;
223 g_dbus_connection_add_filter (c2
,
225 (gpointer
) &on_filter_freed_called
,
226 a_gdestroynotify_that_sets_a_gboolean_to_true_and_quits_loop
);
227 /* object registration */
228 on_register_object_freed_called
= FALSE
;
230 registration_id
= g_dbus_connection_register_object (c2
,
232 (GDBusInterfaceInfo
*) &boo_interface_info
,
234 (gpointer
) &on_register_object_freed_called
,
235 a_gdestroynotify_that_sets_a_gboolean_to_true_and_quits_loop
,
237 g_assert_no_error (error
);
238 g_assert (registration_id
> 0);
239 /* ok, finalize the connection and check that all the GDestroyNotify functions are invoked as expected */
241 quit_mainloop_fired
= FALSE
;
242 quit_mainloop_id
= g_timeout_add (30000, test_connection_quit_mainloop
, (gpointer
) &quit_mainloop_fired
);
243 _log ("destroynotifies for\n"
244 " register_object %p\n"
247 &on_register_object_freed_called
,
248 &on_filter_freed_called
,
249 &on_signal_registration_freed_called
);
252 if (on_signal_registration_freed_called
&&
253 on_filter_freed_called
&&
254 on_register_object_freed_called
)
256 if (quit_mainloop_fired
)
258 _log ("entering loop");
259 g_main_loop_run (loop
);
260 _log ("exiting loop");
262 g_source_remove (quit_mainloop_id
);
263 g_assert (on_signal_registration_freed_called
);
264 g_assert (on_filter_freed_called
);
265 g_assert (on_register_object_freed_called
);
266 g_assert (!quit_mainloop_fired
);
269 * Check for correct behavior when the bus goes away
272 g_assert (!g_dbus_connection_is_closed (c
));
273 g_dbus_connection_set_exit_on_close (c
, FALSE
);
275 _g_assert_signal_received (c
, "closed");
276 g_assert (g_dbus_connection_is_closed (c
));
282 /* ---------------------------------------------------------------------------------------------------- */
283 /* Test that sending and receiving messages work as expected */
284 /* ---------------------------------------------------------------------------------------------------- */
287 msg_cb_expect_error_disconnected (GDBusConnection
*connection
,
294 /* Make sure gdbusconnection isn't holding @connection's lock. (#747349) */
295 g_dbus_connection_get_last_serial (connection
);
298 result
= g_dbus_connection_call_finish (connection
,
301 g_assert_error (error
, G_IO_ERROR
, G_IO_ERROR_CLOSED
);
302 g_assert (!g_dbus_error_is_remote_error (error
));
303 g_error_free (error
);
304 g_assert (result
== NULL
);
306 g_main_loop_quit (loop
);
310 msg_cb_expect_error_unknown_method (GDBusConnection
*connection
,
317 /* Make sure gdbusconnection isn't holding @connection's lock. (#747349) */
318 g_dbus_connection_get_last_serial (connection
);
321 result
= g_dbus_connection_call_finish (connection
,
324 g_assert_error (error
, G_DBUS_ERROR
, G_DBUS_ERROR_UNKNOWN_METHOD
);
325 g_assert (g_dbus_error_is_remote_error (error
));
326 g_error_free (error
);
327 g_assert (result
== NULL
);
329 g_main_loop_quit (loop
);
333 msg_cb_expect_success (GDBusConnection
*connection
,
340 /* Make sure gdbusconnection isn't holding @connection's lock. (#747349) */
341 g_dbus_connection_get_last_serial (connection
);
344 result
= g_dbus_connection_call_finish (connection
,
347 g_assert_no_error (error
);
348 g_assert (result
!= NULL
);
349 g_variant_unref (result
);
351 g_main_loop_quit (loop
);
355 msg_cb_expect_error_cancelled (GDBusConnection
*connection
,
362 /* Make sure gdbusconnection isn't holding @connection's lock. (#747349) */
363 g_dbus_connection_get_last_serial (connection
);
366 result
= g_dbus_connection_call_finish (connection
,
369 g_assert_error (error
, G_IO_ERROR
, G_IO_ERROR_CANCELLED
);
370 g_assert (!g_dbus_error_is_remote_error (error
));
371 g_error_free (error
);
372 g_assert (result
== NULL
);
374 g_main_loop_quit (loop
);
378 msg_cb_expect_error_cancelled_2 (GDBusConnection
*connection
,
385 /* Make sure gdbusconnection isn't holding @connection's lock. (#747349) */
386 g_dbus_connection_get_last_serial (connection
);
389 result
= g_dbus_connection_call_finish (connection
,
392 g_assert_error (error
, G_IO_ERROR
, G_IO_ERROR_CANCELLED
);
393 g_assert (!g_dbus_error_is_remote_error (error
));
394 g_error_free (error
);
395 g_assert (result
== NULL
);
397 g_main_loop_quit (loop
);
400 /* ---------------------------------------------------------------------------------------------------- */
403 test_connection_send (void)
410 /* First, get an unopened connection */
411 c
= g_bus_get_sync (G_BUS_TYPE_SESSION
, NULL
, NULL
);
412 g_assert (c
!= NULL
);
413 g_assert (!g_dbus_connection_is_closed (c
));
416 * Check that we never actually send a message if the GCancellable
417 * is already cancelled - i.e. we should get #G_IO_ERROR_CANCELLED
418 * when the actual connection is not up.
420 ca
= g_cancellable_new ();
421 g_cancellable_cancel (ca
);
422 g_dbus_connection_call (c
,
423 "org.freedesktop.DBus", /* bus_name */
424 "/org/freedesktop/DBus", /* object path */
425 "org.freedesktop.DBus", /* interface name */
426 "GetId", /* method name */
428 G_DBUS_CALL_FLAGS_NONE
,
431 (GAsyncReadyCallback
) msg_cb_expect_error_cancelled
,
433 g_main_loop_run (loop
);
437 * Check that we get a reply to the GetId() method call.
439 g_dbus_connection_call (c
,
440 "org.freedesktop.DBus", /* bus_name */
441 "/org/freedesktop/DBus", /* object path */
442 "org.freedesktop.DBus", /* interface name */
443 "GetId", /* method name */
445 G_DBUS_CALL_FLAGS_NONE
,
448 (GAsyncReadyCallback
) msg_cb_expect_success
,
450 g_main_loop_run (loop
);
453 * Check that we get an error reply to the NonExistantMethod() method call.
455 g_dbus_connection_call (c
,
456 "org.freedesktop.DBus", /* bus_name */
457 "/org/freedesktop/DBus", /* object path */
458 "org.freedesktop.DBus", /* interface name */
459 "NonExistantMethod", /* method name */
461 G_DBUS_CALL_FLAGS_NONE
,
464 (GAsyncReadyCallback
) msg_cb_expect_error_unknown_method
,
466 g_main_loop_run (loop
);
469 * Check that cancellation works when the message is already in flight.
471 ca
= g_cancellable_new ();
472 g_dbus_connection_call (c
,
473 "org.freedesktop.DBus", /* bus_name */
474 "/org/freedesktop/DBus", /* object path */
475 "org.freedesktop.DBus", /* interface name */
476 "GetId", /* method name */
478 G_DBUS_CALL_FLAGS_NONE
,
481 (GAsyncReadyCallback
) msg_cb_expect_error_cancelled_2
,
483 g_cancellable_cancel (ca
);
484 g_main_loop_run (loop
);
488 * Check that we get an error when sending to a connection that is disconnected.
490 g_dbus_connection_set_exit_on_close (c
, FALSE
);
492 _g_assert_signal_received (c
, "closed");
493 g_assert (g_dbus_connection_is_closed (c
));
495 g_dbus_connection_call (c
,
496 "org.freedesktop.DBus", /* bus_name */
497 "/org/freedesktop/DBus", /* object path */
498 "org.freedesktop.DBus", /* interface name */
499 "GetId", /* method name */
501 G_DBUS_CALL_FLAGS_NONE
,
504 (GAsyncReadyCallback
) msg_cb_expect_error_disconnected
,
506 g_main_loop_run (loop
);
513 /* ---------------------------------------------------------------------------------------------------- */
514 /* Connection signal tests */
515 /* ---------------------------------------------------------------------------------------------------- */
518 test_connection_signal_handler (GDBusConnection
*connection
,
519 const gchar
*sender_name
,
520 const gchar
*object_path
,
521 const gchar
*interface_name
,
522 const gchar
*signal_name
,
523 GVariant
*parameters
,
526 gint
*counter
= user_data
;
529 /*g_debug ("in test_connection_signal_handler (sender=%s path=%s interface=%s member=%s)",
535 g_main_loop_quit (loop
);
539 test_connection_signals (void)
551 gint count_name_owner_changed
;
555 gboolean quit_mainloop_fired
;
556 guint quit_mainloop_id
;
561 * Bring up first separate connections
564 /* if running with dbus-monitor, it claims the name :1.0 - so if we don't run with the monitor
567 if (g_getenv ("G_DBUS_MONITOR") == NULL
)
569 c1
= _g_bus_get_priv (G_BUS_TYPE_SESSION
, NULL
, NULL
);
570 g_assert (c1
!= NULL
);
571 g_assert (!g_dbus_connection_is_closed (c1
));
574 c1
= g_bus_get_sync (G_BUS_TYPE_SESSION
, NULL
, NULL
);
575 g_assert (c1
!= NULL
);
576 g_assert (!g_dbus_connection_is_closed (c1
));
577 g_assert_cmpstr (g_dbus_connection_get_unique_name (c1
), ==, ":1.1");
580 * Install two signal handlers for the first connection
582 * - Listen to the signal "Foo" from :1.2 (e.g. c2)
583 * - Listen to the signal "Foo" from anyone (e.g. both c2 and c3)
585 * and then count how many times this signal handler was invoked.
587 s1
= g_dbus_connection_signal_subscribe (c1
,
589 "org.gtk.GDBus.ExampleInterface",
591 "/org/gtk/GDBus/ExampleInterface",
593 G_DBUS_SIGNAL_FLAGS_NONE
,
594 test_connection_signal_handler
,
597 s2
= g_dbus_connection_signal_subscribe (c1
,
598 NULL
, /* match any sender */
599 "org.gtk.GDBus.ExampleInterface",
601 "/org/gtk/GDBus/ExampleInterface",
603 G_DBUS_SIGNAL_FLAGS_NONE
,
604 test_connection_signal_handler
,
607 s3
= g_dbus_connection_signal_subscribe (c1
,
608 "org.freedesktop.DBus", /* sender */
609 "org.freedesktop.DBus", /* interface */
610 "NameOwnerChanged", /* member */
611 "/org/freedesktop/DBus", /* path */
613 G_DBUS_SIGNAL_FLAGS_NONE
,
614 test_connection_signal_handler
,
615 &count_name_owner_changed
,
617 /* Note that s1b is *just like* s1 - this is to catch a bug where N
618 * subscriptions of the same rule causes N calls to each of the N
619 * subscriptions instead of just 1 call to each of the N subscriptions.
621 s1b
= g_dbus_connection_signal_subscribe (c1
,
623 "org.gtk.GDBus.ExampleInterface",
625 "/org/gtk/GDBus/ExampleInterface",
627 G_DBUS_SIGNAL_FLAGS_NONE
,
628 test_connection_signal_handler
,
639 count_name_owner_changed
= 0;
642 * Make c2 emit "Foo" - we should catch it twice
644 * Note that there is no way to be sure that the signal subscriptions
645 * on c1 are effective yet - for all we know, the AddMatch() messages
646 * could sit waiting in a buffer somewhere between this process and
647 * the message bus. And emitting signals on c2 (a completely other
648 * socket!) will not necessarily change this.
650 * To ensure this is not the case, do a synchronous call on c1.
652 result
= g_dbus_connection_call_sync (c1
,
653 "org.freedesktop.DBus", /* bus name */
654 "/org/freedesktop/DBus", /* object path */
655 "org.freedesktop.DBus", /* interface name */
656 "GetId", /* method name */
657 NULL
, /* parameters */
658 NULL
, /* return type */
659 G_DBUS_CALL_FLAGS_NONE
,
663 g_assert_no_error (error
);
664 g_assert (result
!= NULL
);
665 g_variant_unref (result
);
668 * Bring up two other connections
670 c2
= _g_bus_get_priv (G_BUS_TYPE_SESSION
, NULL
, NULL
);
671 g_assert (c2
!= NULL
);
672 g_assert (!g_dbus_connection_is_closed (c2
));
673 g_assert_cmpstr (g_dbus_connection_get_unique_name (c2
), ==, ":1.2");
674 c3
= _g_bus_get_priv (G_BUS_TYPE_SESSION
, NULL
, NULL
);
675 g_assert (c3
!= NULL
);
676 g_assert (!g_dbus_connection_is_closed (c3
));
677 g_assert_cmpstr (g_dbus_connection_get_unique_name (c3
), ==, ":1.3");
679 /* now, emit the signal on c2 */
680 ret
= g_dbus_connection_emit_signal (c2
,
681 NULL
, /* destination bus name */
682 "/org/gtk/GDBus/ExampleInterface",
683 "org.gtk.GDBus.ExampleInterface",
687 g_assert_no_error (error
);
689 while (!(count_s1
>= 1 && count_s2
>= 1))
690 g_main_loop_run (loop
);
691 g_assert_cmpint (count_s1
, ==, 1);
692 g_assert_cmpint (count_s2
, ==, 1);
695 * Make c3 emit "Foo" - we should catch it only once
697 ret
= g_dbus_connection_emit_signal (c3
,
698 NULL
, /* destination bus name */
699 "/org/gtk/GDBus/ExampleInterface",
700 "org.gtk.GDBus.ExampleInterface",
704 g_assert_no_error (error
);
706 while (!(count_s1
== 1 && count_s2
== 2))
707 g_main_loop_run (loop
);
708 g_assert_cmpint (count_s1
, ==, 1);
709 g_assert_cmpint (count_s2
, ==, 2);
712 * Also to check the total amount of NameOwnerChanged signals - use a 5 second ceiling
713 * to avoid spinning forever
715 quit_mainloop_fired
= FALSE
;
716 quit_mainloop_id
= g_timeout_add (30000, test_connection_quit_mainloop
, &quit_mainloop_fired
);
717 while (count_name_owner_changed
< 2 && !quit_mainloop_fired
)
718 g_main_loop_run (loop
);
719 g_source_remove (quit_mainloop_id
);
720 g_assert_cmpint (count_s1
, ==, 1);
721 g_assert_cmpint (count_s2
, ==, 2);
722 g_assert_cmpint (count_name_owner_changed
, ==, 2);
724 g_dbus_connection_signal_unsubscribe (c1
, s1
);
725 g_dbus_connection_signal_unsubscribe (c1
, s2
);
726 g_dbus_connection_signal_unsubscribe (c1
, s3
);
727 g_dbus_connection_signal_unsubscribe (c1
, s1b
);
737 test_match_rule (GDBusConnection
*connection
,
738 GDBusSignalFlags flags
,
741 gboolean should_match
)
743 guint subscription_ids
[2];
746 GError
*error
= NULL
;
748 subscription_ids
[0] = g_dbus_connection_signal_subscribe (connection
,
749 NULL
, "org.gtk.ExampleInterface", "Foo", "/",
751 G_DBUS_SIGNAL_FLAGS_NONE
,
752 test_connection_signal_handler
,
754 subscription_ids
[1] = g_dbus_connection_signal_subscribe (connection
,
755 NULL
, "org.gtk.ExampleInterface", "Foo", "/",
758 test_connection_signal_handler
,
760 g_assert_cmpint (subscription_ids
[0], !=, 0);
761 g_assert_cmpint (subscription_ids
[1], !=, 0);
763 g_dbus_connection_emit_signal (connection
,
764 NULL
, "/", "org.gtk.ExampleInterface",
765 "Foo", g_variant_new ("(s)", arg0
),
767 g_assert_no_error (error
);
769 /* synchronously ping a non-existent method to make sure the signals are dispatched */
770 g_dbus_connection_call_sync (connection
, "org.gtk.ExampleInterface", "/", "org.gtk.ExampleInterface",
771 "Bar", g_variant_new ("()"), G_VARIANT_TYPE_UNIT
, G_DBUS_CALL_FLAGS_NONE
,
774 while (g_main_context_iteration (NULL
, FALSE
))
777 g_assert_cmpint (emissions
, ==, 1);
778 g_assert_cmpint (matches
, ==, should_match
? 1 : 0);
780 g_dbus_connection_signal_unsubscribe (connection
, subscription_ids
[0]);
781 g_dbus_connection_signal_unsubscribe (connection
, subscription_ids
[1]);
785 test_connection_signal_match_rules (void)
787 GDBusConnection
*con
;
790 con
= g_bus_get_sync (G_BUS_TYPE_SESSION
, NULL
, NULL
);
792 test_match_rule (con
, G_DBUS_SIGNAL_FLAGS_NONE
, "foo", "foo", TRUE
);
793 test_match_rule (con
, G_DBUS_SIGNAL_FLAGS_NONE
, "foo", "bar", FALSE
);
795 test_match_rule (con
, G_DBUS_SIGNAL_FLAGS_MATCH_ARG0_NAMESPACE
, "org.gtk", "", FALSE
);
796 test_match_rule (con
, G_DBUS_SIGNAL_FLAGS_MATCH_ARG0_NAMESPACE
, "org.gtk", "org", FALSE
);
797 test_match_rule (con
, G_DBUS_SIGNAL_FLAGS_MATCH_ARG0_NAMESPACE
, "org.gtk", "org.gtk", TRUE
);
798 test_match_rule (con
, G_DBUS_SIGNAL_FLAGS_MATCH_ARG0_NAMESPACE
, "org.gtk", "org.gtk.Example", TRUE
);
799 test_match_rule (con
, G_DBUS_SIGNAL_FLAGS_MATCH_ARG0_NAMESPACE
, "org.gtk", "org.gtk+", FALSE
);
801 test_match_rule (con
, G_DBUS_SIGNAL_FLAGS_MATCH_ARG0_PATH
, "/", "/", TRUE
);
802 test_match_rule (con
, G_DBUS_SIGNAL_FLAGS_MATCH_ARG0_PATH
, "/", "", FALSE
);
803 test_match_rule (con
, G_DBUS_SIGNAL_FLAGS_MATCH_ARG0_PATH
, "/org/gtk/Example", "/org/gtk/Example", TRUE
);
804 test_match_rule (con
, G_DBUS_SIGNAL_FLAGS_MATCH_ARG0_PATH
, "/org/gtk/", "/org/gtk/Example", TRUE
);
805 test_match_rule (con
, G_DBUS_SIGNAL_FLAGS_MATCH_ARG0_PATH
, "/org/gtk/Example", "/org/gtk/", TRUE
);
806 test_match_rule (con
, G_DBUS_SIGNAL_FLAGS_MATCH_ARG0_PATH
, "/org/gtk/Example", "/org/gtk", FALSE
);
807 test_match_rule (con
, G_DBUS_SIGNAL_FLAGS_MATCH_ARG0_PATH
, "/org/gtk+", "/org/gtk", FALSE
);
809 g_object_unref (con
);
813 /* ---------------------------------------------------------------------------------------------------- */
822 static GDBusMessage
*
823 filter_func (GDBusConnection
*connection
,
824 GDBusMessage
*message
,
828 FilterData
*data
= user_data
;
829 guint32 reply_serial
;
833 reply_serial
= g_dbus_message_get_reply_serial (message
);
834 if (reply_serial
== data
->serial
)
835 data
->num_handled
+= 1;
839 data
->num_outgoing
+= 1;
848 gboolean alter_incoming
;
849 gboolean alter_outgoing
;
852 static GDBusMessage
*
853 other_filter_func (GDBusConnection
*connection
,
854 GDBusMessage
*message
,
858 FilterEffects
*effects
= user_data
;
863 alter
= effects
->alter_incoming
;
865 alter
= effects
->alter_outgoing
;
874 copy
= g_dbus_message_copy (message
, NULL
);
875 g_object_unref (message
);
877 body
= g_dbus_message_get_body (copy
);
878 g_variant_get (body
, "(s)", &s
);
879 s2
= g_strdup_printf ("MOD: %s", s
);
880 g_dbus_message_set_body (copy
, g_variant_new ("(s)", s2
));
895 test_connection_filter_name_owner_changed_signal_handler (GDBusConnection
*connection
,
896 const gchar
*sender_name
,
897 const gchar
*object_path
,
898 const gchar
*interface_name
,
899 const gchar
*signal_name
,
900 GVariant
*parameters
,
904 const gchar
*old_owner
;
905 const gchar
*new_owner
;
907 g_variant_get (parameters
,
913 if (g_strcmp0 (name
, "com.example.TestService") == 0 && strlen (new_owner
) > 0)
915 g_main_loop_quit (loop
);
920 test_connection_filter_on_timeout (gpointer user_data
)
922 g_printerr ("Timeout waiting 30 sec on service\n");
923 g_assert_not_reached ();
928 test_connection_filter (void)
937 guint timeout_mainloop_id
;
938 guint signal_handler_id
;
939 FilterEffects effects
;
943 memset (&data
, '\0', sizeof (FilterData
));
948 c
= g_bus_get_sync (G_BUS_TYPE_SESSION
, NULL
, &error
);
949 g_assert_no_error (error
);
950 g_assert (c
!= NULL
);
952 filter_id
= g_dbus_connection_add_filter (c
,
957 m
= g_dbus_message_new_method_call ("org.freedesktop.DBus", /* name */
958 "/org/freedesktop/DBus", /* path */
959 "org.freedesktop.DBus", /* interface */
961 g_dbus_message_set_body (m
, g_variant_new ("(s)", "org.freedesktop.DBus"));
963 g_dbus_connection_send_message (c
, m
, G_DBUS_SEND_MESSAGE_FLAGS_NONE
, &data
.serial
, &error
);
964 g_assert_no_error (error
);
966 while (data
.num_handled
== 0)
969 m2
= g_dbus_message_copy (m
, &error
);
970 g_assert_no_error (error
);
971 g_dbus_connection_send_message (c
, m2
, G_DBUS_SEND_MESSAGE_FLAGS_NONE
, &data
.serial
, &error
);
973 g_assert_no_error (error
);
975 while (data
.num_handled
== 1)
978 m2
= g_dbus_message_copy (m
, &error
);
979 g_assert_no_error (error
);
980 g_dbus_message_set_serial (m2
, data
.serial
);
981 /* lock the message to test PRESERVE_SERIAL flag. */
982 g_dbus_message_lock (m2
);
983 g_dbus_connection_send_message (c
, m2
, G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL
, &data
.serial
, &error
);
985 g_assert_no_error (error
);
987 while (data
.num_handled
== 2)
990 m2
= g_dbus_message_copy (m
, &error
);
991 g_assert_no_error (error
);
992 r
= g_dbus_connection_send_message_with_reply_sync (c
,
994 G_DBUS_SEND_MESSAGE_FLAGS_NONE
,
997 NULL
, /* GCancellable */
1000 g_assert_no_error (error
);
1001 g_assert (r
!= NULL
);
1003 g_assert_cmpint (data
.num_handled
, ==, 4);
1005 g_dbus_connection_remove_filter (c
, filter_id
);
1007 m2
= g_dbus_message_copy (m
, &error
);
1008 g_assert_no_error (error
);
1009 r
= g_dbus_connection_send_message_with_reply_sync (c
,
1011 G_DBUS_SEND_MESSAGE_FLAGS_NONE
,
1014 NULL
, /* GCancellable */
1016 g_object_unref (m2
);
1017 g_assert_no_error (error
);
1018 g_assert (r
!= NULL
);
1020 g_assert_cmpint (data
.num_handled
, ==, 4);
1021 g_assert_cmpint (data
.num_outgoing
, ==, 4);
1023 /* wait for service to be available */
1024 signal_handler_id
= g_dbus_connection_signal_subscribe (c
,
1025 "org.freedesktop.DBus", /* sender */
1026 "org.freedesktop.DBus",
1028 "/org/freedesktop/DBus",
1030 G_DBUS_SIGNAL_FLAGS_NONE
,
1031 test_connection_filter_name_owner_changed_signal_handler
,
1034 g_assert_cmpint (signal_handler_id
, !=, 0);
1036 /* this is safe; testserver will exit once the bus goes away */
1037 g_assert (g_spawn_command_line_async (g_test_get_filename (G_TEST_BUILT
, "gdbus-testserver", NULL
), NULL
));
1039 timeout_mainloop_id
= g_timeout_add (30000, test_connection_filter_on_timeout
, NULL
);
1040 g_main_loop_run (loop
);
1041 g_source_remove (timeout_mainloop_id
);
1042 g_dbus_connection_signal_unsubscribe (c
, signal_handler_id
);
1044 /* now test some combinations... */
1045 filter_id
= g_dbus_connection_add_filter (c
,
1050 effects
.alter_incoming
= FALSE
;
1051 effects
.alter_outgoing
= FALSE
;
1053 result
= g_dbus_connection_call_sync (c
,
1054 "com.example.TestService", /* bus name */
1055 "/com/example/TestObject", /* object path */
1056 "com.example.Frob", /* interface name */
1057 "HelloWorld", /* method name */
1058 g_variant_new ("(s)", "Cat"), /* parameters */
1059 G_VARIANT_TYPE ("(s)"), /* return type */
1060 G_DBUS_CALL_FLAGS_NONE
,
1064 g_assert_no_error (error
);
1065 g_variant_get (result
, "(&s)", &s
);
1066 g_assert_cmpstr (s
, ==, "You greeted me with 'Cat'. Thanks!");
1067 g_variant_unref (result
);
1069 effects
.alter_incoming
= TRUE
;
1070 effects
.alter_outgoing
= TRUE
;
1072 result
= g_dbus_connection_call_sync (c
,
1073 "com.example.TestService", /* bus name */
1074 "/com/example/TestObject", /* object path */
1075 "com.example.Frob", /* interface name */
1076 "HelloWorld", /* method name */
1077 g_variant_new ("(s)", "Cat"), /* parameters */
1078 G_VARIANT_TYPE ("(s)"), /* return type */
1079 G_DBUS_CALL_FLAGS_NONE
,
1083 g_assert_no_error (error
);
1084 g_variant_get (result
, "(&s)", &s
);
1085 g_assert_cmpstr (s
, ==, "MOD: You greeted me with 'MOD: Cat'. Thanks!");
1086 g_variant_unref (result
);
1089 g_dbus_connection_remove_filter (c
, filter_id
);
1094 session_bus_down ();
1097 /* ---------------------------------------------------------------------------------------------------- */
1099 #define NUM_THREADS 50
1102 send_bogus_message (GDBusConnection
*c
, guint32
*out_serial
)
1107 m
= g_dbus_message_new_method_call ("org.freedesktop.DBus", /* name */
1108 "/org/freedesktop/DBus", /* path */
1109 "org.freedesktop.DBus", /* interface */
1111 g_dbus_message_set_body (m
, g_variant_new ("(s)", "org.freedesktop.DBus"));
1113 g_dbus_connection_send_message (c
, m
, G_DBUS_SEND_MESSAGE_FLAGS_NONE
, out_serial
, &error
);
1114 g_assert_no_error (error
);
1118 #define SLEEP_USEC (100 * 1000)
1121 serials_thread_func (GDBusConnection
*c
)
1123 guint32 message_serial
;
1126 /* No calls on this thread yet */
1127 g_assert_cmpint (g_dbus_connection_get_last_serial(c
), ==, 0);
1129 /* Send a bogus message and store its serial */
1131 send_bogus_message (c
, &message_serial
);
1133 /* Give it some time to actually send the message out. 10 seconds
1134 * should be plenty, even on slow machines. */
1135 for (i
= 0; i
< 10 * G_USEC_PER_SEC
/ SLEEP_USEC
; i
++)
1137 if (g_dbus_connection_get_last_serial(c
) != 0)
1140 g_usleep (SLEEP_USEC
);
1143 g_assert_cmpint (g_dbus_connection_get_last_serial(c
), !=, 0);
1144 g_assert_cmpint (g_dbus_connection_get_last_serial(c
), ==, message_serial
);
1150 test_connection_serials (void)
1154 GThread
*pool
[NUM_THREADS
];
1160 c
= g_bus_get_sync (G_BUS_TYPE_SESSION
, NULL
, &error
);
1161 g_assert_no_error (error
);
1162 g_assert (c
!= NULL
);
1164 /* Status after initialization */
1165 g_assert_cmpint (g_dbus_connection_get_last_serial (c
), ==, 1);
1167 /* Send a bogus message */
1168 send_bogus_message (c
, NULL
);
1169 g_assert_cmpint (g_dbus_connection_get_last_serial (c
), ==, 2);
1171 /* Start the threads */
1172 for (i
= 0; i
< NUM_THREADS
; i
++)
1173 pool
[i
] = g_thread_new (NULL
, (GThreadFunc
) serials_thread_func
, c
);
1175 /* Wait until threads are finished */
1176 for (i
= 0; i
< NUM_THREADS
; i
++)
1177 g_thread_join (pool
[i
]);
1179 /* No calls in between on this thread, should be the last value */
1180 g_assert_cmpint (g_dbus_connection_get_last_serial (c
), ==, 2);
1182 send_bogus_message (c
, NULL
);
1184 /* All above calls + calls in threads */
1185 g_assert_cmpint (g_dbus_connection_get_last_serial (c
), ==, 3 + NUM_THREADS
);
1189 session_bus_down ();
1192 /* ---------------------------------------------------------------------------------------------------- */
1195 test_connection_basic (void)
1197 GDBusConnection
*connection
;
1199 GDBusCapabilityFlags flags
;
1203 gboolean exit_on_close
;
1205 GCredentials
*credentials
;
1210 connection
= g_bus_get_sync (G_BUS_TYPE_SESSION
, NULL
, &error
);
1211 g_assert_no_error (error
);
1212 g_assert (connection
!= NULL
);
1214 flags
= g_dbus_connection_get_capabilities (connection
);
1215 g_assert (flags
== G_DBUS_CAPABILITY_FLAGS_NONE
||
1216 flags
== G_DBUS_CAPABILITY_FLAGS_UNIX_FD_PASSING
);
1218 credentials
= g_dbus_connection_get_peer_credentials (connection
);
1219 g_assert (credentials
== NULL
);
1221 g_object_get (connection
,
1224 "unique-name", &name
,
1226 "exit-on-close", &exit_on_close
,
1227 "capabilities", &flags
,
1230 g_assert (G_IS_IO_STREAM (stream
));
1231 g_assert (g_dbus_is_guid (guid
));
1232 g_assert (g_dbus_is_unique_name (name
));
1234 g_assert (exit_on_close
);
1235 g_assert (flags
== G_DBUS_CAPABILITY_FLAGS_NONE
||
1236 flags
== G_DBUS_CAPABILITY_FLAGS_UNIX_FD_PASSING
);
1237 g_object_unref (stream
);
1241 g_object_unref (connection
);
1243 session_bus_down ();
1246 /* ---------------------------------------------------------------------------------------------------- */
1253 g_test_init (&argc
, &argv
, NULL
);
1255 /* all the tests rely on a shared main loop */
1256 loop
= g_main_loop_new (NULL
, FALSE
);
1258 g_test_dbus_unset ();
1260 /* gdbus cleanup is pretty racy due to worker threads, so always do this test first */
1261 g_test_add_func ("/gdbus/connection/bus-failure", test_connection_bus_failure
);
1263 g_test_add_func ("/gdbus/connection/basic", test_connection_basic
);
1264 g_test_add_func ("/gdbus/connection/life-cycle", test_connection_life_cycle
);
1265 g_test_add_func ("/gdbus/connection/send", test_connection_send
);
1266 g_test_add_func ("/gdbus/connection/signals", test_connection_signals
);
1267 g_test_add_func ("/gdbus/connection/signal-match-rules", test_connection_signal_match_rules
);
1268 g_test_add_func ("/gdbus/connection/filter", test_connection_filter
);
1269 g_test_add_func ("/gdbus/connection/serials", test_connection_serials
);
1272 g_main_loop_unref (loop
);