Bug 618882 – No way to ensure that a message is sent
[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   GDBusConnection *c;
43   GDBusConnection *c2;
44   GError *error;
45
46   error = NULL;
47
48   /*
49    * Check for correct behavior when no bus is present
50    *
51    */
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));
55   g_assert (c == NULL);
56   g_error_free (error);
57   error = NULL;
58
59   /*
60    *  Check for correct behavior when a bus is present
61    */
62   session_bus_up ();
63   /* case 1 */
64   c = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
65   g_assert_no_error (error);
66   g_assert (c != NULL);
67   g_assert (!g_dbus_connection_is_closed (c));
68
69   /*
70    * Check that singleton handling work
71    */
72   c2 = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
73   g_assert_no_error (error);
74   g_assert (c2 != NULL);
75   g_assert (c == c2);
76   g_object_unref (c2);
77
78   /*
79    * Check that private connections work
80    */
81   c2 = _g_bus_get_priv (G_BUS_TYPE_SESSION, NULL, &error);
82   g_assert_no_error (error);
83   g_assert (c2 != NULL);
84   g_assert (c != c2);
85   g_object_unref (c2);
86
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));
94   g_object_unref (c2);
95
96   /*
97    *  Check for correct behavior when the bus goes away
98    *
99    */
100   g_assert (!g_dbus_connection_is_closed (c));
101   g_dbus_connection_set_exit_on_close (c, FALSE);
102   session_bus_down ();
103   if (!g_dbus_connection_is_closed (c))
104     _g_assert_signal_received (c, "closed");
105   g_assert (g_dbus_connection_is_closed (c));
106
107   _g_object_wait_for_single_ref (c);
108   g_object_unref (c);
109 }
110
111 /* ---------------------------------------------------------------------------------------------------- */
112 /* Test that sending and receiving messages work as expected */
113 /* ---------------------------------------------------------------------------------------------------- */
114
115 static void
116 msg_cb_expect_error_disconnected (GDBusConnection *connection,
117                                   GAsyncResult    *res,
118                                   gpointer         user_data)
119 {
120   GError *error;
121   GVariant *result;
122
123   error = NULL;
124   result = g_dbus_connection_call_finish (connection,
125                                           res,
126                                           &error);
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);
131
132   g_main_loop_quit (loop);
133 }
134
135 static void
136 msg_cb_expect_error_unknown_method (GDBusConnection *connection,
137                                     GAsyncResult    *res,
138                                     gpointer         user_data)
139 {
140   GError *error;
141   GVariant *result;
142
143   error = NULL;
144   result = g_dbus_connection_call_finish (connection,
145                                           res,
146                                           &error);
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);
150
151   g_main_loop_quit (loop);
152 }
153
154 static void
155 msg_cb_expect_success (GDBusConnection *connection,
156                        GAsyncResult    *res,
157                        gpointer         user_data)
158 {
159   GError *error;
160   GVariant *result;
161
162   error = NULL;
163   result = g_dbus_connection_call_finish (connection,
164                                           res,
165                                           &error);
166   g_assert_no_error (error);
167   g_assert (result != NULL);
168   g_variant_unref (result);
169
170   g_main_loop_quit (loop);
171 }
172
173 static void
174 msg_cb_expect_error_cancelled (GDBusConnection *connection,
175                                GAsyncResult    *res,
176                                gpointer         user_data)
177 {
178   GError *error;
179   GVariant *result;
180
181   error = NULL;
182   result = g_dbus_connection_call_finish (connection,
183                                           res,
184                                           &error);
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);
189
190   g_main_loop_quit (loop);
191 }
192
193 static void
194 msg_cb_expect_error_cancelled_2 (GDBusConnection *connection,
195                                  GAsyncResult    *res,
196                                  gpointer         user_data)
197 {
198   GError *error;
199   GVariant *result;
200
201   error = NULL;
202   result = g_dbus_connection_call_finish (connection,
203                                           res,
204                                           &error);
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);
209
210   g_main_loop_quit (loop);
211 }
212
213 /* ---------------------------------------------------------------------------------------------------- */
214
215 static void
216 test_connection_send (void)
217 {
218   GDBusConnection *c;
219   GCancellable *ca;
220
221   session_bus_up ();
222
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));
227
228   /*
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.
232    */
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 */
240                           NULL, NULL,
241                           G_DBUS_CALL_FLAGS_NONE,
242                           -1,
243                           ca,
244                           (GAsyncReadyCallback) msg_cb_expect_error_cancelled,
245                           NULL);
246   g_main_loop_run (loop);
247   g_object_unref (ca);
248
249   /*
250    * Check that we get a reply to the GetId() method call.
251    */
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 */
257                           NULL, NULL,
258                           G_DBUS_CALL_FLAGS_NONE,
259                           -1,
260                           NULL,
261                           (GAsyncReadyCallback) msg_cb_expect_success,
262                           NULL);
263   g_main_loop_run (loop);
264
265   /*
266    * Check that we get an error reply to the NonExistantMethod() method call.
267    */
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 */
273                           NULL, NULL,
274                           G_DBUS_CALL_FLAGS_NONE,
275                           -1,
276                           NULL,
277                           (GAsyncReadyCallback) msg_cb_expect_error_unknown_method,
278                           NULL);
279   g_main_loop_run (loop);
280
281   /*
282    * Check that cancellation works when the message is already in flight.
283    */
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 */
290                           NULL, NULL,
291                           G_DBUS_CALL_FLAGS_NONE,
292                           -1,
293                           ca,
294                           (GAsyncReadyCallback) msg_cb_expect_error_cancelled_2,
295                           NULL);
296   g_cancellable_cancel (ca);
297   g_main_loop_run (loop);
298   g_object_unref (ca);
299
300   /*
301    * Check that we get an error when sending to a connection that is disconnected.
302    */
303   g_dbus_connection_set_exit_on_close (c, FALSE);
304   session_bus_down ();
305   _g_assert_signal_received (c, "closed");
306   g_assert (g_dbus_connection_is_closed (c));
307
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 */
313                           NULL, NULL,
314                           G_DBUS_CALL_FLAGS_NONE,
315                           -1,
316                           NULL,
317                           (GAsyncReadyCallback) msg_cb_expect_error_disconnected,
318                           NULL);
319   g_main_loop_run (loop);
320
321   _g_object_wait_for_single_ref (c);
322   g_object_unref (c);
323 }
324
325 /* ---------------------------------------------------------------------------------------------------- */
326 /* Connection signal tests */
327 /* ---------------------------------------------------------------------------------------------------- */
328
329 static void
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,
336                                 gpointer         user_data)
337 {
338   gint *counter = user_data;
339   *counter += 1;
340
341   /*g_debug ("in test_connection_signal_handler (sender=%s path=%s interface=%s member=%s)",
342            sender_name,
343            object_path,
344            interface_name,
345            signal_name);*/
346
347   g_main_loop_quit (loop);
348 }
349
350 static gboolean
351 test_connection_signal_quit_mainloop (gpointer user_data)
352 {
353   gboolean *quit_mainloop_fired = user_data;
354   *quit_mainloop_fired = TRUE;
355   g_main_loop_quit (loop);
356   return TRUE;
357 }
358
359 static void
360 test_connection_signals (void)
361 {
362   GDBusConnection *c1;
363   GDBusConnection *c2;
364   GDBusConnection *c3;
365   guint s1;
366   guint s1b;
367   guint s2;
368   guint s3;
369   gint count_s1;
370   gint count_s1b;
371   gint count_s2;
372   gint count_name_owner_changed;
373   GError *error;
374   gboolean ret;
375   GVariant *result;
376
377   error = NULL;
378
379   /*
380    * Bring up first separate connections
381    */
382   session_bus_up ();
383   /* if running with dbus-monitor, it claims the name :1.0 - so if we don't run with the monitor
384    * emulate this
385    */
386   if (g_getenv ("G_DBUS_MONITOR") == NULL)
387     {
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));
391       g_object_unref (c1);
392     }
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");
397
398   /*
399    * Install two signal handlers for the first connection
400    *
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)
403    *
404    * and then count how many times this signal handler was invoked.
405    */
406   s1 = g_dbus_connection_signal_subscribe (c1,
407                                            ":1.2",
408                                            "org.gtk.GDBus.ExampleInterface",
409                                            "Foo",
410                                            "/org/gtk/GDBus/ExampleInterface",
411                                            NULL,
412                                            test_connection_signal_handler,
413                                            &count_s1,
414                                            NULL);
415   s2 = g_dbus_connection_signal_subscribe (c1,
416                                            NULL, /* match any sender */
417                                            "org.gtk.GDBus.ExampleInterface",
418                                            "Foo",
419                                            "/org/gtk/GDBus/ExampleInterface",
420                                            NULL,
421                                            test_connection_signal_handler,
422                                            &count_s2,
423                                            NULL);
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 */
429                                            NULL,
430                                            test_connection_signal_handler,
431                                            &count_name_owner_changed,
432                                            NULL);
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.
436    */
437   s1b = g_dbus_connection_signal_subscribe (c1,
438                                            ":1.2",
439                                            "org.gtk.GDBus.ExampleInterface",
440                                            "Foo",
441                                            "/org/gtk/GDBus/ExampleInterface",
442                                            NULL,
443                                            test_connection_signal_handler,
444                                            &count_s1b,
445                                            NULL);
446   g_assert (s1 != 0);
447   g_assert (s1b != 0);
448   g_assert (s2 != 0);
449   g_assert (s3 != 0);
450
451   count_s1 = 0;
452   count_s1b = 0;
453   count_s2 = 0;
454   count_name_owner_changed = 0;
455
456   /*
457    * Bring up two other connections
458    */
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");
467
468   /*
469    * Make c2 emit "Foo" - we should catch it twice
470    *
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.
476    *
477    * To ensure this is not the case, do a synchronous call on c1.
478    */
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,
487                                         -1,
488                                         NULL,
489                                         &error);
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",
498                                        "Foo",
499                                        NULL,
500                                        &error);
501   g_assert_no_error (error);
502   g_assert (ret);
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);
507
508   /*
509    * Make c3 emit "Foo" - we should catch it only once
510    */
511   ret = g_dbus_connection_emit_signal (c3,
512                                        NULL, /* destination bus name */
513                                        "/org/gtk/GDBus/ExampleInterface",
514                                        "org.gtk.GDBus.ExampleInterface",
515                                        "Foo",
516                                        NULL,
517                                        &error);
518   g_assert_no_error (error);
519   g_assert (ret);
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);
524
525   /*
526    * Also to check the total amount of NameOwnerChanged signals - use a 5 second ceiling
527    * to avoid spinning forever
528    */
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);
539
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);
544
545   _g_object_wait_for_single_ref (c1);
546   _g_object_wait_for_single_ref (c2);
547   _g_object_wait_for_single_ref (c3);
548
549   g_object_unref (c1);
550   g_object_unref (c2);
551   g_object_unref (c3);
552
553   session_bus_down ();
554 }
555
556 /* ---------------------------------------------------------------------------------------------------- */
557
558 typedef struct
559 {
560   guint num_handled;
561   guint num_outgoing;
562   guint32 serial;
563 } FilterData;
564
565 static gboolean
566 filter_func (GDBusConnection *connection,
567              GDBusMessage    *message,
568              gboolean         incoming,
569              gpointer         user_data)
570 {
571   FilterData *data = user_data;
572   guint32 reply_serial;
573
574   if (incoming)
575     {
576       reply_serial = g_dbus_message_get_reply_serial (message);
577       if (reply_serial == data->serial)
578         data->num_handled += 1;
579     }
580   else
581     {
582       data->num_outgoing += 1;
583     }
584
585   return FALSE;
586 }
587
588 static void
589 test_connection_filter (void)
590 {
591   GDBusConnection *c;
592   FilterData data;
593   GDBusMessage *m;
594   GDBusMessage *r;
595   GError *error;
596   guint filter_id;
597
598   memset (&data, '\0', sizeof (FilterData));
599
600   session_bus_up ();
601
602   error = NULL;
603   c = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
604   g_assert_no_error (error);
605   g_assert (c != NULL);
606
607   filter_id = g_dbus_connection_add_filter (c,
608                                             filter_func,
609                                             &data,
610                                             NULL);
611
612   m = g_dbus_message_new_method_call ("org.freedesktop.DBus", /* name */
613                                       "/org/freedesktop/DBus", /* path */
614                                       "org.freedesktop.DBus", /* interface */
615                                       "GetNameOwner");
616   g_dbus_message_set_body (m, g_variant_new ("(s)", "org.freedesktop.DBus"));
617   error = NULL;
618   g_dbus_connection_send_message (c, m, &data.serial, &error);
619   g_assert_no_error (error);
620
621   while (data.num_handled == 0)
622     g_thread_yield ();
623
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);
627
628   while (data.num_handled == 1)
629     g_thread_yield ();
630
631   g_dbus_message_set_serial (m, 0);
632   r = g_dbus_connection_send_message_with_reply_sync (c,
633                                                       m,
634                                                       -1,
635                                                       &data.serial,
636                                                       NULL, /* GCancellable */
637                                                       &error);
638   g_assert_no_error (error);
639   g_assert (r != NULL);
640   g_object_unref (r);
641   g_assert_cmpint (data.num_handled, ==, 3);
642
643   g_dbus_connection_remove_filter (c, filter_id);
644
645   g_dbus_message_set_serial (m, 0);
646   r = g_dbus_connection_send_message_with_reply_sync (c,
647                                                       m,
648                                                       -1,
649                                                       &data.serial,
650                                                       NULL, /* GCancellable */
651                                                       &error);
652   g_assert_no_error (error);
653   g_assert (r != NULL);
654   g_object_unref (r);
655   g_assert_cmpint (data.num_handled, ==, 3);
656   g_assert_cmpint (data.num_outgoing, ==, 3);
657
658   _g_object_wait_for_single_ref (c);
659   g_object_unref (c);
660   g_object_unref (m);
661
662   session_bus_down ();
663 }
664
665 /* ---------------------------------------------------------------------------------------------------- */
666
667 static void
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,
674                                       gpointer         user_data)
675 {
676   g_main_loop_quit (loop);
677 }
678
679 static gboolean
680 test_connection_flush_on_timeout (gpointer user_data)
681 {
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 ();
685   return FALSE;
686 }
687
688 static void
689 test_connection_flush (void)
690 {
691   GDBusConnection *connection;
692   GError *error;
693   guint n;
694   guint signal_handler_id;
695
696   session_bus_up ();
697
698   error = NULL;
699   connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
700   g_assert_no_error (error);
701   g_assert (connection != NULL);
702
703   signal_handler_id = g_dbus_connection_signal_subscribe (connection,
704                                                           NULL, /* sender */
705                                                           "org.gtk.GDBus.FlushInterface",
706                                                           "SomeSignal",
707                                                           "/org/gtk/GDBus/FlushObject",
708                                                           NULL,
709                                                           test_connection_flush_signal_handler,
710                                                           NULL,
711                                                           NULL);
712   g_assert_cmpint (signal_handler_id, !=, 0);
713
714   for (n = 0; n < 50; n++)
715     {
716       gboolean ret;
717       gint exit_status;
718       guint timeout_mainloop_id;
719
720       error = NULL;
721       ret = g_spawn_command_line_sync ("./gdbus-connection-flush-helper",
722                                        NULL, /* stdout */
723                                        NULL, /* stderr */
724                                        &exit_status,
725                                        &error);
726       g_assert_no_error (error);
727       g_assert (WIFEXITED (exit_status));
728       g_assert_cmpint (WEXITSTATUS (exit_status), ==, 0);
729       g_assert (ret);
730
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);
734     }
735
736   g_dbus_connection_signal_unsubscribe (connection, signal_handler_id);
737   _g_object_wait_for_single_ref (connection);
738   g_object_unref (connection);
739
740   session_bus_down ();
741 }
742
743 /* ---------------------------------------------------------------------------------------------------- */
744
745 int
746 main (int   argc,
747       char *argv[])
748 {
749   g_type_init ();
750   g_test_init (&argc, &argv, NULL);
751
752   /* all the tests rely on a shared main loop */
753   loop = g_main_loop_new (NULL, FALSE);
754
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().
757    */
758   g_unsetenv ("DISPLAY");
759   g_setenv ("DBUS_SESSION_BUS_ADDRESS", session_bus_get_temporary_address (), TRUE);
760
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);
766   return g_test_run();
767 }