Imported Upstream version 2.67.4
[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.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 "config.h"
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/gnetworking.h>
37 #include <gio/gunixsocketaddress.h>
38 #include <gio/gunixfdlist.h>
39 #include <gio/gcredentialsprivate.h>
40
41 #ifdef G_OS_UNIX
42 #include <gio/gunixconnection.h>
43 #include <errno.h>
44 #endif
45
46 #include "gdbus-tests.h"
47
48 #include "gdbus-object-manager-example/objectmanager-gen.h"
49
50 #ifdef G_OS_UNIX
51 static gboolean is_unix = TRUE;
52 #else
53 static gboolean is_unix = FALSE;
54 #endif
55
56 static gchar *tmpdir = NULL;
57 static gchar *tmp_address = NULL;
58 static gchar *test_guid = NULL;
59 static GMutex service_loop_lock;
60 static GCond service_loop_cond;
61 static GMainLoop *service_loop = NULL;
62 static GDBusServer *server = NULL;
63 static GMainLoop *loop = NULL;
64
65 /* ---------------------------------------------------------------------------------------------------- */
66 /* Test that peer-to-peer connections work */
67 /* ---------------------------------------------------------------------------------------------------- */
68
69
70 typedef struct
71 {
72   gboolean accept_connection;
73   gint num_connection_attempts;
74   GPtrArray *current_connections;
75   guint num_method_calls;
76   gboolean signal_received;
77 } PeerData;
78
79 /* This needs to be enough to usually take more than one write(),
80  * to reproduce
81  * <https://gitlab.gnome.org/GNOME/glib/-/issues/2074>.
82  * 1 MiB ought to be enough. */
83 #define BIG_MESSAGE_ARRAY_SIZE (1024 * 1024)
84
85 static const gchar *test_interface_introspection_xml =
86   "<node>"
87   "  <interface name='org.gtk.GDBus.PeerTestInterface'>"
88   "    <method name='HelloPeer'>"
89   "      <arg type='s' name='greeting' direction='in'/>"
90   "      <arg type='s' name='response' direction='out'/>"
91   "    </method>"
92   "    <method name='EmitSignal'/>"
93   "    <method name='EmitSignalWithNameSet'/>"
94   "    <method name='OpenFile'>"
95   "      <arg type='s' name='path' direction='in'/>"
96   "    </method>"
97   "    <method name='OpenFileWithBigMessage'>"
98   "      <arg type='s' name='path' direction='in'/>"
99   "      <arg type='h' name='handle' direction='out'/>"
100   "      <arg type='ay' name='junk' direction='out'/>"
101   "    </method>"
102   "    <signal name='PeerSignal'>"
103   "      <arg type='s' name='a_string'/>"
104   "    </signal>"
105   "    <property type='s' name='PeerProperty' access='read'/>"
106   "  </interface>"
107   "</node>";
108 static GDBusInterfaceInfo *test_interface_introspection_data = NULL;
109
110 static void
111 test_interface_method_call (GDBusConnection       *connection,
112                             const gchar           *sender,
113                             const gchar           *object_path,
114                             const gchar           *interface_name,
115                             const gchar           *method_name,
116                             GVariant              *parameters,
117                             GDBusMethodInvocation *invocation,
118                             gpointer               user_data)
119 {
120   PeerData *data = user_data;
121   const GDBusMethodInfo *info;
122
123   data->num_method_calls++;
124
125   g_assert_cmpstr (object_path, ==, "/org/gtk/GDBus/PeerTestObject");
126   g_assert_cmpstr (interface_name, ==, "org.gtk.GDBus.PeerTestInterface");
127
128   info = g_dbus_method_invocation_get_method_info (invocation);
129   g_assert_cmpstr (info->name, ==, method_name);
130
131   if (g_strcmp0 (method_name, "HelloPeer") == 0)
132     {
133       const gchar *greeting;
134       gchar *response;
135
136       g_variant_get (parameters, "(&s)", &greeting);
137
138       response = g_strdup_printf ("You greeted me with '%s'.",
139                                   greeting);
140       g_dbus_method_invocation_return_value (invocation,
141                                              g_variant_new ("(s)", response));
142       g_free (response);
143     }
144   else if (g_strcmp0 (method_name, "EmitSignal") == 0)
145     {
146       GError *error;
147
148       error = NULL;
149       g_dbus_connection_emit_signal (connection,
150                                      NULL,
151                                      "/org/gtk/GDBus/PeerTestObject",
152                                      "org.gtk.GDBus.PeerTestInterface",
153                                      "PeerSignal",
154                                      NULL,
155                                      &error);
156       g_assert_no_error (error);
157       g_dbus_method_invocation_return_value (invocation, NULL);
158     }
159   else if (g_strcmp0 (method_name, "EmitSignalWithNameSet") == 0)
160     {
161       GError *error;
162       gboolean ret;
163       GDBusMessage *message;
164
165       message = g_dbus_message_new_signal ("/org/gtk/GDBus/PeerTestObject",
166                                            "org.gtk.GDBus.PeerTestInterface",
167                                            "PeerSignalWithNameSet");
168       g_dbus_message_set_sender (message, ":1.42");
169
170       error = NULL;
171       ret = g_dbus_connection_send_message (connection, message, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, &error);
172       g_assert_no_error (error);
173       g_assert (ret);
174       g_object_unref (message);
175
176       g_dbus_method_invocation_return_value (invocation, NULL);
177     }
178   else if (g_strcmp0 (method_name, "OpenFile") == 0 ||
179            g_strcmp0 (method_name, "OpenFileWithBigMessage") == 0)
180     {
181 #ifdef G_OS_UNIX
182       const gchar *path;
183       GDBusMessage *reply;
184       GError *error;
185       gint fd;
186       GUnixFDList *fd_list;
187
188       g_variant_get (parameters, "(&s)", &path);
189
190       fd_list = g_unix_fd_list_new ();
191
192       error = NULL;
193
194       fd = g_open (path, O_RDONLY, 0);
195       g_assert (fd != -1);
196       g_unix_fd_list_append (fd_list, fd, &error);
197       g_assert_no_error (error);
198       close (fd);
199
200       reply = g_dbus_message_new_method_reply (g_dbus_method_invocation_get_message (invocation));
201       g_dbus_message_set_unix_fd_list (reply, fd_list);
202       g_object_unref (fd_list);
203       g_object_unref (invocation);
204
205       if (g_strcmp0 (method_name, "OpenFileWithBigMessage") == 0)
206         {
207           char *junk;
208
209           junk = g_new0 (char, BIG_MESSAGE_ARRAY_SIZE);
210           g_dbus_message_set_body (reply,
211                                    g_variant_new ("(h@ay)",
212                                                   0,
213                                                   g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
214                                                                              junk,
215                                                                              BIG_MESSAGE_ARRAY_SIZE,
216                                                                              1)));
217           g_free (junk);
218         }
219
220       error = NULL;
221       g_dbus_connection_send_message (connection,
222                                       reply,
223                                       G_DBUS_SEND_MESSAGE_FLAGS_NONE,
224                                       NULL, /* out_serial */
225                                       &error);
226       g_assert_no_error (error);
227       g_object_unref (reply);
228 #else
229       g_dbus_method_invocation_return_dbus_error (invocation,
230                                                   "org.gtk.GDBus.NotOnUnix",
231                                                   "Your OS does not support file descriptor passing");
232 #endif
233     }
234   else
235     {
236       g_assert_not_reached ();
237     }
238 }
239
240 static GVariant *
241 test_interface_get_property (GDBusConnection  *connection,
242                              const gchar      *sender,
243                              const gchar      *object_path,
244                              const gchar      *interface_name,
245                              const gchar      *property_name,
246                              GError          **error,
247                              gpointer          user_data)
248 {
249   g_assert_cmpstr (object_path, ==, "/org/gtk/GDBus/PeerTestObject");
250   g_assert_cmpstr (interface_name, ==, "org.gtk.GDBus.PeerTestInterface");
251   g_assert_cmpstr (property_name, ==, "PeerProperty");
252
253   return g_variant_new_string ("ThePropertyValue");
254 }
255
256
257 static const GDBusInterfaceVTable test_interface_vtable =
258 {
259   test_interface_method_call,
260   test_interface_get_property,
261   NULL  /* set_property */
262 };
263
264 static void
265 on_proxy_signal_received (GDBusProxy *proxy,
266                           gchar      *sender_name,
267                           gchar      *signal_name,
268                           GVariant   *parameters,
269                           gpointer    user_data)
270 {
271   PeerData *data = user_data;
272
273   data->signal_received = TRUE;
274
275   g_assert (sender_name == NULL);
276   g_assert_cmpstr (signal_name, ==, "PeerSignal");
277   g_main_loop_quit (loop);
278 }
279
280 static void
281 on_proxy_signal_received_with_name_set (GDBusProxy *proxy,
282                                         gchar      *sender_name,
283                                         gchar      *signal_name,
284                                         GVariant   *parameters,
285                                         gpointer    user_data)
286 {
287   PeerData *data = user_data;
288
289   data->signal_received = TRUE;
290
291   g_assert_cmpstr (sender_name, ==, ":1.42");
292   g_assert_cmpstr (signal_name, ==, "PeerSignalWithNameSet");
293   g_main_loop_quit (loop);
294 }
295
296 /* ---------------------------------------------------------------------------------------------------- */
297
298 static void
299 setup_test_address (void)
300 {
301   if (is_unix)
302     {
303       g_test_message ("Testing with unix:dir address");
304       tmpdir = g_dir_make_tmp ("gdbus-test-XXXXXX", NULL);
305       tmp_address = g_strdup_printf ("unix:dir=%s", tmpdir);
306     }
307   else
308     tmp_address = g_strdup ("nonce-tcp:host=127.0.0.1");
309 }
310
311 #ifdef G_OS_UNIX
312 static void
313 setup_tmpdir_test_address (void)
314 {
315   g_test_message ("Testing with unix:tmpdir address");
316   tmpdir = g_dir_make_tmp ("gdbus-test-XXXXXX", NULL);
317   tmp_address = g_strdup_printf ("unix:tmpdir=%s", tmpdir);
318 }
319
320 static void
321 setup_path_test_address (void)
322 {
323   g_test_message ("Testing with unix:path address");
324   tmpdir = g_dir_make_tmp ("gdbus-test-XXXXXX", NULL);
325   tmp_address = g_strdup_printf ("unix:path=%s/gdbus-peer-socket", tmpdir);
326 }
327 #endif
328
329 static void
330 teardown_test_address (void)
331 {
332   g_free (tmp_address);
333   if (tmpdir)
334     {
335       /* Ensuring the rmdir succeeds also ensures any sockets created on the
336        * filesystem are also deleted.
337        */
338       g_assert_cmpstr (g_rmdir (tmpdir) == 0 ? "OK" : g_strerror (errno),
339                        ==, "OK");
340       g_clear_pointer (&tmpdir, g_free);
341     }
342 }
343
344 /* ---------------------------------------------------------------------------------------------------- */
345
346 static gboolean
347 on_authorize_authenticated_peer (GDBusAuthObserver *observer,
348                                  GIOStream         *stream,
349                                  GCredentials      *credentials,
350                                  gpointer           user_data)
351 {
352   PeerData *data = user_data;
353   gboolean authorized;
354
355   data->num_connection_attempts++;
356
357   authorized = TRUE;
358   if (!data->accept_connection)
359     {
360       authorized = FALSE;
361       g_main_loop_quit (loop);
362     }
363
364   return authorized;
365 }
366
367 /* Runs in thread we created GDBusServer in (since we didn't pass G_DBUS_SERVER_FLAGS_RUN_IN_THREAD) */
368 static gboolean
369 on_new_connection (GDBusServer *server,
370                    GDBusConnection *connection,
371                    gpointer user_data)
372 {
373   PeerData *data = user_data;
374   GError *error = NULL;
375   guint reg_id;
376
377   //g_printerr ("Client connected.\n"
378   //         "Negotiated capabilities: unix-fd-passing=%d\n",
379   //         g_dbus_connection_get_capabilities (connection) & G_DBUS_CAPABILITY_FLAGS_UNIX_FD_PASSING);
380
381   g_ptr_array_add (data->current_connections, g_object_ref (connection));
382
383 #if G_CREDENTIALS_SUPPORTED
384     {
385       GCredentials *credentials;
386
387       credentials = g_dbus_connection_get_peer_credentials (connection);
388
389       g_assert (credentials != NULL);
390       g_assert_cmpuint (g_credentials_get_unix_user (credentials, NULL), ==,
391                         getuid ());
392 #if G_CREDENTIALS_HAS_PID
393       g_assert_cmpint (g_credentials_get_unix_pid (credentials, &error), ==,
394                        getpid ());
395       g_assert_no_error (error);
396 #else
397       g_assert_cmpint (g_credentials_get_unix_pid (credentials, &error), ==, -1);
398       g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED);
399       g_clear_error (&error);
400 #endif
401     }
402 #endif
403
404   /* export object on the newly established connection */
405   reg_id = g_dbus_connection_register_object (connection,
406                                               "/org/gtk/GDBus/PeerTestObject",
407                                               test_interface_introspection_data,
408                                               &test_interface_vtable,
409                                               data,
410                                               NULL, /* GDestroyNotify for data */
411                                               &error);
412   g_assert_no_error (error);
413   g_assert (reg_id > 0);
414
415   g_main_loop_quit (loop);
416
417   return TRUE;
418 }
419
420 /* We don't tell the main thread about the new GDBusServer until it has
421  * had a chance to start listening. */
422 static gboolean
423 idle_in_service_loop (gpointer loop)
424 {
425   g_assert (service_loop == NULL);
426   g_mutex_lock (&service_loop_lock);
427   service_loop = loop;
428   g_cond_broadcast (&service_loop_cond);
429   g_mutex_unlock (&service_loop_lock);
430
431   return G_SOURCE_REMOVE;
432 }
433
434 static void
435 run_service_loop (GMainContext *service_context)
436 {
437   GMainLoop *loop;
438   GSource *source;
439
440   g_assert (service_loop == NULL);
441
442   loop = g_main_loop_new (service_context, FALSE);
443   source = g_idle_source_new ();
444   g_source_set_callback (source, idle_in_service_loop, loop, NULL);
445   g_source_attach (source, service_context);
446   g_source_unref (source);
447   g_main_loop_run (loop);
448 }
449
450 static void
451 teardown_service_loop (void)
452 {
453   g_mutex_lock (&service_loop_lock);
454   g_clear_pointer (&service_loop, g_main_loop_unref);
455   g_mutex_unlock (&service_loop_lock);
456 }
457
458 static void
459 await_service_loop (void)
460 {
461   g_mutex_lock (&service_loop_lock);
462   while (service_loop == NULL)
463     g_cond_wait (&service_loop_cond, &service_loop_lock);
464   g_mutex_unlock (&service_loop_lock);
465 }
466
467 static gpointer
468 service_thread_func (gpointer user_data)
469 {
470   PeerData *data = user_data;
471   GMainContext *service_context;
472   GDBusAuthObserver *observer, *o;
473   GError *error;
474   GDBusServerFlags f;
475   gchar *a, *g;
476   gboolean b;
477
478   service_context = g_main_context_new ();
479   g_main_context_push_thread_default (service_context);
480
481   error = NULL;
482   observer = g_dbus_auth_observer_new ();
483   server = g_dbus_server_new_sync (tmp_address,
484                                    G_DBUS_SERVER_FLAGS_NONE,
485                                    test_guid,
486                                    observer,
487                                    NULL, /* cancellable */
488                                    &error);
489   g_assert_no_error (error);
490
491   g_signal_connect (server,
492                     "new-connection",
493                     G_CALLBACK (on_new_connection),
494                     data);
495   g_signal_connect (observer,
496                     "authorize-authenticated-peer",
497                     G_CALLBACK (on_authorize_authenticated_peer),
498                     data);
499
500   g_assert_cmpint (g_dbus_server_get_flags (server), ==, G_DBUS_SERVER_FLAGS_NONE);
501   g_assert_cmpstr (g_dbus_server_get_guid (server), ==, test_guid);
502   g_object_get (server,
503                 "flags", &f,
504                 "address", &a,
505                 "guid", &g,
506                 "active", &b,
507                 "authentication-observer", &o,
508                 NULL);
509   g_assert_cmpint (f, ==, G_DBUS_SERVER_FLAGS_NONE);
510   g_assert_cmpstr (a, ==, tmp_address);
511   g_assert_cmpstr (g, ==, test_guid);
512   g_assert (!b);
513   g_assert (o == observer);
514   g_free (a);
515   g_free (g);
516   g_object_unref (o);
517
518   g_object_unref (observer);
519
520   g_dbus_server_start (server);
521
522   run_service_loop (service_context);
523
524   g_main_context_pop_thread_default (service_context);
525
526   teardown_service_loop ();
527   g_main_context_unref (service_context);
528
529   /* test code specifically unrefs the server - see below */
530   g_assert (server == NULL);
531
532   return NULL;
533 }
534
535 #if 0
536 static gboolean
537 on_incoming_connection (GSocketService     *service,
538                         GSocketConnection  *socket_connection,
539                         GObject            *source_object,
540                         gpointer           user_data)
541 {
542   PeerData *data = user_data;
543
544   if (data->accept_connection)
545     {
546       GError *error;
547       guint reg_id;
548       GDBusConnection *connection;
549
550       error = NULL;
551       connection = g_dbus_connection_new_sync (G_IO_STREAM (socket_connection),
552                                                test_guid,
553                                                G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER,
554                                                NULL, /* cancellable */
555                                                &error);
556       g_assert_no_error (error);
557
558       g_ptr_array_add (data->current_connections, connection);
559
560       /* export object on the newly established connection */
561       error = NULL;
562       reg_id = g_dbus_connection_register_object (connection,
563                                                   "/org/gtk/GDBus/PeerTestObject",
564                                                   &test_interface_introspection_data,
565                                                   &test_interface_vtable,
566                                                   data,
567                                                   NULL, /* GDestroyNotify for data */
568                                                   &error);
569       g_assert_no_error (error);
570       g_assert (reg_id > 0);
571
572     }
573   else
574     {
575       /* don't do anything */
576     }
577
578   data->num_connection_attempts++;
579
580   g_main_loop_quit (loop);
581
582   /* stops other signal handlers from being invoked */
583   return TRUE;
584 }
585
586 static gpointer
587 service_thread_func (gpointer data)
588 {
589   GMainContext *service_context;
590   gchar *socket_path;
591   GSocketAddress *address;
592   GError *error;
593
594   service_context = g_main_context_new ();
595   g_main_context_push_thread_default (service_context);
596
597   socket_path = g_strdup_printf ("/tmp/gdbus-test-pid-%d", getpid ());
598   address = g_unix_socket_address_new (socket_path);
599
600   service = g_socket_service_new ();
601   error = NULL;
602   g_socket_listener_add_address (G_SOCKET_LISTENER (service),
603                                  address,
604                                  G_SOCKET_TYPE_STREAM,
605                                  G_SOCKET_PROTOCOL_DEFAULT,
606                                  NULL, /* source_object */
607                                  NULL, /* effective_address */
608                                  &error);
609   g_assert_no_error (error);
610   g_signal_connect (service,
611                     "incoming",
612                     G_CALLBACK (on_incoming_connection),
613                     data);
614   g_socket_service_start (service);
615
616   run_service_loop (service_context);
617
618   g_main_context_pop_thread_default (service_context);
619
620   teardown_service_loop ();
621   g_main_context_unref (service_context);
622
623   g_object_unref (address);
624   g_free (socket_path);
625   return NULL;
626 }
627 #endif
628
629 /* ---------------------------------------------------------------------------------------------------- */
630
631 #if 0
632 static gboolean
633 check_connection (gpointer user_data)
634 {
635   PeerData *data = user_data;
636   guint n;
637
638   for (n = 0; n < data->current_connections->len; n++)
639     {
640       GDBusConnection *c;
641       GIOStream *stream;
642
643       c = G_DBUS_CONNECTION (data->current_connections->pdata[n]);
644       stream = g_dbus_connection_get_stream (c);
645
646       g_debug ("In check_connection for %d: connection %p, stream %p", n, c, stream);
647       g_debug ("closed = %d", g_io_stream_is_closed (stream));
648
649       GSocket *socket;
650       socket = g_socket_connection_get_socket (G_SOCKET_CONNECTION (stream));
651       g_debug ("socket_closed = %d", g_socket_is_closed (socket));
652       g_debug ("socket_condition_check = %d", g_socket_condition_check (socket, G_IO_IN|G_IO_OUT|G_IO_ERR|G_IO_HUP));
653
654       gchar buf[128];
655       GError *error;
656       gssize num_read;
657       error = NULL;
658       num_read = g_input_stream_read (g_io_stream_get_input_stream (stream),
659                                       buf,
660                                       128,
661                                       NULL,
662                                       &error);
663       if (num_read < 0)
664         {
665           g_debug ("error: %s", error->message);
666           g_error_free (error);
667         }
668       else
669         {
670           g_debug ("no error, read %d bytes", (gint) num_read);
671         }
672     }
673
674   return G_SOURCE_REMOVE;
675 }
676
677 static gboolean
678 on_do_disconnect_in_idle (gpointer data)
679 {
680   GDBusConnection *c = G_DBUS_CONNECTION (data);
681   g_debug ("GDC %p has ref_count %d", c, G_OBJECT (c)->ref_count);
682   g_dbus_connection_disconnect (c);
683   g_object_unref (c);
684   return G_SOURCE_REMOVE;
685 }
686 #endif
687
688 #ifdef G_OS_UNIX
689 static gchar *
690 read_all_from_fd (gint fd, gsize *out_len, GError **error)
691 {
692   GString *str;
693   gchar buf[64];
694   gssize num_read;
695
696   str = g_string_new (NULL);
697
698   do
699     {
700       int errsv;
701
702       num_read = read (fd, buf, sizeof (buf));
703       errsv = errno;
704       if (num_read == -1)
705         {
706           if (errsv == EAGAIN || errsv == EWOULDBLOCK)
707             continue;
708           g_set_error (error,
709                        G_IO_ERROR,
710                        g_io_error_from_errno (errsv),
711                        "Failed reading %d bytes into offset %d: %s",
712                        (gint) sizeof (buf),
713                        (gint) str->len,
714                        g_strerror (errsv));
715           goto error;
716         }
717       else if (num_read > 0)
718         {
719           g_string_append_len (str, buf, num_read);
720         }
721       else if (num_read == 0)
722         {
723           break;
724         }
725     }
726   while (TRUE);
727
728   if (out_len != NULL)
729     *out_len = str->len;
730   return g_string_free (str, FALSE);
731
732  error:
733   if (out_len != NULL)
734     *out_len = 0;
735   g_string_free (str, TRUE);
736   return NULL;
737 }
738 #endif
739
740 static void
741 do_test_peer (void)
742 {
743   GDBusConnection *c;
744   GDBusConnection *c2;
745   GDBusProxy *proxy;
746   GError *error;
747   PeerData data;
748   GVariant *value;
749   GVariant *result;
750   const gchar *s;
751   GThread *service_thread;
752   gulong signal_handler_id;
753   gsize i;
754
755   memset (&data, '\0', sizeof (PeerData));
756   data.current_connections = g_ptr_array_new_with_free_func (g_object_unref);
757
758   /* first try to connect when there is no server */
759   error = NULL;
760   c = g_dbus_connection_new_for_address_sync (is_unix ? "unix:path=/tmp/gdbus-test-does-not-exist-pid" :
761                                               /* NOTE: Even if something is listening on port 12345 the connection
762                                                * will fail because the nonce file doesn't exist */
763                                               "nonce-tcp:host=127.0.0.1,port=12345,noncefile=this-does-not-exist-gdbus",
764                                               G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
765                                               NULL, /* GDBusAuthObserver */
766                                               NULL, /* cancellable */
767                                               &error);
768   _g_assert_error_domain (error, G_IO_ERROR);
769   g_assert (!g_dbus_error_is_remote_error (error));
770   g_clear_error (&error);
771   g_assert (c == NULL);
772
773   /* bring up a server - we run the server in a different thread to avoid deadlocks */
774   service_thread = g_thread_new ("test_peer",
775                                  service_thread_func,
776                                  &data);
777   await_service_loop ();
778   g_assert (server != NULL);
779
780   /* bring up a connection and accept it */
781   data.accept_connection = TRUE;
782   error = NULL;
783   c = g_dbus_connection_new_for_address_sync (g_dbus_server_get_client_address (server),
784                                               G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
785                                               NULL, /* GDBusAuthObserver */
786                                               NULL, /* cancellable */
787                                               &error);
788   g_assert_no_error (error);
789   g_assert (c != NULL);
790   while (data.current_connections->len < 1)
791     g_main_loop_run (loop);
792   g_assert_cmpint (data.current_connections->len, ==, 1);
793   g_assert_cmpint (data.num_connection_attempts, ==, 1);
794   g_assert (g_dbus_connection_get_unique_name (c) == NULL);
795   g_assert_cmpstr (g_dbus_connection_get_guid (c), ==, test_guid);
796
797   /* check that we create a proxy, read properties, receive signals and invoke
798    * the HelloPeer() method. Since the server runs in another thread it's fine
799    * to use synchronous blocking API here.
800    */
801   error = NULL;
802   proxy = g_dbus_proxy_new_sync (c,
803                                  G_DBUS_PROXY_FLAGS_NONE,
804                                  NULL,
805                                  NULL, /* bus_name */
806                                  "/org/gtk/GDBus/PeerTestObject",
807                                  "org.gtk.GDBus.PeerTestInterface",
808                                  NULL, /* GCancellable */
809                                  &error);
810   g_assert_no_error (error);
811   g_assert (proxy != NULL);
812   error = NULL;
813   value = g_dbus_proxy_get_cached_property (proxy, "PeerProperty");
814   g_assert_cmpstr (g_variant_get_string (value, NULL), ==, "ThePropertyValue");
815
816   /* try invoking a method */
817   error = NULL;
818   result = g_dbus_proxy_call_sync (proxy,
819                                    "HelloPeer",
820                                    g_variant_new ("(s)", "Hey Peer!"),
821                                    G_DBUS_CALL_FLAGS_NONE,
822                                    -1,
823                                    NULL,  /* GCancellable */
824                                    &error);
825   g_assert_no_error (error);
826   g_variant_get (result, "(&s)", &s);
827   g_assert_cmpstr (s, ==, "You greeted me with 'Hey Peer!'.");
828   g_variant_unref (result);
829   g_assert_cmpint (data.num_method_calls, ==, 1);
830
831   /* make the other peer emit a signal - catch it */
832   signal_handler_id = g_signal_connect (proxy,
833                                         "g-signal",
834                                         G_CALLBACK (on_proxy_signal_received),
835                                         &data);
836   g_assert (!data.signal_received);
837   g_dbus_proxy_call (proxy,
838                      "EmitSignal",
839                      NULL,  /* no arguments */
840                      G_DBUS_CALL_FLAGS_NONE,
841                      -1,
842                      NULL,  /* GCancellable */
843                      NULL,  /* GAsyncReadyCallback - we don't care about the result */
844                      NULL); /* user_data */
845   g_main_loop_run (loop);
846   g_assert (data.signal_received);
847   g_assert_cmpint (data.num_method_calls, ==, 2);
848   g_signal_handler_disconnect (proxy, signal_handler_id);
849
850   /* Also ensure that messages with the sender header-field set gets
851    * delivered to the proxy - note that this doesn't really make sense
852    * e.g. names are meaning-less in a peer-to-peer case... but we
853    * support it because it makes sense in certain bridging
854    * applications - see e.g. #623815.
855    */
856   signal_handler_id = g_signal_connect (proxy,
857                                         "g-signal",
858                                         G_CALLBACK (on_proxy_signal_received_with_name_set),
859                                         &data);
860   data.signal_received = FALSE;
861   g_dbus_proxy_call (proxy,
862                      "EmitSignalWithNameSet",
863                      NULL,  /* no arguments */
864                      G_DBUS_CALL_FLAGS_NONE,
865                      -1,
866                      NULL,  /* GCancellable */
867                      NULL,  /* GAsyncReadyCallback - we don't care about the result */
868                      NULL); /* user_data */
869   g_main_loop_run (loop);
870   g_assert (data.signal_received);
871   g_assert_cmpint (data.num_method_calls, ==, 3);
872   g_signal_handler_disconnect (proxy, signal_handler_id);
873
874   /*
875    * Check for UNIX fd passing.
876    *
877    * The first time through, we use a very simple method call. Note that
878    * because this does not have a G_VARIANT_TYPE_HANDLE in the message body
879    * to refer to the fd, it is a GDBus-specific idiom that would not
880    * interoperate with libdbus or sd-bus
881    * (see <https://gitlab.gnome.org/GNOME/glib/-/merge_requests/1726>).
882    *
883    * The second time, we call a method that returns a fd attached to a
884    * large message, to reproduce
885    * <https://gitlab.gnome.org/GNOME/glib/-/issues/2074>. It also happens
886    * to follow the more usual pattern for D-Bus messages containing a
887    * G_VARIANT_TYPE_HANDLE to refer to attached fds.
888    */
889   for (i = 0; i < 2; i++)
890     {
891 #ifdef G_OS_UNIX
892       GDBusMessage *method_call_message;
893       GDBusMessage *method_reply_message;
894       GUnixFDList *fd_list;
895       gint fd;
896       gchar *buf;
897       gsize len;
898       gchar *buf2;
899       gsize len2;
900       const char *testfile = g_test_get_filename (G_TEST_DIST, "file.c", NULL);
901       const char *method = "OpenFile";
902       GVariant *body;
903
904       if (i == 1)
905         method = "OpenFileWithBigMessage";
906
907       method_call_message = g_dbus_message_new_method_call (NULL, /* name */
908                                                             "/org/gtk/GDBus/PeerTestObject",
909                                                             "org.gtk.GDBus.PeerTestInterface",
910                                                             method);
911       g_dbus_message_set_body (method_call_message, g_variant_new ("(s)", testfile));
912       error = NULL;
913       method_reply_message = g_dbus_connection_send_message_with_reply_sync (c,
914                                                                              method_call_message,
915                                                                              G_DBUS_SEND_MESSAGE_FLAGS_NONE,
916                                                                              -1,
917                                                                              NULL, /* out_serial */
918                                                                              NULL, /* cancellable */
919                                                                              &error);
920       g_assert_no_error (error);
921       g_assert (g_dbus_message_get_message_type (method_reply_message) == G_DBUS_MESSAGE_TYPE_METHOD_RETURN);
922
923       body = g_dbus_message_get_body (method_reply_message);
924
925       if (i == 1)
926         {
927           gint32 handle = -1;
928           GVariant *junk = NULL;
929
930           g_assert_cmpstr (g_variant_get_type_string (body), ==, "(hay)");
931           g_variant_get (body, "(h@ay)", &handle, &junk);
932           g_assert_cmpint (handle, ==, 0);
933           g_assert_cmpuint (g_variant_n_children (junk), ==, BIG_MESSAGE_ARRAY_SIZE);
934           g_variant_unref (junk);
935         }
936       else
937         {
938           g_assert_null (body);
939         }
940
941       fd_list = g_dbus_message_get_unix_fd_list (method_reply_message);
942       g_assert (fd_list != NULL);
943       g_assert_cmpint (g_unix_fd_list_get_length (fd_list), ==, 1);
944       error = NULL;
945       fd = g_unix_fd_list_get (fd_list, 0, &error);
946       g_assert_no_error (error);
947       g_object_unref (method_call_message);
948       g_object_unref (method_reply_message);
949
950       error = NULL;
951       len = 0;
952       buf = read_all_from_fd (fd, &len, &error);
953       g_assert_no_error (error);
954       g_assert (buf != NULL);
955       close (fd);
956
957       error = NULL;
958       g_file_get_contents (testfile,
959                            &buf2,
960                            &len2,
961                            &error);
962       g_assert_no_error (error);
963       g_assert_cmpmem (buf, len, buf2, len2);
964       g_free (buf2);
965       g_free (buf);
966 #else
967       /* We do the same number of iterations on non-Unix, so that
968        * the method call count will match. In this case we use
969        * OpenFile both times, because the difference between this
970        * and OpenFileWithBigMessage is only relevant on Unix. */
971       error = NULL;
972       result = g_dbus_proxy_call_sync (proxy,
973                                        "OpenFile",
974                                        g_variant_new ("(s)", "boo"),
975                                        G_DBUS_CALL_FLAGS_NONE,
976                                        -1,
977                                        NULL,  /* GCancellable */
978                                        &error);
979       g_assert_error (error, G_IO_ERROR, G_IO_ERROR_DBUS_ERROR);
980       g_assert (result == NULL);
981       g_error_free (error);
982 #endif /* G_OS_UNIX */
983     }
984
985   /* Check that g_socket_get_credentials() work - (though this really
986    * should be in socket.c)
987    */
988   {
989     GSocket *socket;
990     GCredentials *credentials;
991     socket = g_socket_connection_get_socket (G_SOCKET_CONNECTION (g_dbus_connection_get_stream (c)));
992     g_assert (G_IS_SOCKET (socket));
993     error = NULL;
994     credentials = g_socket_get_credentials (socket, &error);
995
996 #if G_CREDENTIALS_SOCKET_GET_CREDENTIALS_SUPPORTED
997     g_assert_no_error (error);
998     g_assert (G_IS_CREDENTIALS (credentials));
999
1000     g_assert_cmpuint (g_credentials_get_unix_user (credentials, NULL), ==,
1001                       getuid ());
1002 #if G_CREDENTIALS_HAS_PID
1003     g_assert_cmpint (g_credentials_get_unix_pid (credentials, &error), ==,
1004                      getpid ());
1005     g_assert_no_error (error);
1006 #else
1007     g_assert_cmpint (g_credentials_get_unix_pid (credentials, &error), ==, -1);
1008     g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED);
1009     g_clear_error (&error);
1010 #endif
1011     g_object_unref (credentials);
1012 #else
1013     g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED);
1014     g_assert (credentials == NULL);
1015 #endif
1016   }
1017
1018
1019   /* bring up a connection - don't accept it - this should fail
1020    */
1021   data.accept_connection = FALSE;
1022   error = NULL;
1023   c2 = g_dbus_connection_new_for_address_sync (g_dbus_server_get_client_address (server),
1024                                                G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
1025                                                NULL, /* GDBusAuthObserver */
1026                                                NULL, /* cancellable */
1027                                                &error);
1028   _g_assert_error_domain (error, G_IO_ERROR);
1029   g_error_free (error);
1030   g_assert (c2 == NULL);
1031
1032 #if 0
1033   /* TODO: THIS TEST DOESN'T WORK YET */
1034
1035   /* bring up a connection - accept it.. then disconnect from the client side - check
1036    * that the server side gets the disconnect signal.
1037    */
1038   error = NULL;
1039   data.accept_connection = TRUE;
1040   c2 = g_dbus_connection_new_for_address_sync (g_dbus_server_get_client_address (server),
1041                                                G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
1042                                                NULL, /* GDBusAuthObserver */
1043                                                NULL, /* cancellable */
1044                                                &error);
1045   g_assert_no_error (error);
1046   g_assert (c2 != NULL);
1047   g_assert (!g_dbus_connection_get_is_disconnected (c2));
1048   while (data.num_connection_attempts < 3)
1049     g_main_loop_run (loop);
1050   g_assert_cmpint (data.current_connections->len, ==, 2);
1051   g_assert_cmpint (data.num_connection_attempts, ==, 3);
1052   g_assert (!g_dbus_connection_get_is_disconnected (G_DBUS_CONNECTION (data.current_connections->pdata[1])));
1053   g_idle_add (on_do_disconnect_in_idle, c2);
1054   g_debug ("==================================================");
1055   g_debug ("==================================================");
1056   g_debug ("==================================================");
1057   g_debug ("waiting for disconnect on connection %p, stream %p",
1058            data.current_connections->pdata[1],
1059            g_dbus_connection_get_stream (data.current_connections->pdata[1]));
1060
1061   g_timeout_add (2000, check_connection, &data);
1062   //_g_assert_signal_received (G_DBUS_CONNECTION (data.current_connections->pdata[1]), "closed");
1063   g_main_loop_run (loop);
1064   g_assert (g_dbus_connection_get_is_disconnected (G_DBUS_CONNECTION (data.current_connections->pdata[1])));
1065   g_ptr_array_set_size (data.current_connections, 1); /* remove disconnected connection object */
1066 #endif
1067
1068   /* unref the server and stop listening for new connections
1069    *
1070    * This won't bring down the established connections - check that c is still connected
1071    * by invoking a method
1072    */
1073   //g_socket_service_stop (service);
1074   //g_object_unref (service);
1075   g_dbus_server_stop (server);
1076   g_object_unref (server);
1077   server = NULL;
1078
1079   error = NULL;
1080   result = g_dbus_proxy_call_sync (proxy,
1081                                    "HelloPeer",
1082                                    g_variant_new ("(s)", "Hey Again Peer!"),
1083                                    G_DBUS_CALL_FLAGS_NONE,
1084                                    -1,
1085                                    NULL,  /* GCancellable */
1086                                    &error);
1087   g_assert_no_error (error);
1088   g_variant_get (result, "(&s)", &s);
1089   g_assert_cmpstr (s, ==, "You greeted me with 'Hey Again Peer!'.");
1090   g_variant_unref (result);
1091   g_assert_cmpint (data.num_method_calls, ==, 6);
1092
1093 #if 0
1094   /* TODO: THIS TEST DOESN'T WORK YET */
1095
1096   /* now disconnect from the server side - check that the client side gets the signal */
1097   g_assert_cmpint (data.current_connections->len, ==, 1);
1098   g_assert (G_DBUS_CONNECTION (data.current_connections->pdata[0]) != c);
1099   g_dbus_connection_disconnect (G_DBUS_CONNECTION (data.current_connections->pdata[0]));
1100   if (!g_dbus_connection_get_is_disconnected (c))
1101     _g_assert_signal_received (c, "closed");
1102   g_assert (g_dbus_connection_get_is_disconnected (c));
1103 #endif
1104
1105   g_object_unref (c);
1106   g_ptr_array_unref (data.current_connections);
1107   g_object_unref (proxy);
1108
1109   g_main_loop_quit (service_loop);
1110   g_thread_join (service_thread);
1111 }
1112
1113 static void
1114 test_peer (void)
1115 {
1116   test_guid = g_dbus_generate_guid ();
1117   loop = g_main_loop_new (NULL, FALSE);
1118
1119   /* Run this test multiple times using different address formats to ensure
1120    * they all work.
1121    */
1122   setup_test_address ();
1123   do_test_peer ();
1124   teardown_test_address ();
1125
1126 #ifdef G_OS_UNIX
1127   setup_tmpdir_test_address ();
1128   do_test_peer ();
1129   teardown_test_address ();
1130
1131   setup_path_test_address ();
1132   do_test_peer ();
1133   teardown_test_address ();
1134 #endif
1135
1136   g_main_loop_unref (loop);
1137   g_free (test_guid);
1138 }
1139
1140 /* ---------------------------------------------------------------------------------------------------- */
1141
1142 #define VALID_GUID "0123456789abcdef0123456789abcdef"
1143
1144 static void
1145 test_peer_invalid_server (void)
1146 {
1147   GDBusServer *server;
1148
1149   if (!g_test_undefined ())
1150     {
1151       g_test_skip ("Not exercising programming errors");
1152       return;
1153     }
1154
1155   if (g_test_subprocess ())
1156     {
1157       /* This assumes we are not going to run out of GDBusServerFlags
1158        * any time soon */
1159       server = g_dbus_server_new_sync ("tcp:", (GDBusServerFlags) (1 << 30),
1160                                        VALID_GUID,
1161                                        NULL, NULL, NULL);
1162       g_assert_null (server);
1163     }
1164   else
1165     {
1166       g_test_trap_subprocess (NULL, 0, 0);
1167       g_test_trap_assert_failed ();
1168       g_test_trap_assert_stderr ("*CRITICAL*G_DBUS_SERVER_FLAGS_ALL*");
1169     }
1170 }
1171
1172 static void
1173 test_peer_invalid_conn_stream_sync (void)
1174 {
1175   GSocket *sock;
1176   GSocketConnection *socket_conn;
1177   GIOStream *iostream;
1178   GDBusConnection *conn;
1179
1180   if (!g_test_undefined ())
1181     {
1182       g_test_skip ("Not exercising programming errors");
1183       return;
1184     }
1185
1186   sock = g_socket_new (G_SOCKET_FAMILY_IPV4,
1187                        G_SOCKET_TYPE_STREAM,
1188                        G_SOCKET_PROTOCOL_TCP,
1189                        NULL);
1190
1191   if (sock == NULL)
1192     {
1193       g_test_skip ("TCP not available?");
1194       return;
1195     }
1196
1197   socket_conn = g_socket_connection_factory_create_connection (sock);
1198   g_assert_nonnull (socket_conn);
1199   iostream = G_IO_STREAM (socket_conn);
1200   g_assert_nonnull (iostream);
1201
1202   if (g_test_subprocess ())
1203     {
1204       /* This assumes we are not going to run out of GDBusConnectionFlags
1205        * any time soon */
1206       conn = g_dbus_connection_new_sync (iostream, VALID_GUID,
1207                                          (GDBusConnectionFlags) (1 << 30),
1208                                          NULL, NULL, NULL);
1209       g_assert_null (conn);
1210     }
1211   else
1212     {
1213       g_test_trap_subprocess (NULL, 0, 0);
1214       g_test_trap_assert_failed ();
1215       g_test_trap_assert_stderr ("*CRITICAL*G_DBUS_CONNECTION_FLAGS_ALL*");
1216     }
1217
1218   g_clear_object (&sock);
1219   g_clear_object (&socket_conn);
1220 }
1221
1222 static void
1223 test_peer_invalid_conn_stream_async (void)
1224 {
1225   GSocket *sock;
1226   GSocketConnection *socket_conn;
1227   GIOStream *iostream;
1228
1229   if (!g_test_undefined ())
1230     {
1231       g_test_skip ("Not exercising programming errors");
1232       return;
1233     }
1234
1235   sock = g_socket_new (G_SOCKET_FAMILY_IPV4,
1236                        G_SOCKET_TYPE_STREAM,
1237                        G_SOCKET_PROTOCOL_TCP,
1238                        NULL);
1239
1240   if (sock == NULL)
1241     {
1242       g_test_skip ("TCP not available?");
1243       return;
1244     }
1245
1246   socket_conn = g_socket_connection_factory_create_connection (sock);
1247   g_assert_nonnull (socket_conn);
1248   iostream = G_IO_STREAM (socket_conn);
1249   g_assert_nonnull (iostream);
1250
1251   if (g_test_subprocess ())
1252     {
1253       g_dbus_connection_new (iostream, VALID_GUID,
1254                              (GDBusConnectionFlags) (1 << 30),
1255                              NULL, NULL, NULL, NULL);
1256     }
1257   else
1258     {
1259       g_test_trap_subprocess (NULL, 0, 0);
1260       g_test_trap_assert_failed ();
1261       g_test_trap_assert_stderr ("*CRITICAL*G_DBUS_CONNECTION_FLAGS_ALL*");
1262     }
1263
1264   g_clear_object (&sock);
1265   g_clear_object (&socket_conn);
1266 }
1267
1268 static void
1269 test_peer_invalid_conn_addr_sync (void)
1270 {
1271   GDBusConnection *conn;
1272
1273   if (!g_test_undefined ())
1274     {
1275       g_test_skip ("Not exercising programming errors");
1276       return;
1277     }
1278
1279   if (g_test_subprocess ())
1280     {
1281       conn = g_dbus_connection_new_for_address_sync ("tcp:",
1282                                                      (GDBusConnectionFlags) (1 << 30),
1283                                                      NULL, NULL, NULL);
1284       g_assert_null (conn);
1285     }
1286   else
1287     {
1288       g_test_trap_subprocess (NULL, 0, 0);
1289       g_test_trap_assert_failed ();
1290       g_test_trap_assert_stderr ("*CRITICAL*G_DBUS_CONNECTION_FLAGS_ALL*");
1291     }
1292 }
1293
1294 static void
1295 test_peer_invalid_conn_addr_async (void)
1296 {
1297   if (!g_test_undefined ())
1298     {
1299       g_test_skip ("Not exercising programming errors");
1300       return;
1301     }
1302
1303   if (g_test_subprocess ())
1304     {
1305       g_dbus_connection_new_for_address ("tcp:",
1306                                          (GDBusConnectionFlags) (1 << 30),
1307                                          NULL, NULL, NULL, NULL);
1308     }
1309   else
1310     {
1311       g_test_trap_subprocess (NULL, 0, 0);
1312       g_test_trap_assert_failed ();
1313       g_test_trap_assert_stderr ("*CRITICAL*G_DBUS_CONNECTION_FLAGS_ALL*");
1314     }
1315 }
1316
1317 /* ---------------------------------------------------------------------------------------------------- */
1318
1319 static void
1320 test_peer_signals (void)
1321 {
1322   GDBusConnection *c;
1323   GDBusProxy *proxy;
1324   GError *error = NULL;
1325   PeerData data;
1326   GThread *service_thread;
1327
1328   g_test_bug ("https://gitlab.gnome.org/GNOME/glib/issues/1620");
1329
1330   test_guid = g_dbus_generate_guid ();
1331   loop = g_main_loop_new (NULL, FALSE);
1332
1333   setup_test_address ();
1334   memset (&data, '\0', sizeof (PeerData));
1335   data.current_connections = g_ptr_array_new_with_free_func (g_object_unref);
1336
1337   /* bring up a server - we run the server in a different thread to avoid deadlocks */
1338   service_thread = g_thread_new ("test_peer",
1339                                  service_thread_func,
1340                                  &data);
1341   await_service_loop ();
1342   g_assert_nonnull (server);
1343
1344   /* bring up a connection and accept it */
1345   data.accept_connection = TRUE;
1346   c = g_dbus_connection_new_for_address_sync (g_dbus_server_get_client_address (server),
1347                                               G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
1348                                               NULL, /* GDBusAuthObserver */
1349                                               NULL, /* cancellable */
1350                                               &error);
1351   g_assert_no_error (error);
1352   g_assert_nonnull (c);
1353   while (data.current_connections->len < 1)
1354     g_main_loop_run (loop);
1355   g_assert_cmpint (data.current_connections->len, ==, 1);
1356   g_assert_cmpint (data.num_connection_attempts, ==, 1);
1357   g_assert_null (g_dbus_connection_get_unique_name (c));
1358   g_assert_cmpstr (g_dbus_connection_get_guid (c), ==, test_guid);
1359
1360   /* Check that we can create a proxy with a non-NULL bus name, even though it's
1361    * irrelevant in the non-message-bus case. Since the server runs in another
1362    * thread it's fine to use synchronous blocking API here.
1363    */
1364   proxy = g_dbus_proxy_new_sync (c,
1365                                  G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
1366                                  G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
1367                                  NULL,
1368                                  ":1.1", /* bus_name */
1369                                  "/org/gtk/GDBus/PeerTestObject",
1370                                  "org.gtk.GDBus.PeerTestInterface",
1371                                  NULL, /* GCancellable */
1372                                  &error);
1373   g_assert_no_error (error);
1374   g_assert_nonnull (proxy);
1375
1376   /* unref the server and stop listening for new connections */
1377   g_dbus_server_stop (server);
1378   g_clear_object (&server);
1379
1380   g_object_unref (c);
1381   g_ptr_array_unref (data.current_connections);
1382   g_object_unref (proxy);
1383
1384   g_main_loop_quit (service_loop);
1385   g_thread_join (service_thread);
1386
1387   teardown_test_address ();
1388
1389   g_main_loop_unref (loop);
1390   g_free (test_guid);
1391 }
1392
1393 /* ---------------------------------------------------------------------------------------------------- */
1394
1395 typedef struct
1396 {
1397   GDBusServer *server;
1398   GMainContext *context;
1399   GMainLoop *loop;
1400
1401   GList *connections;
1402 } DmpData;
1403
1404 static void
1405 dmp_data_free (DmpData *data)
1406 {
1407   g_main_loop_unref (data->loop);
1408   g_main_context_unref (data->context);
1409   g_object_unref (data->server);
1410   g_list_free_full (data->connections, g_object_unref);
1411   g_free (data);
1412 }
1413
1414 static void
1415 dmp_on_method_call (GDBusConnection       *connection,
1416                     const gchar           *sender,
1417                     const gchar           *object_path,
1418                     const gchar           *interface_name,
1419                     const gchar           *method_name,
1420                     GVariant              *parameters,
1421                     GDBusMethodInvocation *invocation,
1422                     gpointer               user_data)
1423 {
1424   //DmpData *data = user_data;
1425   gint32 first;
1426   gint32 second;
1427   g_variant_get (parameters,
1428                  "(ii)",
1429                  &first,
1430                  &second);
1431   g_dbus_method_invocation_return_value (invocation,
1432                                          g_variant_new ("(i)", first + second));
1433 }
1434
1435 static const GDBusInterfaceVTable dmp_interface_vtable =
1436 {
1437   dmp_on_method_call,
1438   NULL,  /* get_property */
1439   NULL   /* set_property */
1440 };
1441
1442
1443 /* Runs in thread we created GDBusServer in (since we didn't pass G_DBUS_SERVER_FLAGS_RUN_IN_THREAD) */
1444 static gboolean
1445 dmp_on_new_connection (GDBusServer     *server,
1446                        GDBusConnection *connection,
1447                        gpointer         user_data)
1448 {
1449   DmpData *data = user_data;
1450   GDBusNodeInfo *node;
1451   GError *error;
1452
1453   /* accept the connection */
1454   data->connections = g_list_prepend (data->connections, g_object_ref (connection));
1455
1456   error = NULL;
1457   node = g_dbus_node_info_new_for_xml ("<node>"
1458                                        "  <interface name='org.gtk.GDBus.DmpInterface'>"
1459                                        "    <method name='AddPair'>"
1460                                        "      <arg type='i' name='first' direction='in'/>"
1461                                        "      <arg type='i' name='second' direction='in'/>"
1462                                        "      <arg type='i' name='sum' direction='out'/>"
1463                                        "    </method>"
1464                                        "  </interface>"
1465                                        "</node>",
1466                                        &error);
1467   g_assert_no_error (error);
1468
1469   /* sleep 100ms before exporting an object - this is to test that
1470    * G_DBUS_CONNECTION_FLAGS_DELAY_MESSAGE_PROCESSING really works
1471    * (GDBusServer uses this feature).
1472    */
1473   usleep (100 * 1000);
1474
1475   /* export an object */
1476   error = NULL;
1477   g_dbus_connection_register_object (connection,
1478                                      "/dmp/test",
1479                                      node->interfaces[0],
1480                                      &dmp_interface_vtable,
1481                                      data,
1482                                      NULL,
1483                                      &error);
1484   g_dbus_node_info_unref (node);
1485
1486   return TRUE;
1487 }
1488
1489 static gpointer
1490 dmp_thread_func (gpointer user_data)
1491 {
1492   DmpData *data = user_data;
1493   GError *error;
1494   gchar *guid;
1495
1496   data->context = g_main_context_new ();
1497   g_main_context_push_thread_default (data->context);
1498
1499   error = NULL;
1500   guid = g_dbus_generate_guid ();
1501   data->server = g_dbus_server_new_sync (tmp_address,
1502                                          G_DBUS_SERVER_FLAGS_NONE,
1503                                          guid,
1504                                          NULL, /* GDBusAuthObserver */
1505                                          NULL, /* GCancellable */
1506                                          &error);
1507   g_assert_no_error (error);
1508   g_signal_connect (data->server,
1509                     "new-connection",
1510                     G_CALLBACK (dmp_on_new_connection),
1511                     data);
1512
1513   g_dbus_server_start (data->server);
1514
1515   data->loop = g_main_loop_new (data->context, FALSE);
1516   g_main_loop_run (data->loop);
1517
1518   g_dbus_server_stop (data->server);
1519   g_main_context_pop_thread_default (data->context);
1520
1521   g_free (guid);
1522   return NULL;
1523 }
1524
1525 static void
1526 delayed_message_processing (void)
1527 {
1528   GError *error;
1529   DmpData *data;
1530   GThread *service_thread;
1531   guint n;
1532
1533   test_guid = g_dbus_generate_guid ();
1534   loop = g_main_loop_new (NULL, FALSE);
1535
1536   setup_test_address ();
1537
1538   data = g_new0 (DmpData, 1);
1539
1540   service_thread = g_thread_new ("dmp",
1541                                  dmp_thread_func,
1542                                  data);
1543   while (data->server == NULL || !g_dbus_server_is_active (data->server))
1544     g_thread_yield ();
1545
1546   for (n = 0; n < 5; n++)
1547     {
1548       GDBusConnection *c;
1549       GVariant *res;
1550       gint32 val;
1551
1552       error = NULL;
1553       c = g_dbus_connection_new_for_address_sync (g_dbus_server_get_client_address (data->server),
1554                                                   G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
1555                                                   NULL, /* GDBusAuthObserver */
1556                                                   NULL, /* GCancellable */
1557                                                   &error);
1558       g_assert_no_error (error);
1559
1560       error = NULL;
1561       res = g_dbus_connection_call_sync (c,
1562                                          NULL,    /* bus name */
1563                                          "/dmp/test",
1564                                          "org.gtk.GDBus.DmpInterface",
1565                                          "AddPair",
1566                                          g_variant_new ("(ii)", 2, n),
1567                                          G_VARIANT_TYPE ("(i)"),
1568                                          G_DBUS_CALL_FLAGS_NONE,
1569                                          -1, /* timeout_msec */
1570                                          NULL, /* GCancellable */
1571                                          &error);
1572       g_assert_no_error (error);
1573       g_variant_get (res, "(i)", &val);
1574       g_assert_cmpint (val, ==, 2 + n);
1575       g_variant_unref (res);
1576       g_object_unref (c);
1577   }
1578
1579   g_main_loop_quit (data->loop);
1580   g_thread_join (service_thread);
1581   dmp_data_free (data);
1582   teardown_test_address ();
1583
1584   g_main_loop_unref (loop);
1585   g_free (test_guid);
1586 }
1587
1588 /* ---------------------------------------------------------------------------------------------------- */
1589
1590 static gboolean
1591 nonce_tcp_on_authorize_authenticated_peer (GDBusAuthObserver *observer,
1592                                            GIOStream         *stream,
1593                                            GCredentials      *credentials,
1594                                            gpointer           user_data)
1595 {
1596   PeerData *data = user_data;
1597   gboolean authorized;
1598
1599   data->num_connection_attempts++;
1600
1601   authorized = TRUE;
1602   if (!data->accept_connection)
1603     {
1604       authorized = FALSE;
1605       g_main_loop_quit (loop);
1606     }
1607
1608   return authorized;
1609 }
1610
1611 /* Runs in thread we created GDBusServer in (since we didn't pass G_DBUS_SERVER_FLAGS_RUN_IN_THREAD) */
1612 static gboolean
1613 nonce_tcp_on_new_connection (GDBusServer *server,
1614                              GDBusConnection *connection,
1615                              gpointer user_data)
1616 {
1617   PeerData *data = user_data;
1618
1619   g_ptr_array_add (data->current_connections, g_object_ref (connection));
1620
1621   g_main_loop_quit (loop);
1622
1623   return TRUE;
1624 }
1625
1626 static gpointer
1627 nonce_tcp_service_thread_func (gpointer user_data)
1628 {
1629   PeerData *data = user_data;
1630   GMainContext *service_context;
1631   GDBusAuthObserver *observer;
1632   GError *error;
1633
1634   service_context = g_main_context_new ();
1635   g_main_context_push_thread_default (service_context);
1636
1637   error = NULL;
1638   observer = g_dbus_auth_observer_new ();
1639   server = g_dbus_server_new_sync ("nonce-tcp:host=127.0.0.1",
1640                                    G_DBUS_SERVER_FLAGS_NONE,
1641                                    test_guid,
1642                                    observer,
1643                                    NULL, /* cancellable */
1644                                    &error);
1645   g_assert_no_error (error);
1646
1647   g_signal_connect (server,
1648                     "new-connection",
1649                     G_CALLBACK (nonce_tcp_on_new_connection),
1650                     data);
1651   g_signal_connect (observer,
1652                     "authorize-authenticated-peer",
1653                     G_CALLBACK (nonce_tcp_on_authorize_authenticated_peer),
1654                     data);
1655   g_object_unref (observer);
1656
1657   g_dbus_server_start (server);
1658
1659   run_service_loop (service_context);
1660
1661   g_main_context_pop_thread_default (service_context);
1662
1663   teardown_service_loop ();
1664   g_main_context_unref (service_context);
1665
1666   /* test code specifically unrefs the server - see below */
1667   g_assert (server == NULL);
1668
1669   return NULL;
1670 }
1671
1672 static void
1673 test_nonce_tcp (void)
1674 {
1675   PeerData data;
1676   GError *error;
1677   GThread *service_thread;
1678   GDBusConnection *c;
1679   gchar *s;
1680   gchar *nonce_file;
1681   gboolean res;
1682   const gchar *address;
1683
1684   test_guid = g_dbus_generate_guid ();
1685   loop = g_main_loop_new (NULL, FALSE);
1686
1687   memset (&data, '\0', sizeof (PeerData));
1688   data.current_connections = g_ptr_array_new_with_free_func (g_object_unref);
1689
1690   error = NULL;
1691   server = NULL;
1692   service_thread = g_thread_new ("nonce-tcp-service",
1693                                  nonce_tcp_service_thread_func,
1694                                  &data);
1695   await_service_loop ();
1696   g_assert (server != NULL);
1697
1698   /* bring up a connection and accept it */
1699   data.accept_connection = TRUE;
1700   error = NULL;
1701   c = g_dbus_connection_new_for_address_sync (g_dbus_server_get_client_address (server),
1702                                               G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
1703                                               NULL, /* GDBusAuthObserver */
1704                                               NULL, /* cancellable */
1705                                               &error);
1706   g_assert_no_error (error);
1707   g_assert (c != NULL);
1708   while (data.current_connections->len < 1)
1709     g_thread_yield ();
1710   g_assert_cmpint (data.current_connections->len, ==, 1);
1711   g_assert_cmpint (data.num_connection_attempts, ==, 1);
1712   g_assert (g_dbus_connection_get_unique_name (c) == NULL);
1713   g_assert_cmpstr (g_dbus_connection_get_guid (c), ==, test_guid);
1714   g_object_unref (c);
1715
1716   /* now, try to subvert the nonce file (this assumes noncefile is the last key/value pair)
1717    */
1718
1719   address = g_dbus_server_get_client_address (server);
1720
1721   s = strstr (address, "noncefile=");
1722   g_assert (s != NULL);
1723   s += sizeof "noncefile=" - 1;
1724   nonce_file = g_strdup (s);
1725
1726   /* First try invalid data in the nonce file - this will actually
1727    * make the client send this and the server will reject it. The way
1728    * it works is that if the nonce doesn't match, the server will
1729    * simply close the connection. So, from the client point of view,
1730    * we can see a variety of errors.
1731    */
1732   error = NULL;
1733   res = g_file_set_contents (nonce_file,
1734                              "0123456789012345",
1735                              -1,
1736                              &error);
1737   g_assert_no_error (error);
1738   g_assert (res);
1739   c = g_dbus_connection_new_for_address_sync (address,
1740                                               G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
1741                                               NULL, /* GDBusAuthObserver */
1742                                               NULL, /* cancellable */
1743                                               &error);
1744   _g_assert_error_domain (error, G_IO_ERROR);
1745   g_error_free (error);
1746   g_assert (c == NULL);
1747
1748   /* Then try with a nonce-file of incorrect length - this will make
1749    * the client complain - we won't even try connecting to the server
1750    * for this
1751    */
1752   error = NULL;
1753   res = g_file_set_contents (nonce_file,
1754                              "0123456789012345_",
1755                              -1,
1756                              &error);
1757   g_assert_no_error (error);
1758   g_assert (res);
1759   c = g_dbus_connection_new_for_address_sync (address,
1760                                               G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
1761                                               NULL, /* GDBusAuthObserver */
1762                                               NULL, /* cancellable */
1763                                               &error);
1764   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1765   g_error_free (error);
1766   g_assert (c == NULL);
1767
1768   /* Finally try with no nonce-file at all */
1769   g_assert_cmpint (g_unlink (nonce_file), ==, 0);
1770   error = NULL;
1771   c = g_dbus_connection_new_for_address_sync (address,
1772                                               G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
1773                                               NULL, /* GDBusAuthObserver */
1774                                               NULL, /* cancellable */
1775                                               &error);
1776   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1777   g_error_free (error);
1778   g_assert (c == NULL);
1779
1780   /* Recreate the nonce-file so we can ensure the server deletes it when stopped. */
1781   g_assert_cmpint (g_creat (nonce_file, 0600), !=, -1);
1782
1783   g_dbus_server_stop (server);
1784   g_object_unref (server);
1785   server = NULL;
1786
1787   g_assert_false (g_file_test (nonce_file, G_FILE_TEST_EXISTS));
1788   g_free (nonce_file);
1789
1790   g_main_loop_quit (service_loop);
1791   g_thread_join (service_thread);
1792
1793   g_ptr_array_unref (data.current_connections);
1794
1795   g_main_loop_unref (loop);
1796   g_free (test_guid);
1797 }
1798
1799 static void
1800 test_credentials (void)
1801 {
1802   GCredentials *c1, *c2;
1803   GError *error;
1804   gchar *desc;
1805
1806   c1 = g_credentials_new ();
1807   c2 = g_credentials_new ();
1808
1809   error = NULL;
1810   if (g_credentials_set_unix_user (c2, getuid (), &error))
1811     g_assert_no_error (error);
1812
1813   g_clear_error (&error);
1814   g_assert (g_credentials_is_same_user (c1, c2, &error));
1815   g_assert_no_error (error);
1816
1817   desc = g_credentials_to_string (c1);
1818   g_assert (desc != NULL);
1819   g_free (desc);
1820
1821   g_object_unref (c1);
1822   g_object_unref (c2);
1823 }
1824
1825 /* ---------------------------------------------------------------------------------------------------- */
1826
1827 static gboolean
1828 tcp_anonymous_on_new_connection (GDBusServer     *server,
1829                                  GDBusConnection *connection,
1830                                  gpointer         user_data)
1831 {
1832   gboolean *seen_connection = user_data;
1833   *seen_connection = TRUE;
1834   return TRUE;
1835 }
1836
1837 static gpointer
1838 tcp_anonymous_service_thread_func (gpointer user_data)
1839 {
1840   gboolean *seen_connection = user_data;
1841   GMainContext *service_context;
1842   GError *error;
1843
1844   service_context = g_main_context_new ();
1845   g_main_context_push_thread_default (service_context);
1846
1847   error = NULL;
1848   server = g_dbus_server_new_sync ("tcp:host=127.0.0.1",
1849                                    G_DBUS_SERVER_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS,
1850                                    test_guid,
1851                                    NULL, /* GDBusObserver* */
1852                                    NULL, /* GCancellable* */
1853                                    &error);
1854   g_assert_no_error (error);
1855
1856   g_signal_connect (server,
1857                     "new-connection",
1858                     G_CALLBACK (tcp_anonymous_on_new_connection),
1859                     seen_connection);
1860
1861   g_dbus_server_start (server);
1862
1863   run_service_loop (service_context);
1864
1865   g_main_context_pop_thread_default (service_context);
1866
1867   teardown_service_loop ();
1868   g_main_context_unref (service_context);
1869
1870   return NULL;
1871 }
1872
1873 static void
1874 test_tcp_anonymous (void)
1875 {
1876   gboolean seen_connection;
1877   GThread *service_thread;
1878   GDBusConnection *connection;
1879   GError *error;
1880
1881   test_guid = g_dbus_generate_guid ();
1882   loop = g_main_loop_new (NULL, FALSE);
1883
1884   seen_connection = FALSE;
1885   service_thread = g_thread_new ("tcp-anon-service",
1886                                  tcp_anonymous_service_thread_func,
1887                                  &seen_connection);
1888   await_service_loop ();
1889   g_assert (server != NULL);
1890
1891   error = NULL;
1892   connection = g_dbus_connection_new_for_address_sync (g_dbus_server_get_client_address (server),
1893                                                        G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
1894                                                        NULL, /* GDBusAuthObserver* */
1895                                                        NULL, /* GCancellable */
1896                                                        &error);
1897   g_assert_no_error (error);
1898   g_assert (connection != NULL);
1899
1900   while (!seen_connection)
1901     g_thread_yield ();
1902
1903   g_object_unref (connection);
1904
1905   g_main_loop_quit (service_loop);
1906   g_dbus_server_stop (server);
1907   g_object_unref (server);
1908   server = NULL;
1909
1910   g_thread_join (service_thread);
1911
1912   g_main_loop_unref (loop);
1913   g_free (test_guid);
1914 }
1915
1916 /* ---------------------------------------------------------------------------------------------------- */
1917
1918 static GDBusServer *codegen_server = NULL;
1919
1920 static gboolean
1921 codegen_on_animal_poke (ExampleAnimal          *animal,
1922                         GDBusMethodInvocation  *invocation,
1923                         gboolean                make_sad,
1924                         gboolean                make_happy,
1925                         gpointer                user_data)
1926 {
1927   if ((make_sad && make_happy) || (!make_sad && !make_happy))
1928     {
1929       g_main_loop_quit (service_loop);
1930
1931       g_dbus_method_invocation_return_dbus_error (invocation,
1932                                                   "org.gtk.GDBus.Examples.ObjectManager.Error.Failed",
1933                                                   "Exactly one of make_sad or make_happy must be TRUE");
1934       goto out;
1935     }
1936
1937   if (make_sad)
1938     {
1939       if (g_strcmp0 (example_animal_get_mood (animal), "Sad") == 0)
1940         {
1941           g_dbus_method_invocation_return_dbus_error (invocation,
1942                                                       "org.gtk.GDBus.Examples.ObjectManager.Error.SadAnimalIsSad",
1943                                                       "Sad animal is already sad");
1944           goto out;
1945         }
1946
1947       example_animal_set_mood (animal, "Sad");
1948       example_animal_complete_poke (animal, invocation);
1949       goto out;
1950     }
1951
1952   if (make_happy)
1953     {
1954       if (g_strcmp0 (example_animal_get_mood (animal), "Happy") == 0)
1955         {
1956           g_dbus_method_invocation_return_dbus_error (invocation,
1957                                                       "org.gtk.GDBus.Examples.ObjectManager.Error.HappyAnimalIsHappy",
1958                                                       "Happy animal is already happy");
1959           goto out;
1960         }
1961
1962       example_animal_set_mood (animal, "Happy");
1963       example_animal_complete_poke (animal, invocation);
1964       goto out;
1965     }
1966
1967   g_assert_not_reached ();
1968
1969  out:
1970   return G_DBUS_METHOD_INVOCATION_HANDLED;
1971 }
1972
1973 /* Runs in thread we created GDBusServer in (since we didn't pass G_DBUS_SERVER_FLAGS_RUN_IN_THREAD) */
1974 static gboolean
1975 codegen_on_new_connection (GDBusServer *server,
1976                            GDBusConnection *connection,
1977                            gpointer user_data)
1978 {
1979   ExampleAnimal *animal = user_data;
1980   GError        *error = NULL;
1981
1982   /* g_printerr ("Client connected.\n" */
1983   /*          "Negotiated capabilities: unix-fd-passing=%d\n", */
1984   /*          g_dbus_connection_get_capabilities (connection) & G_DBUS_CAPABILITY_FLAGS_UNIX_FD_PASSING); */
1985
1986   g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (animal), connection,
1987                                     "/Example/Animals/000", &error);
1988   g_assert_no_error (error);
1989
1990   return TRUE;
1991 }
1992
1993 static gpointer
1994 codegen_service_thread_func (gpointer user_data)
1995 {
1996   GMainContext   *service_context;
1997   ExampleAnimal  *animal;
1998   GError         *error = NULL;
1999
2000   service_context = g_main_context_new ();
2001   g_main_context_push_thread_default (service_context);
2002
2003   /* Create the animal in the right thread context */
2004   animal = example_animal_skeleton_new ();
2005
2006   /* Handle Poke() D-Bus method invocations on the .Animal interface */
2007   g_signal_connect (animal, "handle-poke",
2008                     G_CALLBACK (codegen_on_animal_poke),
2009                     NULL); /* user_data */
2010
2011   codegen_server = g_dbus_server_new_sync (tmp_address,
2012                                            G_DBUS_SERVER_FLAGS_NONE,
2013                                            test_guid,
2014                                            NULL, /* observer */
2015                                            NULL, /* cancellable */
2016                                            &error);
2017   g_assert_no_error (error);
2018   g_dbus_server_start (codegen_server);
2019
2020   g_signal_connect (codegen_server, "new-connection",
2021                     G_CALLBACK (codegen_on_new_connection),
2022                     animal);
2023
2024   run_service_loop (service_context);
2025
2026   g_object_unref (animal);
2027
2028   g_main_context_pop_thread_default (service_context);
2029
2030   teardown_service_loop ();
2031   g_main_context_unref (service_context);
2032
2033   g_dbus_server_stop (codegen_server);
2034   g_object_unref (codegen_server);
2035   codegen_server = NULL;
2036
2037   return NULL;
2038 }
2039
2040
2041 static gboolean
2042 codegen_quit_mainloop_timeout (gpointer data)
2043 {
2044   g_main_loop_quit (loop);
2045   return G_SOURCE_REMOVE;
2046 }
2047
2048 static void
2049 codegen_test_peer (void)
2050 {
2051   GDBusConnection     *connection;
2052   ExampleAnimal       *animal1, *animal2;
2053   GThread             *service_thread;
2054   GError              *error = NULL;
2055   GVariant            *value;
2056   const gchar         *s;
2057
2058   test_guid = g_dbus_generate_guid ();
2059   loop = g_main_loop_new (NULL, FALSE);
2060
2061   setup_test_address ();
2062
2063   /* bring up a server - we run the server in a different thread to avoid deadlocks */
2064   service_thread = g_thread_new ("codegen_test_peer",
2065                                  codegen_service_thread_func,
2066                                  NULL);
2067   await_service_loop ();
2068   g_assert (codegen_server != NULL);
2069
2070   /* Get an animal 1 ...  */
2071   connection = g_dbus_connection_new_for_address_sync (g_dbus_server_get_client_address (codegen_server),
2072                                                        G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
2073                                                        NULL, /* GDBusAuthObserver */
2074                                                        NULL, /* cancellable */
2075                                                        &error);
2076   g_assert_no_error (error);
2077   g_assert (connection != NULL);
2078
2079   animal1 = example_animal_proxy_new_sync (connection, 0, NULL,
2080                                            "/Example/Animals/000", NULL, &error);
2081   g_assert_no_error (error);
2082   g_assert (animal1 != NULL);
2083   g_object_unref (connection);
2084
2085   /* Get animal 2 ...  */
2086   connection = g_dbus_connection_new_for_address_sync (g_dbus_server_get_client_address (codegen_server),
2087                                                        G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
2088                                                        NULL, /* GDBusAuthObserver */
2089                                                        NULL, /* cancellable */
2090                                                        &error);
2091   g_assert_no_error (error);
2092   g_assert (connection != NULL);
2093
2094   animal2 = example_animal_proxy_new_sync (connection, 0, NULL,
2095                                            "/Example/Animals/000", NULL, &error);
2096   g_assert_no_error (error);
2097   g_assert (animal2 != NULL);
2098   g_object_unref (connection);
2099
2100   /* Make animal sad via animal1  */
2101   example_animal_call_poke_sync (animal1, TRUE, FALSE, NULL, &error);
2102   g_assert_no_error (error);
2103
2104   /* Poke server and make sure animal is updated */
2105   value = g_dbus_proxy_call_sync (G_DBUS_PROXY (animal1),
2106                                   "org.freedesktop.DBus.Peer.Ping",
2107                                   NULL, G_DBUS_CALL_FLAGS_NONE, -1,
2108                                   NULL, &error);
2109   g_assert_no_error (error);
2110   g_assert (value != NULL);
2111   g_variant_unref (value);
2112
2113   /* Give the proxies a chance to refresh in the default main loop */
2114   g_timeout_add (100, codegen_quit_mainloop_timeout, NULL);
2115   g_main_loop_run (loop);
2116
2117   /* Assert animals are sad */
2118   g_assert_cmpstr (example_animal_get_mood (animal1), ==, "Sad");
2119   g_assert_cmpstr (example_animal_get_mood (animal2), ==, "Sad");
2120
2121   /* Make animal happy via animal2  */
2122   example_animal_call_poke_sync (animal2, FALSE, TRUE, NULL, &error);
2123   g_assert_no_error (error);
2124
2125   /* Some random unrelated call, just to get some test coverage */
2126   value = g_dbus_proxy_call_sync (G_DBUS_PROXY (animal2),
2127                                   "org.freedesktop.DBus.Peer.GetMachineId",
2128                                   NULL, G_DBUS_CALL_FLAGS_NONE, -1,
2129                                   NULL, &error);
2130   g_assert_no_error (error);
2131   g_variant_get (value, "(&s)", &s);
2132   g_test_message ("Machine ID: %s", s);
2133   /* It's valid for machine-id inside containers to be empty, so we
2134    * need to test for that possibility
2135    */
2136   g_assert ((s == NULL || *s == '\0') || g_dbus_is_guid (s));
2137   g_variant_unref (value);
2138   
2139   /* Poke server and make sure animal is updated */
2140   value = g_dbus_proxy_call_sync (G_DBUS_PROXY (animal2),
2141                                   "org.freedesktop.DBus.Peer.Ping",
2142                                   NULL, G_DBUS_CALL_FLAGS_NONE, -1,
2143                                   NULL, &error);
2144   g_assert_no_error (error);
2145   g_assert (value != NULL);
2146   g_variant_unref (value);
2147
2148   /* Give the proxies a chance to refresh in the default main loop */
2149   g_timeout_add (1000, codegen_quit_mainloop_timeout, NULL);
2150   g_main_loop_run (loop);
2151
2152   /* Assert animals are happy */
2153   g_assert_cmpstr (example_animal_get_mood (animal1), ==, "Happy");
2154   g_assert_cmpstr (example_animal_get_mood (animal2), ==, "Happy");
2155
2156   /* This final call making the animal happy and sad will cause
2157    * the server to quit, when the server quits we dont get property
2158    * change notifications anyway because those are done from an idle handler
2159    */
2160   example_animal_call_poke_sync (animal2, TRUE, TRUE, NULL, &error);
2161   g_clear_error (&error);
2162
2163   g_object_unref (animal1);
2164   g_object_unref (animal2);
2165   g_thread_join (service_thread);
2166
2167   teardown_test_address ();
2168
2169   g_main_loop_unref (loop);
2170   g_free (test_guid);
2171 }
2172
2173 /* ---------------------------------------------------------------------------------------------------- */
2174
2175
2176 int
2177 main (int   argc,
2178       char *argv[])
2179 {
2180   gint ret;
2181   GDBusNodeInfo *introspection_data = NULL;
2182
2183   g_test_init (&argc, &argv, G_TEST_OPTION_ISOLATE_DIRS, NULL);
2184
2185   introspection_data = g_dbus_node_info_new_for_xml (test_interface_introspection_xml, NULL);
2186   g_assert (introspection_data != NULL);
2187   test_interface_introspection_data = introspection_data->interfaces[0];
2188
2189   g_test_add_func ("/gdbus/peer-to-peer", test_peer);
2190   g_test_add_func ("/gdbus/peer-to-peer/invalid/server",
2191                    test_peer_invalid_server);
2192   g_test_add_func ("/gdbus/peer-to-peer/invalid/conn/stream/async",
2193                    test_peer_invalid_conn_stream_async);
2194   g_test_add_func ("/gdbus/peer-to-peer/invalid/conn/stream/sync",
2195                    test_peer_invalid_conn_stream_sync);
2196   g_test_add_func ("/gdbus/peer-to-peer/invalid/conn/addr/async",
2197                    test_peer_invalid_conn_addr_async);
2198   g_test_add_func ("/gdbus/peer-to-peer/invalid/conn/addr/sync",
2199                    test_peer_invalid_conn_addr_sync);
2200   g_test_add_func ("/gdbus/peer-to-peer/signals", test_peer_signals);
2201   g_test_add_func ("/gdbus/delayed-message-processing", delayed_message_processing);
2202   g_test_add_func ("/gdbus/nonce-tcp", test_nonce_tcp);
2203
2204   g_test_add_func ("/gdbus/tcp-anonymous", test_tcp_anonymous);
2205   g_test_add_func ("/gdbus/credentials", test_credentials);
2206   g_test_add_func ("/gdbus/codegen-peer-to-peer", codegen_test_peer);
2207
2208   ret = g_test_run ();
2209
2210   g_dbus_node_info_unref (introspection_data);
2211
2212   return ret;
2213 }