GDBusConnection: Fix up g_dbus_connection_close()
[platform/upstream/glib.git] / gio / tests / gdbus-connection.c
1 /* GLib testing framework examples and tests
2  *
3  * Copyright (C) 2008-2010 Red Hat, Inc.
4  *
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.
9  *
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.
14  *
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.
19  *
20  * Author: David Zeuthen <davidz@redhat.com>
21  */
22
23 #include <gio/gio.h>
24 #include <unistd.h>
25 #include <string.h>
26
27 #include <sys/types.h>
28 #include <sys/wait.h>
29
30 #include "gdbus-tests.h"
31
32 /* all tests rely on a shared mainloop */
33 static GMainLoop *loop = NULL;
34
35 /* ---------------------------------------------------------------------------------------------------- */
36 /* Connection life-cycle testing */
37 /* ---------------------------------------------------------------------------------------------------- */
38
39 static void
40 test_connection_life_cycle (void)
41 {
42   gboolean ret;
43   GDBusConnection *c;
44   GDBusConnection *c2;
45   GError *error;
46
47   error = NULL;
48
49   /*
50    * Check for correct behavior when no bus is present
51    *
52    */
53   c = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
54   _g_assert_error_domain (error, G_IO_ERROR);
55   g_assert (!g_dbus_error_is_remote_error (error));
56   g_assert (c == NULL);
57   g_error_free (error);
58   error = NULL;
59
60   /*
61    *  Check for correct behavior when a bus is present
62    */
63   session_bus_up ();
64   /* case 1 */
65   c = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
66   g_assert_no_error (error);
67   g_assert (c != NULL);
68   g_assert (!g_dbus_connection_is_closed (c));
69
70   /*
71    * Check that singleton handling work
72    */
73   c2 = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
74   g_assert_no_error (error);
75   g_assert (c2 != NULL);
76   g_assert (c == c2);
77   g_object_unref (c2);
78
79   /*
80    * Check that private connections work
81    */
82   c2 = _g_bus_get_priv (G_BUS_TYPE_SESSION, NULL, &error);
83   g_assert_no_error (error);
84   g_assert (c2 != NULL);
85   g_assert (c != c2);
86   g_object_unref (c2);
87
88   c2 = _g_bus_get_priv (G_BUS_TYPE_SESSION, NULL, &error);
89   g_assert_no_error (error);
90   g_assert (c2 != NULL);
91   g_assert (!g_dbus_connection_is_closed (c2));
92   ret = g_dbus_connection_close_sync (c2, NULL, &error);
93   g_assert_no_error (error);
94   g_assert (ret);
95   _g_assert_signal_received (c2, "closed");
96   g_assert (g_dbus_connection_is_closed (c2));
97   ret = g_dbus_connection_close_sync (c2, NULL, &error);
98   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CLOSED);
99   g_assert (!ret);
100   g_object_unref (c2);
101
102   /*
103    *  Check for correct behavior when the bus goes away
104    *
105    */
106   g_assert (!g_dbus_connection_is_closed (c));
107   g_dbus_connection_set_exit_on_close (c, FALSE);
108   session_bus_down ();
109   if (!g_dbus_connection_is_closed (c))
110     _g_assert_signal_received (c, "closed");
111   g_assert (g_dbus_connection_is_closed (c));
112
113   _g_object_wait_for_single_ref (c);
114   g_object_unref (c);
115 }
116
117 /* ---------------------------------------------------------------------------------------------------- */
118 /* Test that sending and receiving messages work as expected */
119 /* ---------------------------------------------------------------------------------------------------- */
120
121 static void
122 msg_cb_expect_error_disconnected (GDBusConnection *connection,
123                                   GAsyncResult    *res,
124                                   gpointer         user_data)
125 {
126   GError *error;
127   GVariant *result;
128
129   error = NULL;
130   result = g_dbus_connection_call_finish (connection,
131                                           res,
132                                           &error);
133   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CLOSED);
134   g_assert (!g_dbus_error_is_remote_error (error));
135   g_error_free (error);
136   g_assert (result == NULL);
137
138   g_main_loop_quit (loop);
139 }
140
141 static void
142 msg_cb_expect_error_unknown_method (GDBusConnection *connection,
143                                     GAsyncResult    *res,
144                                     gpointer         user_data)
145 {
146   GError *error;
147   GVariant *result;
148
149   error = NULL;
150   result = g_dbus_connection_call_finish (connection,
151                                           res,
152                                           &error);
153   g_assert_error (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD);
154   g_assert (g_dbus_error_is_remote_error (error));
155   g_assert (result == NULL);
156
157   g_main_loop_quit (loop);
158 }
159
160 static void
161 msg_cb_expect_success (GDBusConnection *connection,
162                        GAsyncResult    *res,
163                        gpointer         user_data)
164 {
165   GError *error;
166   GVariant *result;
167
168   error = NULL;
169   result = g_dbus_connection_call_finish (connection,
170                                           res,
171                                           &error);
172   g_assert_no_error (error);
173   g_assert (result != NULL);
174   g_variant_unref (result);
175
176   g_main_loop_quit (loop);
177 }
178
179 static void
180 msg_cb_expect_error_cancelled (GDBusConnection *connection,
181                                GAsyncResult    *res,
182                                gpointer         user_data)
183 {
184   GError *error;
185   GVariant *result;
186
187   error = NULL;
188   result = g_dbus_connection_call_finish (connection,
189                                           res,
190                                           &error);
191   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
192   g_assert (!g_dbus_error_is_remote_error (error));
193   g_error_free (error);
194   g_assert (result == NULL);
195
196   g_main_loop_quit (loop);
197 }
198
199 static void
200 msg_cb_expect_error_cancelled_2 (GDBusConnection *connection,
201                                  GAsyncResult    *res,
202                                  gpointer         user_data)
203 {
204   GError *error;
205   GVariant *result;
206
207   error = NULL;
208   result = g_dbus_connection_call_finish (connection,
209                                           res,
210                                           &error);
211   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
212   g_assert (!g_dbus_error_is_remote_error (error));
213   g_error_free (error);
214   g_assert (result == NULL);
215
216   g_main_loop_quit (loop);
217 }
218
219 /* ---------------------------------------------------------------------------------------------------- */
220
221 static void
222 test_connection_send (void)
223 {
224   GDBusConnection *c;
225   GCancellable *ca;
226
227   session_bus_up ();
228
229   /* First, get an unopened connection */
230   c = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
231   g_assert (c != NULL);
232   g_assert (!g_dbus_connection_is_closed (c));
233
234   /*
235    * Check that we never actually send a message if the GCancellable
236    * is already cancelled - i.e.  we should get #G_IO_ERROR_CANCELLED
237    * when the actual connection is not up.
238    */
239   ca = g_cancellable_new ();
240   g_cancellable_cancel (ca);
241   g_dbus_connection_call (c,
242                           "org.freedesktop.DBus",  /* bus_name */
243                           "/org/freedesktop/DBus", /* object path */
244                           "org.freedesktop.DBus",  /* interface name */
245                           "GetId",                 /* method name */
246                           NULL, NULL,
247                           G_DBUS_CALL_FLAGS_NONE,
248                           -1,
249                           ca,
250                           (GAsyncReadyCallback) msg_cb_expect_error_cancelled,
251                           NULL);
252   g_main_loop_run (loop);
253   g_object_unref (ca);
254
255   /*
256    * Check that we get a reply to the GetId() method call.
257    */
258   g_dbus_connection_call (c,
259                           "org.freedesktop.DBus",  /* bus_name */
260                           "/org/freedesktop/DBus", /* object path */
261                           "org.freedesktop.DBus",  /* interface name */
262                           "GetId",                 /* method name */
263                           NULL, NULL,
264                           G_DBUS_CALL_FLAGS_NONE,
265                           -1,
266                           NULL,
267                           (GAsyncReadyCallback) msg_cb_expect_success,
268                           NULL);
269   g_main_loop_run (loop);
270
271   /*
272    * Check that we get an error reply to the NonExistantMethod() method call.
273    */
274   g_dbus_connection_call (c,
275                           "org.freedesktop.DBus",  /* bus_name */
276                           "/org/freedesktop/DBus", /* object path */
277                           "org.freedesktop.DBus",  /* interface name */
278                           "NonExistantMethod",     /* method name */
279                           NULL, NULL,
280                           G_DBUS_CALL_FLAGS_NONE,
281                           -1,
282                           NULL,
283                           (GAsyncReadyCallback) msg_cb_expect_error_unknown_method,
284                           NULL);
285   g_main_loop_run (loop);
286
287   /*
288    * Check that cancellation works when the message is already in flight.
289    */
290   ca = g_cancellable_new ();
291   g_dbus_connection_call (c,
292                           "org.freedesktop.DBus",  /* bus_name */
293                           "/org/freedesktop/DBus", /* object path */
294                           "org.freedesktop.DBus",  /* interface name */
295                           "GetId",                 /* method name */
296                           NULL, NULL,
297                           G_DBUS_CALL_FLAGS_NONE,
298                           -1,
299                           ca,
300                           (GAsyncReadyCallback) msg_cb_expect_error_cancelled_2,
301                           NULL);
302   g_cancellable_cancel (ca);
303   g_main_loop_run (loop);
304   g_object_unref (ca);
305
306   /*
307    * Check that we get an error when sending to a connection that is disconnected.
308    */
309   g_dbus_connection_set_exit_on_close (c, FALSE);
310   session_bus_down ();
311   _g_assert_signal_received (c, "closed");
312   g_assert (g_dbus_connection_is_closed (c));
313
314   g_dbus_connection_call (c,
315                           "org.freedesktop.DBus",  /* bus_name */
316                           "/org/freedesktop/DBus", /* object path */
317                           "org.freedesktop.DBus",  /* interface name */
318                           "GetId",                 /* method name */
319                           NULL, NULL,
320                           G_DBUS_CALL_FLAGS_NONE,
321                           -1,
322                           NULL,
323                           (GAsyncReadyCallback) msg_cb_expect_error_disconnected,
324                           NULL);
325   g_main_loop_run (loop);
326
327   _g_object_wait_for_single_ref (c);
328   g_object_unref (c);
329 }
330
331 /* ---------------------------------------------------------------------------------------------------- */
332 /* Connection signal tests */
333 /* ---------------------------------------------------------------------------------------------------- */
334
335 static void
336 test_connection_signal_handler (GDBusConnection  *connection,
337                                 const gchar      *sender_name,
338                                 const gchar      *object_path,
339                                 const gchar      *interface_name,
340                                 const gchar      *signal_name,
341                                 GVariant         *parameters,
342                                 gpointer         user_data)
343 {
344   gint *counter = user_data;
345   *counter += 1;
346
347   /*g_debug ("in test_connection_signal_handler (sender=%s path=%s interface=%s member=%s)",
348            sender_name,
349            object_path,
350            interface_name,
351            signal_name);*/
352
353   g_main_loop_quit (loop);
354 }
355
356 static gboolean
357 test_connection_signal_quit_mainloop (gpointer user_data)
358 {
359   gboolean *quit_mainloop_fired = user_data;
360   *quit_mainloop_fired = TRUE;
361   g_main_loop_quit (loop);
362   return TRUE;
363 }
364
365 static void
366 test_connection_signals (void)
367 {
368   GDBusConnection *c1;
369   GDBusConnection *c2;
370   GDBusConnection *c3;
371   guint s1;
372   guint s1b;
373   guint s2;
374   guint s3;
375   gint count_s1;
376   gint count_s1b;
377   gint count_s2;
378   gint count_name_owner_changed;
379   GError *error;
380   gboolean ret;
381   GVariant *result;
382
383   error = NULL;
384
385   /*
386    * Bring up first separate connections
387    */
388   session_bus_up ();
389   /* if running with dbus-monitor, it claims the name :1.0 - so if we don't run with the monitor
390    * emulate this
391    */
392   if (g_getenv ("G_DBUS_MONITOR") == NULL)
393     {
394       c1 = _g_bus_get_priv (G_BUS_TYPE_SESSION, NULL, NULL);
395       g_assert (c1 != NULL);
396       g_assert (!g_dbus_connection_is_closed (c1));
397       g_object_unref (c1);
398     }
399   c1 = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
400   g_assert (c1 != NULL);
401   g_assert (!g_dbus_connection_is_closed (c1));
402   g_assert_cmpstr (g_dbus_connection_get_unique_name (c1), ==, ":1.1");
403
404   /*
405    * Install two signal handlers for the first connection
406    *
407    *  - Listen to the signal "Foo" from :1.2 (e.g. c2)
408    *  - Listen to the signal "Foo" from anyone (e.g. both c2 and c3)
409    *
410    * and then count how many times this signal handler was invoked.
411    */
412   s1 = g_dbus_connection_signal_subscribe (c1,
413                                            ":1.2",
414                                            "org.gtk.GDBus.ExampleInterface",
415                                            "Foo",
416                                            "/org/gtk/GDBus/ExampleInterface",
417                                            NULL,
418                                            test_connection_signal_handler,
419                                            &count_s1,
420                                            NULL);
421   s2 = g_dbus_connection_signal_subscribe (c1,
422                                            NULL, /* match any sender */
423                                            "org.gtk.GDBus.ExampleInterface",
424                                            "Foo",
425                                            "/org/gtk/GDBus/ExampleInterface",
426                                            NULL,
427                                            test_connection_signal_handler,
428                                            &count_s2,
429                                            NULL);
430   s3 = g_dbus_connection_signal_subscribe (c1,
431                                            "org.freedesktop.DBus",  /* sender */
432                                            "org.freedesktop.DBus",  /* interface */
433                                            "NameOwnerChanged",      /* member */
434                                            "/org/freedesktop/DBus", /* path */
435                                            NULL,
436                                            test_connection_signal_handler,
437                                            &count_name_owner_changed,
438                                            NULL);
439   /* Note that s1b is *just like* s1 - this is to catch a bug where N
440    * subscriptions of the same rule causes N calls to each of the N
441    * subscriptions instead of just 1 call to each of the N subscriptions.
442    */
443   s1b = g_dbus_connection_signal_subscribe (c1,
444                                            ":1.2",
445                                            "org.gtk.GDBus.ExampleInterface",
446                                            "Foo",
447                                            "/org/gtk/GDBus/ExampleInterface",
448                                            NULL,
449                                            test_connection_signal_handler,
450                                            &count_s1b,
451                                            NULL);
452   g_assert (s1 != 0);
453   g_assert (s1b != 0);
454   g_assert (s2 != 0);
455   g_assert (s3 != 0);
456
457   count_s1 = 0;
458   count_s1b = 0;
459   count_s2 = 0;
460   count_name_owner_changed = 0;
461
462   /*
463    * Bring up two other connections
464    */
465   c2 = _g_bus_get_priv (G_BUS_TYPE_SESSION, NULL, NULL);
466   g_assert (c2 != NULL);
467   g_assert (!g_dbus_connection_is_closed (c2));
468   g_assert_cmpstr (g_dbus_connection_get_unique_name (c2), ==, ":1.2");
469   c3 = _g_bus_get_priv (G_BUS_TYPE_SESSION, NULL, NULL);
470   g_assert (c3 != NULL);
471   g_assert (!g_dbus_connection_is_closed (c3));
472   g_assert_cmpstr (g_dbus_connection_get_unique_name (c3), ==, ":1.3");
473
474   /*
475    * Make c2 emit "Foo" - we should catch it twice
476    *
477    * Note that there is no way to be sure that the signal subscriptions
478    * on c1 are effective yet - for all we know, the AddMatch() messages
479    * could sit waiting in a buffer somewhere between this process and
480    * the message bus. And emitting signals on c2 (a completely other
481    * socket!) will not necessarily change this.
482    *
483    * To ensure this is not the case, do a synchronous call on c1.
484    */
485   result = g_dbus_connection_call_sync (c1,
486                                         "org.freedesktop.DBus",  /* bus name */
487                                         "/org/freedesktop/DBus", /* object path */
488                                         "org.freedesktop.DBus",  /* interface name */
489                                         "GetId",                 /* method name */
490                                         NULL,                    /* parameters */
491                                         NULL,                    /* return type */
492                                         G_DBUS_CALL_FLAGS_NONE,
493                                         -1,
494                                         NULL,
495                                         &error);
496   g_assert_no_error (error);
497   g_assert (result != NULL);
498   g_variant_unref (result);
499   /* now, emit the signal on c2 */
500   ret = g_dbus_connection_emit_signal (c2,
501                                        NULL, /* destination bus name */
502                                        "/org/gtk/GDBus/ExampleInterface",
503                                        "org.gtk.GDBus.ExampleInterface",
504                                        "Foo",
505                                        NULL,
506                                        &error);
507   g_assert_no_error (error);
508   g_assert (ret);
509   while (!(count_s1 >= 1 && count_s2 >= 1))
510     g_main_loop_run (loop);
511   g_assert_cmpint (count_s1, ==, 1);
512   g_assert_cmpint (count_s2, ==, 1);
513
514   /*
515    * Make c3 emit "Foo" - we should catch it only once
516    */
517   ret = g_dbus_connection_emit_signal (c3,
518                                        NULL, /* destination bus name */
519                                        "/org/gtk/GDBus/ExampleInterface",
520                                        "org.gtk.GDBus.ExampleInterface",
521                                        "Foo",
522                                        NULL,
523                                        &error);
524   g_assert_no_error (error);
525   g_assert (ret);
526   while (!(count_s1 == 1 && count_s2 == 2))
527     g_main_loop_run (loop);
528   g_assert_cmpint (count_s1, ==, 1);
529   g_assert_cmpint (count_s2, ==, 2);
530
531   /*
532    * Also to check the total amount of NameOwnerChanged signals - use a 5 second ceiling
533    * to avoid spinning forever
534    */
535   gboolean quit_mainloop_fired;
536   guint quit_mainloop_id;
537   quit_mainloop_fired = FALSE;
538   quit_mainloop_id = g_timeout_add (5000, test_connection_signal_quit_mainloop, &quit_mainloop_fired);
539   while (count_name_owner_changed < 2 && !quit_mainloop_fired)
540     g_main_loop_run (loop);
541   g_source_remove (quit_mainloop_id);
542   g_assert_cmpint (count_s1, ==, 1);
543   g_assert_cmpint (count_s2, ==, 2);
544   g_assert_cmpint (count_name_owner_changed, ==, 2);
545
546   g_dbus_connection_signal_unsubscribe (c1, s1);
547   g_dbus_connection_signal_unsubscribe (c1, s2);
548   g_dbus_connection_signal_unsubscribe (c1, s3);
549   g_dbus_connection_signal_unsubscribe (c1, s1b);
550
551   _g_object_wait_for_single_ref (c1);
552   _g_object_wait_for_single_ref (c2);
553   _g_object_wait_for_single_ref (c3);
554
555   g_object_unref (c1);
556   g_object_unref (c2);
557   g_object_unref (c3);
558
559   session_bus_down ();
560 }
561
562 /* ---------------------------------------------------------------------------------------------------- */
563
564 typedef struct
565 {
566   guint num_handled;
567   guint num_outgoing;
568   guint32 serial;
569 } FilterData;
570
571 static gboolean
572 filter_func (GDBusConnection *connection,
573              GDBusMessage    *message,
574              gboolean         incoming,
575              gpointer         user_data)
576 {
577   FilterData *data = user_data;
578   guint32 reply_serial;
579
580   if (incoming)
581     {
582       reply_serial = g_dbus_message_get_reply_serial (message);
583       if (reply_serial == data->serial)
584         data->num_handled += 1;
585     }
586   else
587     {
588       data->num_outgoing += 1;
589     }
590
591   return FALSE;
592 }
593
594 static void
595 test_connection_filter (void)
596 {
597   GDBusConnection *c;
598   FilterData data;
599   GDBusMessage *m;
600   GDBusMessage *r;
601   GError *error;
602   guint filter_id;
603
604   memset (&data, '\0', sizeof (FilterData));
605
606   session_bus_up ();
607
608   error = NULL;
609   c = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
610   g_assert_no_error (error);
611   g_assert (c != NULL);
612
613   filter_id = g_dbus_connection_add_filter (c,
614                                             filter_func,
615                                             &data,
616                                             NULL);
617
618   m = g_dbus_message_new_method_call ("org.freedesktop.DBus", /* name */
619                                       "/org/freedesktop/DBus", /* path */
620                                       "org.freedesktop.DBus", /* interface */
621                                       "GetNameOwner");
622   g_dbus_message_set_body (m, g_variant_new ("(s)", "org.freedesktop.DBus"));
623   error = NULL;
624   g_dbus_connection_send_message (c, m, &data.serial, &error);
625   g_assert_no_error (error);
626
627   while (data.num_handled == 0)
628     g_thread_yield ();
629
630   g_dbus_message_set_serial (m, 0);
631   g_dbus_connection_send_message (c, m, &data.serial, &error);
632   g_assert_no_error (error);
633
634   while (data.num_handled == 1)
635     g_thread_yield ();
636
637   g_dbus_message_set_serial (m, 0);
638   r = g_dbus_connection_send_message_with_reply_sync (c,
639                                                       m,
640                                                       -1,
641                                                       &data.serial,
642                                                       NULL, /* GCancellable */
643                                                       &error);
644   g_assert_no_error (error);
645   g_assert (r != NULL);
646   g_object_unref (r);
647   g_assert_cmpint (data.num_handled, ==, 3);
648
649   g_dbus_connection_remove_filter (c, filter_id);
650
651   g_dbus_message_set_serial (m, 0);
652   r = g_dbus_connection_send_message_with_reply_sync (c,
653                                                       m,
654                                                       -1,
655                                                       &data.serial,
656                                                       NULL, /* GCancellable */
657                                                       &error);
658   g_assert_no_error (error);
659   g_assert (r != NULL);
660   g_object_unref (r);
661   g_assert_cmpint (data.num_handled, ==, 3);
662   g_assert_cmpint (data.num_outgoing, ==, 3);
663
664   _g_object_wait_for_single_ref (c);
665   g_object_unref (c);
666   g_object_unref (m);
667
668   session_bus_down ();
669 }
670
671 /* ---------------------------------------------------------------------------------------------------- */
672
673 static void
674 test_connection_flush_signal_handler (GDBusConnection  *connection,
675                                       const gchar      *sender_name,
676                                       const gchar      *object_path,
677                                       const gchar      *interface_name,
678                                       const gchar      *signal_name,
679                                       GVariant         *parameters,
680                                       gpointer         user_data)
681 {
682   g_main_loop_quit (loop);
683 }
684
685 static gboolean
686 test_connection_flush_on_timeout (gpointer user_data)
687 {
688   guint iteration = GPOINTER_TO_UINT (user_data);
689   g_printerr ("Timeout waiting 1000 msec on iteration %d\n", iteration);
690   g_assert_not_reached ();
691   return FALSE;
692 }
693
694 static void
695 test_connection_flush (void)
696 {
697   GDBusConnection *connection;
698   GError *error;
699   guint n;
700   guint signal_handler_id;
701
702   session_bus_up ();
703
704   error = NULL;
705   connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
706   g_assert_no_error (error);
707   g_assert (connection != NULL);
708
709   signal_handler_id = g_dbus_connection_signal_subscribe (connection,
710                                                           NULL, /* sender */
711                                                           "org.gtk.GDBus.FlushInterface",
712                                                           "SomeSignal",
713                                                           "/org/gtk/GDBus/FlushObject",
714                                                           NULL,
715                                                           test_connection_flush_signal_handler,
716                                                           NULL,
717                                                           NULL);
718   g_assert_cmpint (signal_handler_id, !=, 0);
719
720   for (n = 0; n < 50; n++)
721     {
722       gboolean ret;
723       gint exit_status;
724       guint timeout_mainloop_id;
725
726       error = NULL;
727       ret = g_spawn_command_line_sync ("./gdbus-connection-flush-helper",
728                                        NULL, /* stdout */
729                                        NULL, /* stderr */
730                                        &exit_status,
731                                        &error);
732       g_assert_no_error (error);
733       g_assert (WIFEXITED (exit_status));
734       g_assert_cmpint (WEXITSTATUS (exit_status), ==, 0);
735       g_assert (ret);
736
737       timeout_mainloop_id = g_timeout_add (1000, test_connection_flush_on_timeout, GUINT_TO_POINTER (n));
738       g_main_loop_run (loop);
739       g_source_remove (timeout_mainloop_id);
740     }
741
742   g_dbus_connection_signal_unsubscribe (connection, signal_handler_id);
743   _g_object_wait_for_single_ref (connection);
744   g_object_unref (connection);
745
746   session_bus_down ();
747 }
748
749 /* ---------------------------------------------------------------------------------------------------- */
750
751 int
752 main (int   argc,
753       char *argv[])
754 {
755   g_type_init ();
756   g_test_init (&argc, &argv, NULL);
757
758   /* all the tests rely on a shared main loop */
759   loop = g_main_loop_new (NULL, FALSE);
760
761   /* all the tests use a session bus with a well-known address that we can bring up and down
762    * using session_bus_up() and session_bus_down().
763    */
764   g_unsetenv ("DISPLAY");
765   g_setenv ("DBUS_SESSION_BUS_ADDRESS", session_bus_get_temporary_address (), TRUE);
766
767   g_test_add_func ("/gdbus/connection-life-cycle", test_connection_life_cycle);
768   g_test_add_func ("/gdbus/connection-send", test_connection_send);
769   g_test_add_func ("/gdbus/connection-signals", test_connection_signals);
770   g_test_add_func ("/gdbus/connection-filter", test_connection_filter);
771   g_test_add_func ("/gdbus/connection-flush", test_connection_flush);
772   return g_test_run();
773 }