Imported Upstream version 2.72.3
[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.1 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, see <http://www.gnu.org/licenses/>.
17  *
18  * Author: David Zeuthen <davidz@redhat.com>
19  */
20
21 #include <gio/gio.h>
22 #include <unistd.h>
23 #include <string.h>
24
25 #include <sys/types.h>
26
27 #include "gdbus-tests.h"
28
29 /* all tests rely on a shared mainloop */
30 static GMainLoop *loop = NULL;
31
32 #if 0
33 G_GNUC_UNUSED static void
34 _log (const gchar *format, ...)
35 {
36   GTimeVal now;
37   time_t now_time;
38   struct tm *now_tm;
39   gchar time_buf[128];
40   gchar *str;
41   va_list var_args;
42
43   va_start (var_args, format);
44   str = g_strdup_vprintf (format, var_args);
45   va_end (var_args);
46
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);
51
52   g_printerr ("%s.%06d: %s\n",
53            time_buf, (gint) now.tv_usec / 1000,
54            str);
55   g_free (str);
56 }
57 #else
58 #define _log(...)
59 #endif
60
61 static gboolean
62 test_connection_quit_mainloop (gpointer user_data)
63 {
64   gboolean *quit_mainloop_fired = user_data;  /* (atomic) */
65   _log ("quit_mainloop_fired");
66   g_atomic_int_set (quit_mainloop_fired, TRUE);
67   g_main_loop_quit (loop);
68   return G_SOURCE_CONTINUE;
69 }
70
71 /* ---------------------------------------------------------------------------------------------------- */
72 /* Connection life-cycle testing */
73 /* ---------------------------------------------------------------------------------------------------- */
74
75 static const GDBusInterfaceInfo boo_interface_info =
76 {
77   -1,
78   "org.example.Boo",
79   (GDBusMethodInfo **) NULL,
80   (GDBusSignalInfo **) NULL,
81   (GDBusPropertyInfo **) NULL,
82   NULL,
83 };
84
85 static const GDBusInterfaceVTable boo_vtable =
86 {
87   NULL, /* _method_call */
88   NULL, /* _get_property */
89   NULL,  /* _set_property */
90   { 0 }
91 };
92
93 /* Runs in a worker thread. */
94 static GDBusMessage *
95 some_filter_func (GDBusConnection *connection,
96                   GDBusMessage    *message,
97                   gboolean         incoming,
98                   gpointer         user_data)
99 {
100   return message;
101 }
102
103 static void
104 on_name_owner_changed (GDBusConnection *connection,
105                        const gchar     *sender_name,
106                        const gchar     *object_path,
107                        const gchar     *interface_name,
108                        const gchar     *signal_name,
109                        GVariant        *parameters,
110                        gpointer         user_data)
111 {
112 }
113
114 static void
115 a_gdestroynotify_that_sets_a_gboolean_to_true_and_quits_loop (gpointer user_data)
116 {
117   gboolean *val = user_data;  /* (atomic) */
118   g_atomic_int_set (val, TRUE);
119   _log ("destroynotify fired for %p", val);
120   g_main_loop_quit (loop);
121 }
122
123 static void
124 test_connection_bus_failure (void)
125 {
126   GDBusConnection *c;
127   GError *error = NULL;
128
129   /*
130    * Check for correct behavior when no bus is present
131    *
132    */
133   c = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
134   g_assert_nonnull (error);
135   g_assert_false (g_dbus_error_is_remote_error (error));
136   g_assert_null (c);
137   g_error_free (error);
138 }
139
140 static void
141 test_connection_life_cycle (void)
142 {
143   gboolean ret;
144   GDBusConnection *c;
145   GDBusConnection *c2;
146   GError *error;
147   gboolean on_signal_registration_freed_called;  /* (atomic) */
148   gboolean on_filter_freed_called;  /* (atomic) */
149   gboolean on_register_object_freed_called;  /* (atomic) */
150   gboolean quit_mainloop_fired;  /* (atomic) */
151   guint quit_mainloop_id;
152   guint registration_id;
153
154   error = NULL;
155
156   /*
157    *  Check for correct behavior when a bus is present
158    */
159   session_bus_up ();
160   /* case 1 */
161   error = NULL;
162   c = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
163   g_assert_no_error (error);
164   g_assert_nonnull (c);
165   g_assert_false (g_dbus_connection_is_closed (c));
166
167   /*
168    * Check that singleton handling work
169    */
170   error = NULL;
171   c2 = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
172   g_assert_no_error (error);
173   g_assert_nonnull (c2);
174   g_assert_true (c == c2);
175   g_object_unref (c2);
176
177   /*
178    * Check that private connections work
179    */
180   c2 = _g_bus_get_priv (G_BUS_TYPE_SESSION, NULL, &error);
181   g_assert_no_error (error);
182   g_assert_nonnull (c2);
183   g_assert_true (c != c2);
184   g_object_unref (c2);
185
186   c2 = _g_bus_get_priv (G_BUS_TYPE_SESSION, NULL, &error);
187   g_assert_no_error (error);
188   g_assert_nonnull (c2);
189   g_assert_false (g_dbus_connection_is_closed (c2));
190   ret = g_dbus_connection_close_sync (c2, NULL, &error);
191   g_assert_no_error (error);
192   g_assert_true (ret);
193   _g_assert_signal_received (c2, "closed");
194   g_assert_true (g_dbus_connection_is_closed (c2));
195   ret = g_dbus_connection_close_sync (c2, NULL, &error);
196   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CLOSED);
197   g_error_free (error);
198   g_assert_false (ret);
199   g_object_unref (c2);
200
201   /*
202    * Check that the finalization code works
203    *
204    * (and that the GDestroyNotify for filters and objects and signal
205    * registrations are run as expected)
206    */
207   error = NULL;
208   c2 = _g_bus_get_priv (G_BUS_TYPE_SESSION, NULL, &error);
209   g_assert_no_error (error);
210   g_assert_nonnull (c2);
211   /* signal registration */
212   g_atomic_int_set (&on_signal_registration_freed_called, FALSE);
213   g_dbus_connection_signal_subscribe (c2,
214                                       "org.freedesktop.DBus", /* bus name */
215                                       "org.freedesktop.DBus", /* interface */
216                                       "NameOwnerChanged",     /* member */
217                                       "/org/freesktop/DBus",  /* path */
218                                       NULL,                   /* arg0 */
219                                       G_DBUS_SIGNAL_FLAGS_NONE,
220                                       on_name_owner_changed,
221                                       (gpointer) &on_signal_registration_freed_called,
222                                       a_gdestroynotify_that_sets_a_gboolean_to_true_and_quits_loop);
223   /* filter func */
224   g_atomic_int_set (&on_filter_freed_called, FALSE);
225   g_dbus_connection_add_filter (c2,
226                                 some_filter_func,
227                                 (gpointer) &on_filter_freed_called,
228                                 a_gdestroynotify_that_sets_a_gboolean_to_true_and_quits_loop);
229   /* object registration */
230   g_atomic_int_set (&on_register_object_freed_called, FALSE);
231   error = NULL;
232   registration_id = g_dbus_connection_register_object (c2,
233                                                        "/foo",
234                                                        (GDBusInterfaceInfo *) &boo_interface_info,
235                                                        &boo_vtable,
236                                                        (gpointer) &on_register_object_freed_called,
237                                                        a_gdestroynotify_that_sets_a_gboolean_to_true_and_quits_loop,
238                                                        &error);
239   g_assert_no_error (error);
240   g_assert_cmpuint (registration_id, >, 0);
241   /* ok, finalize the connection and check that all the GDestroyNotify functions are invoked as expected */
242   g_object_unref (c2);
243   g_atomic_int_set (&quit_mainloop_fired, FALSE);
244   quit_mainloop_id = g_timeout_add (30000, test_connection_quit_mainloop, (gpointer) &quit_mainloop_fired);
245   _log ("destroynotifies for\n"
246         " register_object %p\n"
247         " filter          %p\n"
248         " signal          %p",
249         &on_register_object_freed_called,
250         &on_filter_freed_called,
251         &on_signal_registration_freed_called);
252   while (TRUE)
253     {
254       if (g_atomic_int_get (&on_signal_registration_freed_called) &&
255           g_atomic_int_get (&on_filter_freed_called) &&
256           g_atomic_int_get (&on_register_object_freed_called))
257         break;
258       if (g_atomic_int_get (&quit_mainloop_fired))
259         break;
260       _log ("entering loop");
261       g_main_loop_run (loop);
262       _log ("exiting loop");
263     }
264   g_source_remove (quit_mainloop_id);
265   g_assert_true (g_atomic_int_get (&on_signal_registration_freed_called));
266   g_assert_true (g_atomic_int_get (&on_filter_freed_called));
267   g_assert_true (g_atomic_int_get (&on_register_object_freed_called));
268   g_assert_false (g_atomic_int_get (&quit_mainloop_fired));
269
270   /*
271    *  Check for correct behavior when the bus goes away
272    *
273    */
274   g_assert_false (g_dbus_connection_is_closed (c));
275   g_dbus_connection_set_exit_on_close (c, FALSE);
276   session_bus_stop ();
277   _g_assert_signal_received (c, "closed");
278   g_assert_true (g_dbus_connection_is_closed (c));
279   g_object_unref (c);
280
281   session_bus_down ();
282 }
283
284 /* ---------------------------------------------------------------------------------------------------- */
285 /* Test that sending and receiving messages work as expected */
286 /* ---------------------------------------------------------------------------------------------------- */
287
288 static void
289 msg_cb_expect_error_disconnected (GDBusConnection *connection,
290                                   GAsyncResult    *res,
291                                   gpointer         user_data)
292 {
293   GError *error;
294   GVariant *result;
295
296   /* Make sure gdbusconnection isn't holding @connection's lock. (#747349) */
297   g_dbus_connection_get_last_serial (connection);
298
299   error = NULL;
300   result = g_dbus_connection_call_finish (connection,
301                                           res,
302                                           &error);
303   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CLOSED);
304   g_assert_false (g_dbus_error_is_remote_error (error));
305   g_error_free (error);
306   g_assert_null (result);
307
308   g_main_loop_quit (loop);
309 }
310
311 static void
312 msg_cb_expect_error_unknown_method (GDBusConnection *connection,
313                                     GAsyncResult    *res,
314                                     gpointer         user_data)
315 {
316   GError *error;
317   GVariant *result;
318
319   /* Make sure gdbusconnection isn't holding @connection's lock. (#747349) */
320   g_dbus_connection_get_last_serial (connection);
321
322   error = NULL;
323   result = g_dbus_connection_call_finish (connection,
324                                           res,
325                                           &error);
326   g_assert_error (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD);
327   g_assert_true (g_dbus_error_is_remote_error (error));
328   g_error_free (error);
329   g_assert_null (result);
330
331   g_main_loop_quit (loop);
332 }
333
334 static void
335 msg_cb_expect_success (GDBusConnection *connection,
336                        GAsyncResult    *res,
337                        gpointer         user_data)
338 {
339   GError *error;
340   GVariant *result;
341
342   /* Make sure gdbusconnection isn't holding @connection's lock. (#747349) */
343   g_dbus_connection_get_last_serial (connection);
344
345   error = NULL;
346   result = g_dbus_connection_call_finish (connection,
347                                           res,
348                                           &error);
349   g_assert_no_error (error);
350   g_assert_nonnull (result);
351   g_variant_unref (result);
352
353   g_main_loop_quit (loop);
354 }
355
356 static void
357 msg_cb_expect_error_cancelled (GDBusConnection *connection,
358                                GAsyncResult    *res,
359                                gpointer         user_data)
360 {
361   GError *error;
362   GVariant *result;
363
364   /* Make sure gdbusconnection isn't holding @connection's lock. (#747349) */
365   g_dbus_connection_get_last_serial (connection);
366
367   error = NULL;
368   result = g_dbus_connection_call_finish (connection,
369                                           res,
370                                           &error);
371   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
372   g_assert_false (g_dbus_error_is_remote_error (error));
373   g_error_free (error);
374   g_assert_null (result);
375
376   g_main_loop_quit (loop);
377 }
378
379 static void
380 msg_cb_expect_error_cancelled_2 (GDBusConnection *connection,
381                                  GAsyncResult    *res,
382                                  gpointer         user_data)
383 {
384   GError *error;
385   GVariant *result;
386
387   /* Make sure gdbusconnection isn't holding @connection's lock. (#747349) */
388   g_dbus_connection_get_last_serial (connection);
389
390   error = NULL;
391   result = g_dbus_connection_call_finish (connection,
392                                           res,
393                                           &error);
394   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
395   g_assert_false (g_dbus_error_is_remote_error (error));
396   g_error_free (error);
397   g_assert_null (result);
398
399   g_main_loop_quit (loop);
400 }
401
402 /* ---------------------------------------------------------------------------------------------------- */
403
404 static void
405 test_connection_send (void)
406 {
407   GDBusConnection *c;
408   GCancellable *ca;
409
410   session_bus_up ();
411
412   /* First, get an unopened connection */
413   c = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
414   g_assert_nonnull (c);
415   g_assert_false (g_dbus_connection_is_closed (c));
416
417   /*
418    * Check that we never actually send a message if the GCancellable
419    * is already cancelled - i.e.  we should get G_IO_ERROR_CANCELLED
420    * when the actual connection is not up.
421    */
422   ca = g_cancellable_new ();
423   g_cancellable_cancel (ca);
424   g_dbus_connection_call (c,
425                           "org.freedesktop.DBus",  /* bus_name */
426                           "/org/freedesktop/DBus", /* object path */
427                           "org.freedesktop.DBus",  /* interface name */
428                           "GetId",                 /* method name */
429                           NULL, NULL,
430                           G_DBUS_CALL_FLAGS_NONE,
431                           -1,
432                           ca,
433                           (GAsyncReadyCallback) msg_cb_expect_error_cancelled,
434                           NULL);
435   g_main_loop_run (loop);
436   g_object_unref (ca);
437
438   /*
439    * Check that we get a reply to the GetId() method call.
440    */
441   g_dbus_connection_call (c,
442                           "org.freedesktop.DBus",  /* bus_name */
443                           "/org/freedesktop/DBus", /* object path */
444                           "org.freedesktop.DBus",  /* interface name */
445                           "GetId",                 /* method name */
446                           NULL, NULL,
447                           G_DBUS_CALL_FLAGS_NONE,
448                           -1,
449                           NULL,
450                           (GAsyncReadyCallback) msg_cb_expect_success,
451                           NULL);
452   g_main_loop_run (loop);
453
454   /*
455    * Check that we get an error reply to the NonExistantMethod() method call.
456    */
457   g_dbus_connection_call (c,
458                           "org.freedesktop.DBus",  /* bus_name */
459                           "/org/freedesktop/DBus", /* object path */
460                           "org.freedesktop.DBus",  /* interface name */
461                           "NonExistantMethod",     /* method name */
462                           NULL, NULL,
463                           G_DBUS_CALL_FLAGS_NONE,
464                           -1,
465                           NULL,
466                           (GAsyncReadyCallback) msg_cb_expect_error_unknown_method,
467                           NULL);
468   g_main_loop_run (loop);
469
470   /*
471    * Check that cancellation works when the message is already in flight.
472    */
473   ca = g_cancellable_new ();
474   g_dbus_connection_call (c,
475                           "org.freedesktop.DBus",  /* bus_name */
476                           "/org/freedesktop/DBus", /* object path */
477                           "org.freedesktop.DBus",  /* interface name */
478                           "GetId",                 /* method name */
479                           NULL, NULL,
480                           G_DBUS_CALL_FLAGS_NONE,
481                           -1,
482                           ca,
483                           (GAsyncReadyCallback) msg_cb_expect_error_cancelled_2,
484                           NULL);
485   g_cancellable_cancel (ca);
486   g_main_loop_run (loop);
487   g_object_unref (ca);
488
489   /*
490    * Check that we get an error when sending to a connection that is disconnected.
491    */
492   g_dbus_connection_set_exit_on_close (c, FALSE);
493   session_bus_stop ();
494   _g_assert_signal_received (c, "closed");
495   g_assert_true (g_dbus_connection_is_closed (c));
496
497   g_dbus_connection_call (c,
498                           "org.freedesktop.DBus",  /* bus_name */
499                           "/org/freedesktop/DBus", /* object path */
500                           "org.freedesktop.DBus",  /* interface name */
501                           "GetId",                 /* method name */
502                           NULL, NULL,
503                           G_DBUS_CALL_FLAGS_NONE,
504                           -1,
505                           NULL,
506                           (GAsyncReadyCallback) msg_cb_expect_error_disconnected,
507                           NULL);
508   g_main_loop_run (loop);
509
510   g_object_unref (c);
511
512   session_bus_down ();
513 }
514
515 /* ---------------------------------------------------------------------------------------------------- */
516 /* Connection signal tests */
517 /* ---------------------------------------------------------------------------------------------------- */
518
519 static void
520 test_connection_signal_handler (GDBusConnection  *connection,
521                                 const gchar      *sender_name,
522                                 const gchar      *object_path,
523                                 const gchar      *interface_name,
524                                 const gchar      *signal_name,
525                                 GVariant         *parameters,
526                                 gpointer         user_data)
527 {
528   gint *counter = user_data;
529   *counter += 1;
530
531   /*g_debug ("in test_connection_signal_handler (sender=%s path=%s interface=%s member=%s)",
532            sender_name,
533            object_path,
534            interface_name,
535            signal_name);*/
536
537   g_main_loop_quit (loop);
538 }
539
540 static void
541 test_connection_signals (void)
542 {
543   GDBusConnection *c1;
544   GDBusConnection *c2;
545   GDBusConnection *c3;
546   guint s1;
547   guint s1b;
548   guint s2;
549   guint s3;
550   gint count_s1;
551   gint count_s1b;
552   gint count_s2;
553   gint count_name_owner_changed;
554   GError *error;
555   gboolean ret;
556   GVariant *result;
557   gboolean quit_mainloop_fired;
558   guint quit_mainloop_id;
559
560   error = NULL;
561
562   /*
563    * Bring up first separate connections
564    */
565   session_bus_up ();
566   /* if running with dbus-monitor, it claims the name :1.0 - so if we don't run with the monitor
567    * emulate this
568    */
569   if (g_getenv ("G_DBUS_MONITOR") == NULL)
570     {
571       c1 = _g_bus_get_priv (G_BUS_TYPE_SESSION, NULL, NULL);
572       g_assert_nonnull (c1);
573       g_assert_false (g_dbus_connection_is_closed (c1));
574       g_object_unref (c1);
575     }
576   c1 = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
577   g_assert_nonnull (c1);
578   g_assert_false (g_dbus_connection_is_closed (c1));
579   g_assert_cmpstr (g_dbus_connection_get_unique_name (c1), ==, ":1.1");
580
581   /*
582    * Install two signal handlers for the first connection
583    *
584    *  - Listen to the signal "Foo" from :1.2 (e.g. c2)
585    *  - Listen to the signal "Foo" from anyone (e.g. both c2 and c3)
586    *
587    * and then count how many times this signal handler was invoked.
588    */
589   s1 = g_dbus_connection_signal_subscribe (c1,
590                                            ":1.2",
591                                            "org.gtk.GDBus.ExampleInterface",
592                                            "Foo",
593                                            "/org/gtk/GDBus/ExampleInterface",
594                                            NULL,
595                                            G_DBUS_SIGNAL_FLAGS_NONE,
596                                            test_connection_signal_handler,
597                                            &count_s1,
598                                            NULL);
599   s2 = g_dbus_connection_signal_subscribe (c1,
600                                            NULL, /* match any sender */
601                                            "org.gtk.GDBus.ExampleInterface",
602                                            "Foo",
603                                            "/org/gtk/GDBus/ExampleInterface",
604                                            NULL,
605                                            G_DBUS_SIGNAL_FLAGS_NONE,
606                                            test_connection_signal_handler,
607                                            &count_s2,
608                                            NULL);
609   s3 = g_dbus_connection_signal_subscribe (c1,
610                                            "org.freedesktop.DBus",  /* sender */
611                                            "org.freedesktop.DBus",  /* interface */
612                                            "NameOwnerChanged",      /* member */
613                                            "/org/freedesktop/DBus", /* path */
614                                            NULL,
615                                            G_DBUS_SIGNAL_FLAGS_NONE,
616                                            test_connection_signal_handler,
617                                            &count_name_owner_changed,
618                                            NULL);
619   /* Note that s1b is *just like* s1 - this is to catch a bug where N
620    * subscriptions of the same rule causes N calls to each of the N
621    * subscriptions instead of just 1 call to each of the N subscriptions.
622    */
623   s1b = g_dbus_connection_signal_subscribe (c1,
624                                             ":1.2",
625                                             "org.gtk.GDBus.ExampleInterface",
626                                             "Foo",
627                                             "/org/gtk/GDBus/ExampleInterface",
628                                             NULL,
629                                             G_DBUS_SIGNAL_FLAGS_NONE,
630                                             test_connection_signal_handler,
631                                             &count_s1b,
632                                             NULL);
633   g_assert_cmpuint (s1, !=, 0);
634   g_assert_cmpuint (s1b, !=, 0);
635   g_assert_cmpuint (s2, !=, 0);
636   g_assert_cmpuint (s3, !=, 0);
637
638   count_s1 = 0;
639   count_s1b = 0;
640   count_s2 = 0;
641   count_name_owner_changed = 0;
642
643   /*
644    * Make c2 emit "Foo" - we should catch it twice
645    *
646    * Note that there is no way to be sure that the signal subscriptions
647    * on c1 are effective yet - for all we know, the AddMatch() messages
648    * could sit waiting in a buffer somewhere between this process and
649    * the message bus. And emitting signals on c2 (a completely other
650    * socket!) will not necessarily change this.
651    *
652    * To ensure this is not the case, do a synchronous call on c1.
653    */
654   result = g_dbus_connection_call_sync (c1,
655                                         "org.freedesktop.DBus",  /* bus name */
656                                         "/org/freedesktop/DBus", /* object path */
657                                         "org.freedesktop.DBus",  /* interface name */
658                                         "GetId",                 /* method name */
659                                         NULL,                    /* parameters */
660                                         NULL,                    /* return type */
661                                         G_DBUS_CALL_FLAGS_NONE,
662                                         -1,
663                                         NULL,
664                                         &error);
665   g_assert_no_error (error);
666   g_assert_nonnull (result);
667   g_variant_unref (result);
668
669   /*
670    * Bring up two other connections
671    */
672   c2 = _g_bus_get_priv (G_BUS_TYPE_SESSION, NULL, NULL);
673   g_assert_nonnull (c2);
674   g_assert_false (g_dbus_connection_is_closed (c2));
675   g_assert_cmpstr (g_dbus_connection_get_unique_name (c2), ==, ":1.2");
676   c3 = _g_bus_get_priv (G_BUS_TYPE_SESSION, NULL, NULL);
677   g_assert_nonnull (c3);
678   g_assert_false (g_dbus_connection_is_closed (c3));
679   g_assert_cmpstr (g_dbus_connection_get_unique_name (c3), ==, ":1.3");
680
681   /* now, emit the signal on c2 */
682   ret = g_dbus_connection_emit_signal (c2,
683                                        NULL, /* destination bus name */
684                                        "/org/gtk/GDBus/ExampleInterface",
685                                        "org.gtk.GDBus.ExampleInterface",
686                                        "Foo",
687                                        NULL,
688                                        &error);
689   g_assert_no_error (error);
690   g_assert_true (ret);
691   while (!(count_s1 >= 1 && count_s2 >= 1))
692     g_main_loop_run (loop);
693   g_assert_cmpint (count_s1, ==, 1);
694   g_assert_cmpint (count_s2, ==, 1);
695
696   /*
697    * Make c3 emit "Foo" - we should catch it only once
698    */
699   ret = g_dbus_connection_emit_signal (c3,
700                                        NULL, /* destination bus name */
701                                        "/org/gtk/GDBus/ExampleInterface",
702                                        "org.gtk.GDBus.ExampleInterface",
703                                        "Foo",
704                                        NULL,
705                                        &error);
706   g_assert_no_error (error);
707   g_assert_true (ret);
708   while (!(count_s1 == 1 && count_s2 == 2))
709     g_main_loop_run (loop);
710   g_assert_cmpint (count_s1, ==, 1);
711   g_assert_cmpint (count_s2, ==, 2);
712
713   /*
714    * Also to check the total amount of NameOwnerChanged signals - use a 5 second ceiling
715    * to avoid spinning forever
716    */
717   quit_mainloop_fired = FALSE;
718   quit_mainloop_id = g_timeout_add (30000, test_connection_quit_mainloop, &quit_mainloop_fired);
719   while (count_name_owner_changed < 2 && !quit_mainloop_fired)
720     g_main_loop_run (loop);
721   g_source_remove (quit_mainloop_id);
722   g_assert_cmpint (count_s1, ==, 1);
723   g_assert_cmpint (count_s2, ==, 2);
724   g_assert_cmpint (count_name_owner_changed, ==, 2);
725
726   g_dbus_connection_signal_unsubscribe (c1, s1);
727   g_dbus_connection_signal_unsubscribe (c1, s2);
728   g_dbus_connection_signal_unsubscribe (c1, s3);
729   g_dbus_connection_signal_unsubscribe (c1, s1b);
730
731   g_object_unref (c1);
732   g_object_unref (c2);
733   g_object_unref (c3);
734
735   session_bus_down ();
736 }
737
738 static void
739 test_match_rule (GDBusConnection  *connection,
740                  GDBusSignalFlags  flags,
741                  gchar            *arg0_rule,
742                  gchar            *arg0,
743                  gboolean          should_match)
744 {
745   guint subscription_ids[2];
746   gint emissions = 0;
747   gint matches = 0;
748   GError *error = NULL;
749
750   subscription_ids[0] = g_dbus_connection_signal_subscribe (connection,
751                                                             NULL, "org.gtk.ExampleInterface", "Foo", "/",
752                                                             NULL,
753                                                             G_DBUS_SIGNAL_FLAGS_NONE,
754                                                             test_connection_signal_handler,
755                                                             &emissions, NULL);
756   subscription_ids[1] = g_dbus_connection_signal_subscribe (connection,
757                                                             NULL, "org.gtk.ExampleInterface", "Foo", "/",
758                                                             arg0_rule,
759                                                             flags,
760                                                             test_connection_signal_handler,
761                                                             &matches, NULL);
762   g_assert_cmpint (subscription_ids[0], !=, 0);
763   g_assert_cmpint (subscription_ids[1], !=, 0);
764
765   g_dbus_connection_emit_signal (connection,
766                                  NULL, "/", "org.gtk.ExampleInterface",
767                                  "Foo", g_variant_new ("(s)", arg0),
768                                  &error);
769   g_assert_no_error (error);
770
771   /* synchronously ping a non-existent method to make sure the signals are dispatched */
772   g_dbus_connection_call_sync (connection, "org.gtk.ExampleInterface", "/", "org.gtk.ExampleInterface",
773                                "Bar", g_variant_new ("()"), G_VARIANT_TYPE_UNIT, G_DBUS_CALL_FLAGS_NONE,
774                                -1, NULL, NULL);
775
776   while (g_main_context_iteration (NULL, FALSE))
777     ;
778
779   g_assert_cmpint (emissions, ==, 1);
780   g_assert_cmpint (matches, ==, should_match ? 1 : 0);
781
782   g_dbus_connection_signal_unsubscribe (connection, subscription_ids[0]);
783   g_dbus_connection_signal_unsubscribe (connection, subscription_ids[1]);
784 }
785
786 static void
787 test_connection_signal_match_rules (void)
788 {
789   GDBusConnection *con;
790
791   session_bus_up ();
792   con = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
793
794   test_match_rule (con, G_DBUS_SIGNAL_FLAGS_NONE, "foo", "foo", TRUE);
795   test_match_rule (con, G_DBUS_SIGNAL_FLAGS_NONE, "foo", "bar", FALSE);
796
797   test_match_rule (con, G_DBUS_SIGNAL_FLAGS_MATCH_ARG0_NAMESPACE, "org.gtk", "", FALSE);
798   test_match_rule (con, G_DBUS_SIGNAL_FLAGS_MATCH_ARG0_NAMESPACE, "org.gtk", "org", FALSE);
799   test_match_rule (con, G_DBUS_SIGNAL_FLAGS_MATCH_ARG0_NAMESPACE, "org.gtk", "org.gtk", TRUE);
800   test_match_rule (con, G_DBUS_SIGNAL_FLAGS_MATCH_ARG0_NAMESPACE, "org.gtk", "org.gtk.Example", TRUE);
801   test_match_rule (con, G_DBUS_SIGNAL_FLAGS_MATCH_ARG0_NAMESPACE, "org.gtk", "org.gtk+", FALSE);
802
803   test_match_rule (con, G_DBUS_SIGNAL_FLAGS_MATCH_ARG0_PATH, "/", "/", TRUE);
804   test_match_rule (con, G_DBUS_SIGNAL_FLAGS_MATCH_ARG0_PATH, "/", "", FALSE);
805   test_match_rule (con, G_DBUS_SIGNAL_FLAGS_MATCH_ARG0_PATH, "/org/gtk/Example", "/org/gtk/Example", TRUE);
806   test_match_rule (con, G_DBUS_SIGNAL_FLAGS_MATCH_ARG0_PATH, "/org/gtk/", "/org/gtk/Example", TRUE);
807   test_match_rule (con, G_DBUS_SIGNAL_FLAGS_MATCH_ARG0_PATH, "/org/gtk/Example", "/org/gtk/", TRUE);
808   test_match_rule (con, G_DBUS_SIGNAL_FLAGS_MATCH_ARG0_PATH, "/org/gtk/Example", "/org/gtk", FALSE);
809   test_match_rule (con, G_DBUS_SIGNAL_FLAGS_MATCH_ARG0_PATH, "/org/gtk+", "/org/gtk", FALSE);
810
811   g_object_unref (con);
812   session_bus_down ();
813 }
814
815 /* ---------------------------------------------------------------------------------------------------- */
816
817 /* Accessed both from the test code and the filter function (in a worker thread)
818  * so all accesses must be atomic. */
819 typedef struct
820 {
821   GAsyncQueue *incoming_queue;  /* (element-type GDBusMessage) */
822   guint num_outgoing;  /* (atomic) */
823 } FilterData;
824
825 /* Runs in a worker thread. */
826 static GDBusMessage *
827 filter_func (GDBusConnection *connection,
828              GDBusMessage    *message,
829              gboolean         incoming,
830              gpointer         user_data)
831 {
832   FilterData *data = user_data;
833
834   if (incoming)
835     g_async_queue_push (data->incoming_queue, g_object_ref (message));
836   else
837     g_atomic_int_inc (&data->num_outgoing);
838
839   return message;
840 }
841
842 static void
843 wait_for_filtered_reply (GAsyncQueue *incoming_queue,
844                          guint32      expected_serial)
845 {
846   GDBusMessage *popped_message = NULL;
847
848   while ((popped_message = g_async_queue_pop (incoming_queue)) != NULL)
849     {
850       guint32 reply_serial = g_dbus_message_get_reply_serial (popped_message);
851       g_object_unref (popped_message);
852       if (reply_serial == expected_serial)
853         return;
854     }
855
856   g_assert_not_reached ();
857 }
858
859 typedef struct
860 {
861   gboolean alter_incoming;
862   gboolean alter_outgoing;
863 } FilterEffects;
864
865 /* Runs in a worker thread. */
866 static GDBusMessage *
867 other_filter_func (GDBusConnection *connection,
868                    GDBusMessage    *message,
869                    gboolean         incoming,
870                    gpointer         user_data)
871 {
872   const FilterEffects *effects = user_data;
873   GDBusMessage *ret;
874   gboolean alter;
875
876   if (incoming)
877     alter = effects->alter_incoming;
878   else
879     alter = effects->alter_outgoing;
880
881   if (alter)
882     {
883       GDBusMessage *copy;
884       GVariant *body;
885       gchar *s;
886       gchar *s2;
887
888       copy = g_dbus_message_copy (message, NULL);
889       g_object_unref (message);
890
891       body = g_dbus_message_get_body (copy);
892       g_variant_get (body, "(s)", &s);
893       s2 = g_strdup_printf ("MOD: %s", s);
894       g_dbus_message_set_body (copy, g_variant_new ("(s)", s2));
895       g_free (s2);
896       g_free (s);
897
898       ret = copy;
899     }
900   else
901     {
902       ret = message;
903     }
904
905   return ret;
906 }
907
908 static void
909 test_connection_filter_name_owner_changed_signal_handler (GDBusConnection  *connection,
910                                                           const gchar      *sender_name,
911                                                           const gchar      *object_path,
912                                                           const gchar      *interface_name,
913                                                           const gchar      *signal_name,
914                                                           GVariant         *parameters,
915                                                           gpointer         user_data)
916 {
917   const gchar *name;
918   const gchar *old_owner;
919   const gchar *new_owner;
920
921   g_variant_get (parameters,
922                  "(&s&s&s)",
923                  &name,
924                  &old_owner,
925                  &new_owner);
926
927   if (g_strcmp0 (name, "com.example.TestService") == 0 && strlen (new_owner) > 0)
928     {
929       g_main_loop_quit (loop);
930     }
931 }
932
933 static gboolean
934 test_connection_filter_on_timeout (gpointer user_data)
935 {
936   g_printerr ("Timeout waiting 30 sec on service\n");
937   g_assert_not_reached ();
938   return G_SOURCE_REMOVE;
939 }
940
941 static void
942 test_connection_filter (void)
943 {
944   GDBusConnection *c;
945   FilterData data = { NULL, 0 };
946   GDBusMessage *m;
947   GDBusMessage *m2;
948   GDBusMessage *r;
949   GError *error;
950   guint filter_id;
951   guint timeout_mainloop_id;
952   guint signal_handler_id;
953   FilterEffects effects;
954   GVariant *result;
955   const gchar *s;
956   guint32 serial_temp;
957
958   session_bus_up ();
959
960   error = NULL;
961   c = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
962   g_assert_no_error (error);
963   g_assert_nonnull (c);
964
965   data.incoming_queue = g_async_queue_new_full (g_object_unref);
966   data.num_outgoing = 0;
967   filter_id = g_dbus_connection_add_filter (c,
968                                             filter_func,
969                                             &data,
970                                             NULL);
971
972   m = g_dbus_message_new_method_call ("org.freedesktop.DBus", /* name */
973                                       "/org/freedesktop/DBus", /* path */
974                                       "org.freedesktop.DBus", /* interface */
975                                       "GetNameOwner");
976   g_dbus_message_set_body (m, g_variant_new ("(s)", "org.freedesktop.DBus"));
977   error = NULL;
978   g_dbus_connection_send_message (c, m, G_DBUS_SEND_MESSAGE_FLAGS_NONE, &serial_temp, &error);
979   g_assert_no_error (error);
980
981   wait_for_filtered_reply (data.incoming_queue, serial_temp);
982
983   m2 = g_dbus_message_copy (m, &error);
984   g_assert_no_error (error);
985   g_dbus_connection_send_message (c, m2, G_DBUS_SEND_MESSAGE_FLAGS_NONE, &serial_temp, &error);
986   g_object_unref (m2);
987   g_assert_no_error (error);
988
989   wait_for_filtered_reply (data.incoming_queue, serial_temp);
990
991   m2 = g_dbus_message_copy (m, &error);
992   g_assert_no_error (error);
993   g_dbus_message_set_serial (m2, serial_temp);
994   /* lock the message to test PRESERVE_SERIAL flag. */
995   g_dbus_message_lock (m2);
996   g_dbus_connection_send_message (c, m2, G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL, &serial_temp, &error);
997   g_object_unref (m2);
998   g_assert_no_error (error);
999
1000   wait_for_filtered_reply (data.incoming_queue, serial_temp);
1001
1002   m2 = g_dbus_message_copy (m, &error);
1003   g_assert_no_error (error);
1004   r = g_dbus_connection_send_message_with_reply_sync (c,
1005                                                       m2,
1006                                                       G_DBUS_SEND_MESSAGE_FLAGS_NONE,
1007                                                       -1,
1008                                                       &serial_temp,
1009                                                       NULL, /* GCancellable */
1010                                                       &error);
1011   g_object_unref (m2);
1012   g_assert_no_error (error);
1013   g_assert_nonnull (r);
1014   g_object_unref (r);
1015
1016   wait_for_filtered_reply (data.incoming_queue, serial_temp);
1017   g_assert_cmpint (g_async_queue_length (data.incoming_queue), ==, 0);
1018
1019   g_dbus_connection_remove_filter (c, filter_id);
1020
1021   m2 = g_dbus_message_copy (m, &error);
1022   g_assert_no_error (error);
1023   r = g_dbus_connection_send_message_with_reply_sync (c,
1024                                                       m2,
1025                                                       G_DBUS_SEND_MESSAGE_FLAGS_NONE,
1026                                                       -1,
1027                                                       &serial_temp,
1028                                                       NULL, /* GCancellable */
1029                                                       &error);
1030   g_object_unref (m2);
1031   g_assert_no_error (error);
1032   g_assert_nonnull (r);
1033   g_object_unref (r);
1034   g_assert_cmpint (g_async_queue_length (data.incoming_queue), ==, 0);
1035   g_assert_cmpint (g_atomic_int_get (&data.num_outgoing), ==, 4);
1036
1037   /* wait for service to be available */
1038   signal_handler_id = g_dbus_connection_signal_subscribe (c,
1039                                                           "org.freedesktop.DBus", /* sender */
1040                                                           "org.freedesktop.DBus",
1041                                                           "NameOwnerChanged",
1042                                                           "/org/freedesktop/DBus",
1043                                                           NULL, /* arg0 */
1044                                                           G_DBUS_SIGNAL_FLAGS_NONE,
1045                                                           test_connection_filter_name_owner_changed_signal_handler,
1046                                                           NULL,
1047                                                           NULL);
1048   g_assert_cmpint (signal_handler_id, !=, 0);
1049
1050   /* this is safe; testserver will exit once the bus goes away */
1051   g_assert_true (g_spawn_command_line_async (g_test_get_filename (G_TEST_BUILT, "gdbus-testserver", NULL), NULL));
1052
1053   timeout_mainloop_id = g_timeout_add (30000, test_connection_filter_on_timeout, NULL);
1054   g_main_loop_run (loop);
1055   g_source_remove (timeout_mainloop_id);
1056   g_dbus_connection_signal_unsubscribe (c, signal_handler_id);
1057
1058   /* now test some combinations... */
1059   filter_id = g_dbus_connection_add_filter (c,
1060                                             other_filter_func,
1061                                             &effects,
1062                                             NULL);
1063   /* -- */
1064   effects.alter_incoming = FALSE;
1065   effects.alter_outgoing = FALSE;
1066   error = NULL;
1067   result = g_dbus_connection_call_sync (c,
1068                                         "com.example.TestService",      /* bus name */
1069                                         "/com/example/TestObject",      /* object path */
1070                                         "com.example.Frob",             /* interface name */
1071                                         "HelloWorld",                   /* method name */
1072                                         g_variant_new ("(s)", "Cat"),   /* parameters */
1073                                         G_VARIANT_TYPE ("(s)"),         /* return type */
1074                                         G_DBUS_CALL_FLAGS_NONE,
1075                                         -1,
1076                                         NULL,
1077                                         &error);
1078   g_assert_no_error (error);
1079   g_variant_get (result, "(&s)", &s);
1080   g_assert_cmpstr (s, ==, "You greeted me with 'Cat'. Thanks!");
1081   g_variant_unref (result);
1082   /* -- */
1083   effects.alter_incoming = TRUE;
1084   effects.alter_outgoing = TRUE;
1085   error = NULL;
1086   result = g_dbus_connection_call_sync (c,
1087                                         "com.example.TestService",      /* bus name */
1088                                         "/com/example/TestObject",      /* object path */
1089                                         "com.example.Frob",             /* interface name */
1090                                         "HelloWorld",                   /* method name */
1091                                         g_variant_new ("(s)", "Cat"),   /* parameters */
1092                                         G_VARIANT_TYPE ("(s)"),         /* return type */
1093                                         G_DBUS_CALL_FLAGS_NONE,
1094                                         -1,
1095                                         NULL,
1096                                         &error);
1097   g_assert_no_error (error);
1098   g_variant_get (result, "(&s)", &s);
1099   g_assert_cmpstr (s, ==, "MOD: You greeted me with 'MOD: Cat'. Thanks!");
1100   g_variant_unref (result);
1101
1102
1103   g_dbus_connection_remove_filter (c, filter_id);
1104
1105   g_object_unref (c);
1106   g_object_unref (m);
1107   g_async_queue_unref (data.incoming_queue);
1108
1109   session_bus_down ();
1110 }
1111
1112 /* ---------------------------------------------------------------------------------------------------- */
1113
1114 #define NUM_THREADS 50
1115
1116 static void
1117 send_bogus_message (GDBusConnection *c, guint32 *out_serial)
1118 {
1119   GDBusMessage *m;
1120   GError *error;
1121
1122   m = g_dbus_message_new_method_call ("org.freedesktop.DBus", /* name */
1123                                       "/org/freedesktop/DBus", /* path */
1124                                       "org.freedesktop.DBus", /* interface */
1125                                       "GetNameOwner");
1126   g_dbus_message_set_body (m, g_variant_new ("(s)", "org.freedesktop.DBus"));
1127   error = NULL;
1128   g_dbus_connection_send_message (c, m, G_DBUS_SEND_MESSAGE_FLAGS_NONE, out_serial, &error);
1129   g_assert_no_error (error);
1130   g_object_unref (m);
1131 }
1132
1133 #define SLEEP_USEC (100 * 1000)
1134
1135 static gpointer
1136 serials_thread_func (GDBusConnection *c)
1137 {
1138   guint32 message_serial;
1139   guint i;
1140
1141   /* No calls on this thread yet */
1142   g_assert_cmpint (g_dbus_connection_get_last_serial(c), ==, 0);
1143
1144   /* Send a bogus message and store its serial */
1145   message_serial = 0;
1146   send_bogus_message (c, &message_serial);
1147
1148   /* Give it some time to actually send the message out. 10 seconds
1149    * should be plenty, even on slow machines. */
1150   for (i = 0; i < 10 * G_USEC_PER_SEC / SLEEP_USEC; i++)
1151     {
1152       if (g_dbus_connection_get_last_serial(c) != 0)
1153         break;
1154
1155       g_usleep (SLEEP_USEC);
1156     }
1157
1158   g_assert_cmpint (g_dbus_connection_get_last_serial(c), !=, 0);
1159   g_assert_cmpint (g_dbus_connection_get_last_serial(c), ==, message_serial);
1160
1161   return NULL;
1162 }
1163
1164 static void
1165 test_connection_serials (void)
1166 {
1167   GDBusConnection *c;
1168   GError *error;
1169   GThread *pool[NUM_THREADS];
1170   int i;
1171
1172   session_bus_up ();
1173
1174   error = NULL;
1175   c = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
1176   g_assert_no_error (error);
1177   g_assert_nonnull (c);
1178
1179   /* Status after initialization */
1180   g_assert_cmpint (g_dbus_connection_get_last_serial (c), ==, 1);
1181
1182   /* Send a bogus message */
1183   send_bogus_message (c, NULL);
1184   g_assert_cmpint (g_dbus_connection_get_last_serial (c), ==, 2);
1185
1186   /* Start the threads */
1187   for (i = 0; i < NUM_THREADS; i++)
1188     pool[i] = g_thread_new (NULL, (GThreadFunc) serials_thread_func, c);
1189
1190   /* Wait until threads are finished */
1191   for (i = 0; i < NUM_THREADS; i++)
1192       g_thread_join (pool[i]);
1193
1194   /* No calls in between on this thread, should be the last value */
1195   g_assert_cmpint (g_dbus_connection_get_last_serial (c), ==, 2);
1196
1197   send_bogus_message (c, NULL);
1198
1199   /* All above calls + calls in threads */
1200   g_assert_cmpint (g_dbus_connection_get_last_serial (c), ==, 3 + NUM_THREADS);
1201
1202   g_object_unref (c);
1203
1204   session_bus_down ();
1205 }
1206
1207 /* ---------------------------------------------------------------------------------------------------- */
1208
1209 static void
1210 test_connection_basic (void)
1211 {
1212   GDBusConnection *connection;
1213   GError *error;
1214   GDBusCapabilityFlags flags;
1215   GDBusConnectionFlags connection_flags;
1216   gchar *guid;
1217   gchar *name;
1218   gboolean closed;
1219   gboolean exit_on_close;
1220   GIOStream *stream;
1221   GCredentials *credentials;
1222
1223   session_bus_up ();
1224
1225   error = NULL;
1226   connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
1227   g_assert_no_error (error);
1228   g_assert_nonnull (connection);
1229
1230   flags = g_dbus_connection_get_capabilities (connection);
1231   g_assert_true (flags == G_DBUS_CAPABILITY_FLAGS_NONE ||
1232                  flags == G_DBUS_CAPABILITY_FLAGS_UNIX_FD_PASSING);
1233
1234   connection_flags = g_dbus_connection_get_flags (connection);
1235   g_assert_cmpint (connection_flags, ==,
1236                    G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT |
1237                    G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION);
1238
1239   credentials = g_dbus_connection_get_peer_credentials (connection);
1240   g_assert_null (credentials);
1241
1242   g_object_get (connection,
1243                 "stream", &stream,
1244                 "guid", &guid,
1245                 "unique-name", &name,
1246                 "closed", &closed,
1247                 "exit-on-close", &exit_on_close,
1248                 "capabilities", &flags,
1249                 NULL);
1250
1251   g_assert_true (G_IS_IO_STREAM (stream));
1252   g_assert_true (g_dbus_is_guid (guid));
1253   g_assert_true (g_dbus_is_unique_name (name));
1254   g_assert_false (closed);
1255   g_assert_true (exit_on_close);
1256   g_assert_true (flags == G_DBUS_CAPABILITY_FLAGS_NONE ||
1257                  flags == G_DBUS_CAPABILITY_FLAGS_UNIX_FD_PASSING);
1258   g_object_unref (stream);
1259   g_free (name);
1260   g_free (guid);
1261
1262   g_object_unref (connection);
1263
1264   session_bus_down ();
1265 }
1266
1267 /* ---------------------------------------------------------------------------------------------------- */
1268
1269 int
1270 main (int   argc,
1271       char *argv[])
1272 {
1273   int ret;
1274
1275   g_test_init (&argc, &argv, NULL);
1276
1277   /* all the tests rely on a shared main loop */
1278   loop = g_main_loop_new (NULL, FALSE);
1279
1280   g_test_dbus_unset ();
1281
1282   /* gdbus cleanup is pretty racy due to worker threads, so always do this test first */
1283   g_test_add_func ("/gdbus/connection/bus-failure", test_connection_bus_failure);
1284
1285   g_test_add_func ("/gdbus/connection/basic", test_connection_basic);
1286   g_test_add_func ("/gdbus/connection/life-cycle", test_connection_life_cycle);
1287   g_test_add_func ("/gdbus/connection/send", test_connection_send);
1288   g_test_add_func ("/gdbus/connection/signals", test_connection_signals);
1289   g_test_add_func ("/gdbus/connection/signal-match-rules", test_connection_signal_match_rules);
1290   g_test_add_func ("/gdbus/connection/filter", test_connection_filter);
1291   g_test_add_func ("/gdbus/connection/serials", test_connection_serials);
1292   ret = g_test_run();
1293
1294   g_main_loop_unref (loop);
1295   return ret;
1296 }