GDBusServer: Make ::new-connection return whether the connection was claimed
[platform/upstream/glib.git] / gio / tests / gdbus-peer.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 /* for open(2) */
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include <fcntl.h>
31 #include <string.h>
32
33 /* for g_unlink() */
34 #include <glib/gstdio.h>
35
36 #include <gio/gnetworkingprivate.h>
37 #include <gio/gunixsocketaddress.h>
38 #include <gio/gunixfdlist.h>
39
40 /* used in test_overflow */
41 #ifdef G_OS_UNIX
42 #include <gio/gunixconnection.h>
43 #include <errno.h>
44 #endif
45
46 #include "gdbus-tests.h"
47
48 #ifdef G_OS_UNIX
49 static gboolean is_unix = TRUE;
50 #else
51 static gboolean is_unix = FALSE;
52 #endif
53
54 static gchar *test_guid = NULL;
55 static GMainLoop *service_loop = NULL;
56 static GDBusServer *server = NULL;
57 static GMainLoop *loop = NULL;
58
59 /* ---------------------------------------------------------------------------------------------------- */
60 /* Test that peer-to-peer connections work */
61 /* ---------------------------------------------------------------------------------------------------- */
62
63
64 typedef struct
65 {
66   gboolean accept_connection;
67   gint num_connection_attempts;
68   GPtrArray *current_connections;
69   guint num_method_calls;
70   gboolean signal_received;
71 } PeerData;
72
73 static const gchar *test_interface_introspection_xml =
74   "<node>"
75   "  <interface name='org.gtk.GDBus.PeerTestInterface'>"
76   "    <method name='HelloPeer'>"
77   "      <arg type='s' name='greeting' direction='in'/>"
78   "      <arg type='s' name='response' direction='out'/>"
79   "    </method>"
80   "    <method name='EmitSignal'/>"
81   "    <method name='EmitSignalWithNameSet'/>"
82   "    <method name='OpenFile'>"
83   "      <arg type='s' name='path' direction='in'/>"
84   "    </method>"
85   "    <signal name='PeerSignal'>"
86   "      <arg type='s' name='a_string'/>"
87   "    </signal>"
88   "    <property type='s' name='PeerProperty' access='read'/>"
89   "  </interface>"
90   "</node>";
91 static GDBusInterfaceInfo *test_interface_introspection_data = NULL;
92
93 static void
94 test_interface_method_call (GDBusConnection       *connection,
95                             const gchar           *sender,
96                             const gchar           *object_path,
97                             const gchar           *interface_name,
98                             const gchar           *method_name,
99                             GVariant              *parameters,
100                             GDBusMethodInvocation *invocation,
101                             gpointer               user_data)
102 {
103   PeerData *data = user_data;
104   const GDBusMethodInfo *info;
105
106   data->num_method_calls++;
107
108   g_assert_cmpstr (object_path, ==, "/org/gtk/GDBus/PeerTestObject");
109   g_assert_cmpstr (interface_name, ==, "org.gtk.GDBus.PeerTestInterface");
110
111   info = g_dbus_method_invocation_get_method_info (invocation);
112   g_assert_cmpstr (info->name, ==, method_name);
113
114   if (g_strcmp0 (method_name, "HelloPeer") == 0)
115     {
116       const gchar *greeting;
117       gchar *response;
118
119       g_variant_get (parameters, "(&s)", &greeting);
120
121       response = g_strdup_printf ("You greeted me with '%s'.",
122                                   greeting);
123       g_dbus_method_invocation_return_value (invocation,
124                                              g_variant_new ("(s)", response));
125       g_free (response);
126     }
127   else if (g_strcmp0 (method_name, "EmitSignal") == 0)
128     {
129       GError *error;
130
131       error = NULL;
132       g_dbus_connection_emit_signal (connection,
133                                      NULL,
134                                      "/org/gtk/GDBus/PeerTestObject",
135                                      "org.gtk.GDBus.PeerTestInterface",
136                                      "PeerSignal",
137                                      NULL,
138                                      &error);
139       g_assert_no_error (error);
140       g_dbus_method_invocation_return_value (invocation, NULL);
141     }
142   else if (g_strcmp0 (method_name, "EmitSignalWithNameSet") == 0)
143     {
144       GError *error;
145       gboolean ret;
146       GDBusMessage *message;
147
148       message = g_dbus_message_new_signal ("/org/gtk/GDBus/PeerTestObject",
149                                            "org.gtk.GDBus.PeerTestInterface",
150                                            "PeerSignalWithNameSet");
151       g_dbus_message_set_sender (message, ":1.42");
152
153       error = NULL;
154       ret = g_dbus_connection_send_message (connection, message, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, &error);
155       g_assert_no_error (error);
156       g_assert (ret);
157       g_object_unref (message);
158
159       g_dbus_method_invocation_return_value (invocation, NULL);
160     }
161   else if (g_strcmp0 (method_name, "OpenFile") == 0)
162     {
163 #ifdef G_OS_UNIX
164       const gchar *path;
165       GDBusMessage *reply;
166       GError *error;
167       gint fd;
168       GUnixFDList *fd_list;
169
170       g_variant_get (parameters, "(&s)", &path);
171
172       fd_list = g_unix_fd_list_new ();
173
174       error = NULL;
175
176       fd = open (path, O_RDONLY);
177       g_unix_fd_list_append (fd_list, fd, &error);
178       g_assert_no_error (error);
179       close (fd);
180
181       reply = g_dbus_message_new_method_reply (g_dbus_method_invocation_get_message (invocation));
182       g_dbus_message_set_unix_fd_list (reply, fd_list);
183       g_object_unref (fd_list);
184       g_object_unref (invocation);
185
186       error = NULL;
187       g_dbus_connection_send_message (connection,
188                                       reply,
189                                       G_DBUS_SEND_MESSAGE_FLAGS_NONE,
190                                       NULL, /* out_serial */
191                                       &error);
192       g_assert_no_error (error);
193       g_object_unref (reply);
194 #else
195       g_dbus_method_invocation_return_dbus_error (invocation,
196                                                   "org.gtk.GDBus.NotOnUnix",
197                                                   "Your OS does not support file descriptor passing");
198 #endif
199     }
200   else
201     {
202       g_assert_not_reached ();
203     }
204 }
205
206 static GVariant *
207 test_interface_get_property (GDBusConnection  *connection,
208                              const gchar      *sender,
209                              const gchar      *object_path,
210                              const gchar      *interface_name,
211                              const gchar      *property_name,
212                              GError          **error,
213                              gpointer          user_data)
214 {
215   g_assert_cmpstr (object_path, ==, "/org/gtk/GDBus/PeerTestObject");
216   g_assert_cmpstr (interface_name, ==, "org.gtk.GDBus.PeerTestInterface");
217   g_assert_cmpstr (property_name, ==, "PeerProperty");
218
219   return g_variant_new_string ("ThePropertyValue");
220 }
221
222
223 static const GDBusInterfaceVTable test_interface_vtable =
224 {
225   test_interface_method_call,
226   test_interface_get_property,
227   NULL  /* set_property */
228 };
229
230 static void
231 on_proxy_signal_received (GDBusProxy *proxy,
232                           gchar      *sender_name,
233                           gchar      *signal_name,
234                           GVariant   *parameters,
235                           gpointer    user_data)
236 {
237   PeerData *data = user_data;
238
239   data->signal_received = TRUE;
240
241   g_assert (sender_name == NULL);
242   g_assert_cmpstr (signal_name, ==, "PeerSignal");
243   g_main_loop_quit (loop);
244 }
245
246 static void
247 on_proxy_signal_received_with_name_set (GDBusProxy *proxy,
248                                         gchar      *sender_name,
249                                         gchar      *signal_name,
250                                         GVariant   *parameters,
251                                         gpointer    user_data)
252 {
253   PeerData *data = user_data;
254
255   data->signal_received = TRUE;
256
257   g_assert_cmpstr (sender_name, ==, ":1.42");
258   g_assert_cmpstr (signal_name, ==, "PeerSignalWithNameSet");
259   g_main_loop_quit (loop);
260 }
261
262 /* ---------------------------------------------------------------------------------------------------- */
263
264 static gboolean
265 on_authorize_authenticated_peer (GDBusAuthObserver *observer,
266                                  GIOStream         *stream,
267                                  GCredentials      *credentials,
268                                  gpointer           user_data)
269 {
270   PeerData *data = user_data;
271   gboolean authorized;
272
273   data->num_connection_attempts++;
274
275   authorized = TRUE;
276   if (!data->accept_connection)
277     {
278       authorized = FALSE;
279       g_main_loop_quit (loop);
280     }
281
282   return authorized;
283 }
284
285 /* Runs in thread we created GDBusServer in (since we didn't pass G_DBUS_SERVER_FLAGS_RUN_IN_THREAD) */
286 static gboolean
287 on_new_connection (GDBusServer *server,
288                    GDBusConnection *connection,
289                    gpointer user_data)
290 {
291   PeerData *data = user_data;
292   GError *error;
293   guint reg_id;
294
295   //g_print ("Client connected.\n"
296   //         "Negotiated capabilities: unix-fd-passing=%d\n",
297   //         g_dbus_connection_get_capabilities (connection) & G_DBUS_CAPABILITY_FLAGS_UNIX_FD_PASSING);
298
299   g_ptr_array_add (data->current_connections, g_object_ref (connection));
300
301   /* export object on the newly established connection */
302   error = NULL;
303   reg_id = g_dbus_connection_register_object (connection,
304                                               "/org/gtk/GDBus/PeerTestObject",
305                                               test_interface_introspection_data,
306                                               &test_interface_vtable,
307                                               data,
308                                               NULL, /* GDestroyNotify for data */
309                                               &error);
310   g_assert_no_error (error);
311   g_assert (reg_id > 0);
312
313   g_main_loop_quit (loop);
314
315   return TRUE;
316 }
317
318 static gpointer
319 service_thread_func (gpointer user_data)
320 {
321   PeerData *data = user_data;
322   GMainContext *service_context;
323   GDBusAuthObserver *observer;
324   GError *error;
325
326   service_context = g_main_context_new ();
327   g_main_context_push_thread_default (service_context);
328
329   error = NULL;
330   observer = g_dbus_auth_observer_new ();
331   server = g_dbus_server_new_sync (is_unix ? "unix:tmpdir=/tmp/gdbus-test-" : "nonce-tcp:",
332                                    G_DBUS_SERVER_FLAGS_NONE,
333                                    test_guid,
334                                    observer,
335                                    NULL, /* cancellable */
336                                    &error);
337   g_assert_no_error (error);
338
339   g_signal_connect (server,
340                     "new-connection",
341                     G_CALLBACK (on_new_connection),
342                     data);
343   g_signal_connect (observer,
344                     "authorize-authenticated-peer",
345                     G_CALLBACK (on_authorize_authenticated_peer),
346                     data);
347   g_object_unref (observer);
348
349   g_dbus_server_start (server);
350
351   service_loop = g_main_loop_new (service_context, FALSE);
352   g_main_loop_run (service_loop);
353
354   g_main_context_pop_thread_default (service_context);
355
356   g_main_loop_unref (service_loop);
357   g_main_context_unref (service_context);
358
359   /* test code specifically unrefs the server - see below */
360   g_assert (server == NULL);
361
362   return NULL;
363 }
364
365 #if 0
366 static gboolean
367 on_incoming_connection (GSocketService     *service,
368                         GSocketConnection  *socket_connection,
369                         GObject            *source_object,
370                         gpointer           user_data)
371 {
372   PeerData *data = user_data;
373
374   if (data->accept_connection)
375     {
376       GError *error;
377       guint reg_id;
378       GDBusConnection *connection;
379
380       error = NULL;
381       connection = g_dbus_connection_new_sync (G_IO_STREAM (socket_connection),
382                                                test_guid,
383                                                G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER,
384                                                NULL, /* cancellable */
385                                                &error);
386       g_assert_no_error (error);
387
388       g_ptr_array_add (data->current_connections, connection);
389
390       /* export object on the newly established connection */
391       error = NULL;
392       reg_id = g_dbus_connection_register_object (connection,
393                                                   "/org/gtk/GDBus/PeerTestObject",
394                                                   &test_interface_introspection_data,
395                                                   &test_interface_vtable,
396                                                   data,
397                                                   NULL, /* GDestroyNotify for data */
398                                                   &error);
399       g_assert_no_error (error);
400       g_assert (reg_id > 0);
401
402     }
403   else
404     {
405       /* don't do anything */
406     }
407
408   data->num_connection_attempts++;
409
410   g_main_loop_quit (loop);
411
412   /* stops other signal handlers from being invoked */
413   return TRUE;
414 }
415
416 static gpointer
417 service_thread_func (gpointer data)
418 {
419   GMainContext *service_context;
420   gchar *socket_path;
421   GSocketAddress *address;
422   GError *error;
423
424   service_context = g_main_context_new ();
425   g_main_context_push_thread_default (service_context);
426
427   socket_path = g_strdup_printf ("/tmp/gdbus-test-pid-%d", getpid ());
428   address = g_unix_socket_address_new (socket_path);
429
430   service = g_socket_service_new ();
431   error = NULL;
432   g_socket_listener_add_address (G_SOCKET_LISTENER (service),
433                                  address,
434                                  G_SOCKET_TYPE_STREAM,
435                                  G_SOCKET_PROTOCOL_DEFAULT,
436                                  NULL, /* source_object */
437                                  NULL, /* effective_address */
438                                  &error);
439   g_assert_no_error (error);
440   g_signal_connect (service,
441                     "incoming",
442                     G_CALLBACK (on_incoming_connection),
443                     data);
444   g_socket_service_start (service);
445
446   service_loop = g_main_loop_new (service_context, FALSE);
447   g_main_loop_run (service_loop);
448
449   g_main_context_pop_thread_default (service_context);
450
451   g_main_loop_unref (service_loop);
452   g_main_context_unref (service_context);
453
454   g_object_unref (address);
455   g_free (socket_path);
456   return NULL;
457 }
458 #endif
459
460 /* ---------------------------------------------------------------------------------------------------- */
461
462 #if 0
463 static gboolean
464 check_connection (gpointer user_data)
465 {
466   PeerData *data = user_data;
467   guint n;
468
469   for (n = 0; n < data->current_connections->len; n++)
470     {
471       GDBusConnection *c;
472       GIOStream *stream;
473
474       c = G_DBUS_CONNECTION (data->current_connections->pdata[n]);
475       stream = g_dbus_connection_get_stream (c);
476
477       g_debug ("In check_connection for %d: connection %p, stream %p", n, c, stream);
478       g_debug ("closed = %d", g_io_stream_is_closed (stream));
479
480       GSocket *socket;
481       socket = g_socket_connection_get_socket (G_SOCKET_CONNECTION (stream));
482       g_debug ("socket_closed = %d", g_socket_is_closed (socket));
483       g_debug ("socket_condition_check = %d", g_socket_condition_check (socket, G_IO_IN|G_IO_OUT|G_IO_ERR|G_IO_HUP));
484
485       gchar buf[128];
486       GError *error;
487       gssize num_read;
488       error = NULL;
489       num_read = g_input_stream_read (g_io_stream_get_input_stream (stream),
490                                       buf,
491                                       128,
492                                       NULL,
493                                       &error);
494       if (num_read < 0)
495         {
496           g_debug ("error: %s", error->message);
497           g_error_free (error);
498         }
499       else
500         {
501           g_debug ("no error, read %d bytes", (gint) num_read);
502         }
503     }
504
505   return FALSE;
506 }
507
508 static gboolean
509 on_do_disconnect_in_idle (gpointer data)
510 {
511   GDBusConnection *c = G_DBUS_CONNECTION (data);
512   g_debug ("GDC %p has ref_count %d", c, G_OBJECT (c)->ref_count);
513   g_dbus_connection_disconnect (c);
514   g_object_unref (c);
515   return FALSE;
516 }
517 #endif
518
519 #ifdef G_OS_UNIX
520 static gchar *
521 read_all_from_fd (gint fd, gsize *out_len, GError **error)
522 {
523   GString *str;
524   gchar buf[64];
525   gssize num_read;
526
527   str = g_string_new (NULL);
528
529   do
530     {
531       num_read = read (fd, buf, sizeof (buf));
532       if (num_read == -1)
533         {
534           if (errno == EAGAIN || errno == EWOULDBLOCK)
535             continue;
536           g_set_error (error,
537                        G_IO_ERROR,
538                        g_io_error_from_errno (errno),
539                        "Failed reading %d bytes into offset %d: %s",
540                        (gint) sizeof (buf),
541                        (gint) str->len,
542                        strerror (errno));
543           goto error;
544         }
545       else if (num_read > 0)
546         {
547           g_string_append_len (str, buf, num_read);
548         }
549       else if (num_read == 0)
550         {
551           break;
552         }
553     }
554   while (TRUE);
555
556   if (out_len != NULL)
557     *out_len = str->len;
558   return g_string_free (str, FALSE);
559
560  error:
561   if (out_len != NULL)
562     out_len = 0;
563   g_string_free (str, TRUE);
564   return NULL;
565 }
566 #endif
567
568 static void
569 test_peer (void)
570 {
571   GDBusConnection *c;
572   GDBusConnection *c2;
573   GDBusProxy *proxy;
574   GError *error;
575   PeerData data;
576   GVariant *value;
577   GVariant *result;
578   const gchar *s;
579   GThread *service_thread;
580   gulong signal_handler_id;
581
582   memset (&data, '\0', sizeof (PeerData));
583   data.current_connections = g_ptr_array_new_with_free_func (g_object_unref);
584
585   /* first try to connect when there is no server */
586   error = NULL;
587   c = g_dbus_connection_new_for_address_sync (is_unix ? "unix:path=/tmp/gdbus-test-does-not-exist-pid" :
588                                               /* NOTE: Even if something is listening on port 12345 the connection
589                                                * will fail because the nonce file doesn't exist */
590                                               "nonce-tcp:host=localhost,port=12345,noncefile=this-does-not-exist-gdbus",
591                                               G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
592                                               NULL, /* GDBusAuthObserver */
593                                               NULL, /* cancellable */
594                                               &error);
595   _g_assert_error_domain (error, G_IO_ERROR);
596   g_assert (!g_dbus_error_is_remote_error (error));
597   g_clear_error (&error);
598   g_assert (c == NULL);
599
600   /* bring up a server - we run the server in a different thread to avoid deadlocks */
601   error = NULL;
602   service_thread = g_thread_create (service_thread_func,
603                                     &data,
604                                     TRUE,
605                                     &error);
606   while (service_loop == NULL)
607     g_thread_yield ();
608   g_assert (server != NULL);
609
610   /* bring up a connection and accept it */
611   data.accept_connection = TRUE;
612   error = NULL;
613   c = g_dbus_connection_new_for_address_sync (g_dbus_server_get_client_address (server),
614                                               G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
615                                               NULL, /* GDBusAuthObserver */
616                                               NULL, /* cancellable */
617                                               &error);
618   g_assert_no_error (error);
619   g_assert (c != NULL);
620   while (data.current_connections->len < 1)
621     g_main_loop_run (loop);
622   g_assert_cmpint (data.current_connections->len, ==, 1);
623   g_assert_cmpint (data.num_connection_attempts, ==, 1);
624   g_assert (g_dbus_connection_get_unique_name (c) == NULL);
625   g_assert_cmpstr (g_dbus_connection_get_guid (c), ==, test_guid);
626
627   /* check that we create a proxy, read properties, receive signals and invoke
628    * the HelloPeer() method. Since the server runs in another thread it's fine
629    * to use synchronous blocking API here.
630    */
631   error = NULL;
632   proxy = g_dbus_proxy_new_sync (c,
633                                  G_DBUS_PROXY_FLAGS_NONE,
634                                  NULL,
635                                  NULL, /* bus_name */
636                                  "/org/gtk/GDBus/PeerTestObject",
637                                  "org.gtk.GDBus.PeerTestInterface",
638                                  NULL, /* GCancellable */
639                                  &error);
640   g_assert_no_error (error);
641   g_assert (proxy != NULL);
642   error = NULL;
643   value = g_dbus_proxy_get_cached_property (proxy, "PeerProperty");
644   g_assert_cmpstr (g_variant_get_string (value, NULL), ==, "ThePropertyValue");
645
646   /* try invoking a method */
647   error = NULL;
648   result = g_dbus_proxy_call_sync (proxy,
649                                    "HelloPeer",
650                                    g_variant_new ("(s)", "Hey Peer!"),
651                                    G_DBUS_CALL_FLAGS_NONE,
652                                    -1,
653                                    NULL,  /* GCancellable */
654                                    &error);
655   g_assert_no_error (error);
656   g_variant_get (result, "(&s)", &s);
657   g_assert_cmpstr (s, ==, "You greeted me with 'Hey Peer!'.");
658   g_variant_unref (result);
659   g_assert_cmpint (data.num_method_calls, ==, 1);
660
661   /* make the other peer emit a signal - catch it */
662   signal_handler_id = g_signal_connect (proxy,
663                                         "g-signal",
664                                         G_CALLBACK (on_proxy_signal_received),
665                                         &data);
666   g_assert (!data.signal_received);
667   g_dbus_proxy_call (proxy,
668                      "EmitSignal",
669                      NULL,  /* no arguments */
670                      G_DBUS_CALL_FLAGS_NONE,
671                      -1,
672                      NULL,  /* GCancellable */
673                      NULL,  /* GAsyncReadyCallback - we don't care about the result */
674                      NULL); /* user_data */
675   g_main_loop_run (loop);
676   g_assert (data.signal_received);
677   g_assert_cmpint (data.num_method_calls, ==, 2);
678   g_signal_handler_disconnect (proxy, signal_handler_id);
679
680   /* Also ensure that messages with the sender header-field set gets
681    * delivered to the proxy - note that this doesn't really make sense
682    * e.g. names are meaning-less in a peer-to-peer case... but we
683    * support it because it makes sense in certain bridging
684    * applications - see e.g. #623815.
685    */
686   signal_handler_id = g_signal_connect (proxy,
687                                         "g-signal",
688                                         G_CALLBACK (on_proxy_signal_received_with_name_set),
689                                         &data);
690   data.signal_received = FALSE;
691   g_dbus_proxy_call (proxy,
692                      "EmitSignalWithNameSet",
693                      NULL,  /* no arguments */
694                      G_DBUS_CALL_FLAGS_NONE,
695                      -1,
696                      NULL,  /* GCancellable */
697                      NULL,  /* GAsyncReadyCallback - we don't care about the result */
698                      NULL); /* user_data */
699   g_main_loop_run (loop);
700   g_assert (data.signal_received);
701   g_assert_cmpint (data.num_method_calls, ==, 3);
702   g_signal_handler_disconnect (proxy, signal_handler_id);
703
704   /* check for UNIX fd passing */
705 #ifdef G_OS_UNIX
706   {
707     GDBusMessage *method_call_message;
708     GDBusMessage *method_reply_message;
709     GUnixFDList *fd_list;
710     gint fd;
711     gchar *buf;
712     gsize len;
713     gchar *buf2;
714     gsize len2;
715
716     method_call_message = g_dbus_message_new_method_call (NULL, /* name */
717                                                           "/org/gtk/GDBus/PeerTestObject",
718                                                           "org.gtk.GDBus.PeerTestInterface",
719                                                           "OpenFile");
720     g_dbus_message_set_body (method_call_message, g_variant_new ("(s)", "/etc/hosts"));
721     error = NULL;
722     method_reply_message = g_dbus_connection_send_message_with_reply_sync (c,
723                                                                            method_call_message,
724                                                                            G_DBUS_SEND_MESSAGE_FLAGS_NONE,
725                                                                            -1,
726                                                                            NULL, /* out_serial */
727                                                                            NULL, /* cancellable */
728                                                                            &error);
729     g_assert_no_error (error);
730     g_assert (g_dbus_message_get_message_type (method_reply_message) == G_DBUS_MESSAGE_TYPE_METHOD_RETURN);
731     fd_list = g_dbus_message_get_unix_fd_list (method_reply_message);
732     g_assert (fd_list != NULL);
733     g_assert_cmpint (g_unix_fd_list_get_length (fd_list), ==, 1);
734     error = NULL;
735     fd = g_unix_fd_list_get (fd_list, 0, &error);
736     g_assert_no_error (error);
737     g_object_unref (method_call_message);
738     g_object_unref (method_reply_message);
739
740     error = NULL;
741     len = 0;
742     buf = read_all_from_fd (fd, &len, &error);
743     g_assert_no_error (error);
744     g_assert (buf != NULL);
745     close (fd);
746
747     error = NULL;
748     g_file_get_contents ("/etc/hosts",
749                          &buf2,
750                          &len2,
751                          &error);
752     g_assert_no_error (error);
753     g_assert_cmpint (len, ==, len2);
754     g_assert (memcmp (buf, buf2, len) == 0);
755     g_free (buf2);
756     g_free (buf);
757   }
758 #else
759   error = NULL;
760   result = g_dbus_proxy_call_sync (proxy,
761                                    "OpenFile",
762                                    g_variant_new ("(s)", "boo"),
763                                    G_DBUS_CALL_FLAGS_NONE,
764                                    -1,
765                                    NULL,  /* GCancellable */
766                                    &error);
767   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_DBUS_ERROR);
768   g_assert (result == NULL);
769   g_error_free (error);
770 #endif /* G_OS_UNIX */
771
772   /* Check that g_socket_get_credentials() work - this really should
773    * be in a GSocket-specific test suite but no such test suite exists
774    * right now.
775    */
776   {
777     GSocket *socket;
778     GCredentials *credentials;
779     socket = g_socket_connection_get_socket (G_SOCKET_CONNECTION (g_dbus_connection_get_stream (c)));
780     g_assert (G_IS_SOCKET (socket));
781     error = NULL;
782     credentials = g_socket_get_credentials (socket, &error);
783 #ifdef __linux__
784     {
785       struct ucred *native_creds;
786       g_assert_no_error (error);
787       g_assert (G_IS_CREDENTIALS (credentials));
788       native_creds = g_credentials_get_native (credentials, G_CREDENTIALS_TYPE_LINUX_UCRED);
789       g_assert (native_creds != NULL);
790       g_assert (native_creds->uid == getuid ());
791       g_assert (native_creds->gid == getgid ());
792       g_assert (native_creds->pid == getpid ());
793     }
794     g_object_unref (credentials);
795 #else
796     g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED);
797     g_assert (credentials == NULL);
798 #endif
799   }
800
801
802   /* bring up a connection - don't accept it - this should fail
803    */
804   data.accept_connection = FALSE;
805   error = NULL;
806   c2 = g_dbus_connection_new_for_address_sync (g_dbus_server_get_client_address (server),
807                                                G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
808                                                NULL, /* GDBusAuthObserver */
809                                                NULL, /* cancellable */
810                                                &error);
811   _g_assert_error_domain (error, G_IO_ERROR);
812   g_error_free (error);
813   g_assert (c2 == NULL);
814
815 #if 0
816   /* TODO: THIS TEST DOESN'T WORK YET */
817
818   /* bring up a connection - accept it.. then disconnect from the client side - check
819    * that the server side gets the disconnect signal.
820    */
821   error = NULL;
822   data.accept_connection = TRUE;
823   c2 = g_dbus_connection_new_for_address_sync (g_dbus_server_get_client_address (server),
824                                                G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
825                                                NULL, /* GDBusAuthObserver */
826                                                NULL, /* cancellable */
827                                                &error);
828   g_assert_no_error (error);
829   g_assert (c2 != NULL);
830   g_assert (!g_dbus_connection_get_is_disconnected (c2));
831   while (data.num_connection_attempts < 3)
832     g_main_loop_run (loop);
833   g_assert_cmpint (data.current_connections->len, ==, 2);
834   g_assert_cmpint (data.num_connection_attempts, ==, 3);
835   g_assert (!g_dbus_connection_get_is_disconnected (G_DBUS_CONNECTION (data.current_connections->pdata[1])));
836   g_idle_add (on_do_disconnect_in_idle, c2);
837   g_debug ("==================================================");
838   g_debug ("==================================================");
839   g_debug ("==================================================");
840   g_debug ("waiting for disconnect on connection %p, stream %p",
841            data.current_connections->pdata[1],
842            g_dbus_connection_get_stream (data.current_connections->pdata[1]));
843
844   g_timeout_add (2000, check_connection, &data);
845   //_g_assert_signal_received (G_DBUS_CONNECTION (data.current_connections->pdata[1]), "closed");
846   g_main_loop_run (loop);
847   g_assert (g_dbus_connection_get_is_disconnected (G_DBUS_CONNECTION (data.current_connections->pdata[1])));
848   g_ptr_array_set_size (data.current_connections, 1); /* remove disconnected connection object */
849 #endif
850
851   /* unref the server and stop listening for new connections
852    *
853    * This won't bring down the established connections - check that c is still connected
854    * by invoking a method
855    */
856   //g_socket_service_stop (service);
857   //g_object_unref (service);
858   g_dbus_server_stop (server);
859   g_object_unref (server);
860   server = NULL;
861
862   error = NULL;
863   result = g_dbus_proxy_call_sync (proxy,
864                                    "HelloPeer",
865                                    g_variant_new ("(s)", "Hey Again Peer!"),
866                                    G_DBUS_CALL_FLAGS_NONE,
867                                    -1,
868                                    NULL,  /* GCancellable */
869                                    &error);
870   g_assert_no_error (error);
871   g_variant_get (result, "(&s)", &s);
872   g_assert_cmpstr (s, ==, "You greeted me with 'Hey Again Peer!'.");
873   g_variant_unref (result);
874   g_assert_cmpint (data.num_method_calls, ==, 5);
875
876 #if 0
877   /* TODO: THIS TEST DOESN'T WORK YET */
878
879   /* now disconnect from the server side - check that the client side gets the signal */
880   g_assert_cmpint (data.current_connections->len, ==, 1);
881   g_assert (G_DBUS_CONNECTION (data.current_connections->pdata[0]) != c);
882   g_dbus_connection_disconnect (G_DBUS_CONNECTION (data.current_connections->pdata[0]));
883   if (!g_dbus_connection_get_is_disconnected (c))
884     _g_assert_signal_received (c, "closed");
885   g_assert (g_dbus_connection_get_is_disconnected (c));
886 #endif
887
888   g_object_unref (c);
889   g_ptr_array_unref (data.current_connections);
890   g_object_unref (proxy);
891
892   g_main_loop_quit (service_loop);
893   g_thread_join (service_thread);
894 }
895
896 /* ---------------------------------------------------------------------------------------------------- */
897
898 typedef struct
899 {
900   GDBusServer *server;
901   GMainContext *context;
902   GMainLoop *loop;
903
904   GList *connections;
905 } DmpData;
906
907 static void
908 dmp_data_free (DmpData *data)
909 {
910   g_main_loop_unref (data->loop);
911   g_main_context_unref (data->context);
912   g_object_unref (data->server);
913   g_list_foreach (data->connections, (GFunc) g_object_unref, NULL);
914   g_list_free (data->connections);
915   g_free (data);
916 }
917
918 static void
919 dmp_on_method_call (GDBusConnection       *connection,
920                     const gchar           *sender,
921                     const gchar           *object_path,
922                     const gchar           *interface_name,
923                     const gchar           *method_name,
924                     GVariant              *parameters,
925                     GDBusMethodInvocation *invocation,
926                     gpointer               user_data)
927 {
928   //DmpData *data = user_data;
929   gint32 first;
930   gint32 second;
931   g_variant_get (parameters,
932                  "(ii)",
933                  &first,
934                  &second);
935   g_dbus_method_invocation_return_value (invocation,
936                                          g_variant_new ("(i)", first + second));
937 }
938
939 static const GDBusInterfaceVTable dmp_interface_vtable =
940 {
941   dmp_on_method_call,
942   NULL,  /* get_property */
943   NULL   /* set_property */
944 };
945
946
947 /* Runs in thread we created GDBusServer in (since we didn't pass G_DBUS_SERVER_FLAGS_RUN_IN_THREAD) */
948 static gboolean
949 dmp_on_new_connection (GDBusServer     *server,
950                        GDBusConnection *connection,
951                        gpointer         user_data)
952 {
953   DmpData *data = user_data;
954   GDBusNodeInfo *node;
955   GError *error;
956
957   /* accept the connection */
958   data->connections = g_list_prepend (data->connections, g_object_ref (connection));
959
960   error = NULL;
961   node = g_dbus_node_info_new_for_xml ("<node>"
962                                        "  <interface name='org.gtk.GDBus.DmpInterface'>"
963                                        "    <method name='AddPair'>"
964                                        "      <arg type='i' name='first' direction='in'/>"
965                                        "      <arg type='i' name='second' direction='in'/>"
966                                        "      <arg type='i' name='sum' direction='out'/>"
967                                        "    </method>"
968                                        "  </interface>"
969                                        "</node>",
970                                        &error);
971   g_assert_no_error (error);
972
973   /* sleep 100ms before exporting an object - this is to test that
974    * G_DBUS_CONNECTION_FLAGS_DELAY_MESSAGE_PROCESSING really works
975    * (GDBusServer uses this feature).
976    */
977   usleep (100 * 1000);
978
979   /* export an object */
980   error = NULL;
981   g_dbus_connection_register_object (connection,
982                                      "/dmp/test",
983                                      node->interfaces[0],
984                                      &dmp_interface_vtable,
985                                      data,
986                                      NULL,
987                                      &error);
988   g_dbus_node_info_unref (node);
989
990   return TRUE;
991 }
992
993 static gpointer
994 dmp_thread_func (gpointer user_data)
995 {
996   DmpData *data = user_data;
997   GError *error;
998   gchar *guid;
999
1000   data->context = g_main_context_new ();
1001   g_main_context_push_thread_default (data->context);
1002
1003   error = NULL;
1004   guid = g_dbus_generate_guid ();
1005   data->server = g_dbus_server_new_sync ("unix:tmpdir=/tmp/gdbus-test-",
1006                                          G_DBUS_SERVER_FLAGS_NONE,
1007                                          guid,
1008                                          NULL, /* GDBusAuthObserver */
1009                                          NULL, /* GCancellable */
1010                                          &error);
1011   g_assert_no_error (error);
1012   g_signal_connect (data->server,
1013                     "new-connection",
1014                     G_CALLBACK (dmp_on_new_connection),
1015                     data);
1016
1017   g_dbus_server_start (data->server);
1018
1019   data->loop = g_main_loop_new (data->context, FALSE);
1020   g_main_loop_run (data->loop);
1021
1022   g_main_context_pop_thread_default (data->context);
1023
1024   g_free (guid);
1025   return NULL;
1026 }
1027
1028 static void
1029 delayed_message_processing (void)
1030 {
1031   GError *error;
1032   DmpData *data;
1033   GThread *service_thread;
1034   guint n;
1035
1036   data = g_new0 (DmpData, 1);
1037
1038   error = NULL;
1039   service_thread = g_thread_create (dmp_thread_func,
1040                                     data,
1041                                     TRUE,
1042                                     &error);
1043   while (data->server == NULL || !g_dbus_server_is_active (data->server))
1044     g_thread_yield ();
1045
1046   for (n = 0; n < 5; n++)
1047     {
1048       GDBusConnection *c;
1049       GVariant *res;
1050       gint32 val;
1051
1052       error = NULL;
1053       c = g_dbus_connection_new_for_address_sync (g_dbus_server_get_client_address (data->server),
1054                                                   G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
1055                                                   NULL, /* GDBusAuthObserver */
1056                                                   NULL, /* GCancellable */
1057                                                   &error);
1058       g_assert_no_error (error);
1059
1060       error = NULL;
1061       res = g_dbus_connection_call_sync (c,
1062                                          NULL,    /* bus name */
1063                                          "/dmp/test",
1064                                          "org.gtk.GDBus.DmpInterface",
1065                                          "AddPair",
1066                                          g_variant_new ("(ii)", 2, n),
1067                                          G_VARIANT_TYPE ("(i)"),
1068                                          G_DBUS_CALL_FLAGS_NONE,
1069                                          -1, /* timeout_msec */
1070                                          NULL, /* GCancellable */
1071                                          &error);
1072       g_assert_no_error (error);
1073       g_variant_get (res, "(i)", &val);
1074       g_assert_cmpint (val, ==, 2 + n);
1075       g_variant_unref (res);
1076       g_object_unref (c);
1077   }
1078
1079   g_main_loop_quit (data->loop);
1080   g_thread_join (service_thread);
1081   dmp_data_free (data);
1082 }
1083
1084 /* ---------------------------------------------------------------------------------------------------- */
1085
1086 static gboolean
1087 nonce_tcp_on_authorize_authenticated_peer (GDBusAuthObserver *observer,
1088                                            GIOStream         *stream,
1089                                            GCredentials      *credentials,
1090                                            gpointer           user_data)
1091 {
1092   PeerData *data = user_data;
1093   gboolean authorized;
1094
1095   data->num_connection_attempts++;
1096
1097   authorized = TRUE;
1098   if (!data->accept_connection)
1099     {
1100       authorized = FALSE;
1101       g_main_loop_quit (loop);
1102     }
1103
1104   return authorized;
1105 }
1106
1107 /* Runs in thread we created GDBusServer in (since we didn't pass G_DBUS_SERVER_FLAGS_RUN_IN_THREAD) */
1108 static gboolean
1109 nonce_tcp_on_new_connection (GDBusServer *server,
1110                              GDBusConnection *connection,
1111                              gpointer user_data)
1112 {
1113   PeerData *data = user_data;
1114
1115   g_ptr_array_add (data->current_connections, g_object_ref (connection));
1116
1117   g_main_loop_quit (loop);
1118
1119   return TRUE;
1120 }
1121
1122 static gpointer
1123 nonce_tcp_service_thread_func (gpointer user_data)
1124 {
1125   PeerData *data = user_data;
1126   GMainContext *service_context;
1127   GDBusAuthObserver *observer;
1128   GError *error;
1129
1130   service_context = g_main_context_new ();
1131   g_main_context_push_thread_default (service_context);
1132
1133   error = NULL;
1134   observer = g_dbus_auth_observer_new ();
1135   server = g_dbus_server_new_sync ("nonce-tcp:",
1136                                    G_DBUS_SERVER_FLAGS_NONE,
1137                                    test_guid,
1138                                    observer,
1139                                    NULL, /* cancellable */
1140                                    &error);
1141   g_assert_no_error (error);
1142
1143   g_signal_connect (server,
1144                     "new-connection",
1145                     G_CALLBACK (nonce_tcp_on_new_connection),
1146                     data);
1147   g_signal_connect (observer,
1148                     "authorize-authenticated-peer",
1149                     G_CALLBACK (nonce_tcp_on_authorize_authenticated_peer),
1150                     data);
1151   g_object_unref (observer);
1152
1153   g_dbus_server_start (server);
1154
1155   service_loop = g_main_loop_new (service_context, FALSE);
1156   g_main_loop_run (service_loop);
1157
1158   g_main_context_pop_thread_default (service_context);
1159
1160   g_main_loop_unref (service_loop);
1161   g_main_context_unref (service_context);
1162
1163   /* test code specifically unrefs the server - see below */
1164   g_assert (server == NULL);
1165
1166   return NULL;
1167 }
1168
1169 static void
1170 test_nonce_tcp (void)
1171 {
1172   PeerData data;
1173   GError *error;
1174   GThread *service_thread;
1175   GDBusConnection *c;
1176   gchar *s;
1177   gchar *nonce_file;
1178   gboolean res;
1179   const gchar *address;
1180
1181   memset (&data, '\0', sizeof (PeerData));
1182   data.current_connections = g_ptr_array_new_with_free_func (g_object_unref);
1183
1184   error = NULL;
1185   server = NULL;
1186   service_loop = NULL;
1187   service_thread = g_thread_create (nonce_tcp_service_thread_func,
1188                                     &data,
1189                                     TRUE,
1190                                     &error);
1191   while (service_loop == NULL)
1192     g_thread_yield ();
1193   g_assert (server != NULL);
1194
1195
1196   /* bring up a connection and accept it */
1197   data.accept_connection = TRUE;
1198   error = NULL;
1199   c = g_dbus_connection_new_for_address_sync (g_dbus_server_get_client_address (server),
1200                                               G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
1201                                               NULL, /* GDBusAuthObserver */
1202                                               NULL, /* cancellable */
1203                                               &error);
1204   g_assert_no_error (error);
1205   g_assert (c != NULL);
1206   while (data.current_connections->len < 1)
1207     g_main_loop_run (loop);
1208   g_assert_cmpint (data.current_connections->len, ==, 1);
1209   g_assert_cmpint (data.num_connection_attempts, ==, 1);
1210   g_assert (g_dbus_connection_get_unique_name (c) == NULL);
1211   g_assert_cmpstr (g_dbus_connection_get_guid (c), ==, test_guid);
1212   g_object_unref (c);
1213
1214   /* now, try to subvert the nonce file (this assumes noncefile is the last key/value pair)
1215    */
1216
1217   address = g_dbus_server_get_client_address (server);
1218
1219   s = strstr (address, "noncefile=");
1220   g_assert (s != NULL);
1221   s += sizeof "noncefile=" - 1;
1222   nonce_file = g_strdup (s);
1223
1224   /* First try invalid data in the nonce file - this will actually
1225    * make the client send this and the server will reject it. The way
1226    * it works is that if the nonce doesn't match, the server will
1227    * simply close the connection. So, from the client point of view,
1228    * we can see a variety of errors.
1229    */
1230   error = NULL;
1231   res = g_file_set_contents (nonce_file,
1232                              "0123456789012345",
1233                              -1,
1234                              &error);
1235   g_assert_no_error (error);
1236   g_assert (res);
1237   c = g_dbus_connection_new_for_address_sync (address,
1238                                               G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
1239                                               NULL, /* GDBusAuthObserver */
1240                                               NULL, /* cancellable */
1241                                               &error);
1242   _g_assert_error_domain (error, G_IO_ERROR);
1243   g_error_free (error);
1244   g_assert (c == NULL);
1245
1246   /* Then try with a nonce-file of incorrect length - this will make
1247    * the client complain - we won't even try connecting to the server
1248    * for this
1249    */
1250   error = NULL;
1251   res = g_file_set_contents (nonce_file,
1252                              "0123456789012345_",
1253                              -1,
1254                              &error);
1255   g_assert_no_error (error);
1256   g_assert (res);
1257   c = g_dbus_connection_new_for_address_sync (address,
1258                                               G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
1259                                               NULL, /* GDBusAuthObserver */
1260                                               NULL, /* cancellable */
1261                                               &error);
1262   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1263   g_error_free (error);
1264   g_assert (c == NULL);
1265
1266   /* Finally try with no nonce-file at all */
1267   g_assert_cmpint (g_unlink (nonce_file), ==, 0);
1268   error = NULL;
1269   c = g_dbus_connection_new_for_address_sync (address,
1270                                               G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
1271                                               NULL, /* GDBusAuthObserver */
1272                                               NULL, /* cancellable */
1273                                               &error);
1274   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1275   g_error_free (error);
1276   g_assert (c == NULL);
1277
1278   g_free (nonce_file);
1279
1280   g_dbus_server_stop (server);
1281   g_object_unref (server);
1282   server = NULL;
1283
1284   g_main_loop_quit (service_loop);
1285   g_thread_join (service_thread);
1286 }
1287
1288 static void
1289 test_credentials (void)
1290 {
1291   GCredentials *c1, *c2;
1292   GError *error;
1293   gchar *desc;
1294
1295   c1 = g_credentials_new ();
1296   c2 = g_credentials_new ();
1297
1298   error = NULL;
1299   if (g_credentials_set_unix_user (c2, getuid (), &error))
1300     g_assert_no_error (error);
1301
1302   g_clear_error (&error);
1303   g_assert (g_credentials_is_same_user (c1, c2, &error));
1304   g_assert_no_error (error);
1305
1306   desc = g_credentials_to_string (c1);
1307   g_assert (desc != NULL);
1308   g_free (desc);
1309
1310   g_object_unref (c1);
1311   g_object_unref (c2);
1312 }
1313
1314 /* ---------------------------------------------------------------------------------------------------- */
1315
1316 #ifdef G_OS_UNIX
1317
1318 /* Chosen to be big enough to overflow the socket buffer */
1319 #define OVERFLOW_NUM_SIGNALS 5000
1320 #define OVERFLOW_TIMEOUT_SEC 10
1321
1322 static GDBusMessage *
1323 overflow_filter_func (GDBusConnection *connection,
1324                       GDBusMessage    *message,
1325                       gboolean         incoming,
1326                       gpointer         user_data)
1327 {
1328   volatile gint *counter = user_data;
1329   *counter += 1;
1330   return message;
1331 }
1332
1333 static gboolean
1334 overflow_on_500ms_later_func (gpointer user_data)
1335 {
1336   g_main_loop_quit (loop);
1337   return FALSE; /* don't keep the idle */
1338 }
1339
1340 static void
1341 test_overflow (void)
1342 {
1343   gint sv[2];
1344   gint n;
1345   GSocket *socket;
1346   GSocketConnection *socket_connection;
1347   GDBusConnection *producer, *consumer;
1348   GError *error;
1349   GTimer *timer;
1350   volatile gint n_messages_received;
1351   volatile gint n_messages_sent;
1352
1353   g_assert_cmpint (socketpair (AF_UNIX, SOCK_STREAM, 0, sv), ==, 0);
1354
1355   error = NULL;
1356   socket = g_socket_new_from_fd (sv[0], &error);
1357   g_assert_no_error (error);
1358   socket_connection = g_socket_connection_factory_create_connection (socket);
1359   g_assert (socket_connection != NULL);
1360   g_object_unref (socket);
1361   producer = g_dbus_connection_new_sync (G_IO_STREAM (socket_connection),
1362                                          NULL, /* guid */
1363                                          G_DBUS_CONNECTION_FLAGS_NONE,
1364                                          NULL, /* GDBusAuthObserver */
1365                                          NULL, /* GCancellable */
1366                                          &error);
1367   g_dbus_connection_set_exit_on_close (producer, TRUE);
1368   g_assert_no_error (error);
1369   g_object_unref (socket_connection);
1370   n_messages_sent = 0;
1371   g_dbus_connection_add_filter (producer, overflow_filter_func, (gpointer) &n_messages_sent, NULL);
1372
1373   /* send enough data that we get an EAGAIN */
1374   for (n = 0; n < OVERFLOW_NUM_SIGNALS; n++)
1375     {
1376       error = NULL;
1377       g_dbus_connection_emit_signal (producer,
1378                                      NULL, /* destination */
1379                                      "/org/foo/Object",
1380                                      "org.foo.Interface",
1381                                      "Member",
1382                                      g_variant_new ("(s)", "a string"),
1383                                      &error);
1384       g_assert_no_error (error);
1385     }
1386
1387   /* sleep for 0.5 sec (to allow the GDBus IO thread to fill up the
1388    * kernel buffers) and verify that n_messages_sent <
1389    * OVERFLOW_NUM_SIGNALS
1390    *
1391    * This is to verify that not all the submitted messages have been
1392    * sent to the underlying transport.
1393    */
1394   g_timeout_add (500, overflow_on_500ms_later_func, NULL);
1395   g_main_loop_run (loop);
1396   g_assert_cmpint (n_messages_sent, <, OVERFLOW_NUM_SIGNALS);
1397
1398   /* now suck it all out as a client, and add it up */
1399   socket = g_socket_new_from_fd (sv[1], &error);
1400   g_assert_no_error (error);
1401   socket_connection = g_socket_connection_factory_create_connection (socket);
1402   g_assert (socket_connection != NULL);
1403   g_object_unref (socket);
1404   consumer = g_dbus_connection_new_sync (G_IO_STREAM (socket_connection),
1405                                          NULL, /* guid */
1406                                          G_DBUS_CONNECTION_FLAGS_DELAY_MESSAGE_PROCESSING,
1407                                          NULL, /* GDBusAuthObserver */
1408                                          NULL, /* GCancellable */
1409                                          &error);
1410   g_assert_no_error (error);
1411   g_object_unref (socket_connection);
1412   n_messages_received = 0;
1413   g_dbus_connection_add_filter (consumer, overflow_filter_func, (gpointer) &n_messages_received, NULL);
1414   g_dbus_connection_start_message_processing (consumer);
1415
1416   timer = g_timer_new ();
1417   g_timer_start (timer);
1418
1419   while (n_messages_received < OVERFLOW_NUM_SIGNALS && g_timer_elapsed (timer, NULL) < OVERFLOW_TIMEOUT_SEC)
1420       g_main_context_iteration (NULL, FALSE);
1421
1422   g_assert_cmpint (n_messages_sent, ==, OVERFLOW_NUM_SIGNALS);
1423   g_assert_cmpint (n_messages_received, ==, OVERFLOW_NUM_SIGNALS);
1424
1425   g_timer_destroy (timer);
1426   g_object_unref (consumer);
1427   g_object_unref (producer);
1428 }
1429 #else
1430 static void
1431 test_overflow (void)
1432 {
1433   /* TODO: test this with e.g. GWin32InputStream/GWin32OutputStream */
1434 }
1435 #endif
1436
1437 /* ---------------------------------------------------------------------------------------------------- */
1438
1439 int
1440 main (int   argc,
1441       char *argv[])
1442 {
1443   gint ret;
1444   GDBusNodeInfo *introspection_data = NULL;
1445
1446   g_type_init ();
1447   g_thread_init (NULL);
1448   g_test_init (&argc, &argv, NULL);
1449
1450   introspection_data = g_dbus_node_info_new_for_xml (test_interface_introspection_xml, NULL);
1451   g_assert (introspection_data != NULL);
1452   test_interface_introspection_data = introspection_data->interfaces[0];
1453
1454   test_guid = g_dbus_generate_guid ();
1455
1456   /* all the tests rely on a shared main loop */
1457   loop = g_main_loop_new (NULL, FALSE);
1458
1459   g_test_add_func ("/gdbus/peer-to-peer", test_peer);
1460   g_test_add_func ("/gdbus/delayed-message-processing", delayed_message_processing);
1461   g_test_add_func ("/gdbus/nonce-tcp", test_nonce_tcp);
1462   g_test_add_func ("/gdbus/credentials", test_credentials);
1463   g_test_add_func ("/gdbus/overflow", test_overflow);
1464
1465   ret = g_test_run();
1466
1467   g_main_loop_unref (loop);
1468   g_free (test_guid);
1469   g_dbus_node_info_unref (introspection_data);
1470
1471   return ret;
1472 }