Merge branch '976-disable-assert-checks' into 'master'
[glib.git] / gio / tests / gdbus-peer.c
blob7f35baae6da0398ed710d320b128923d5bb1bdcb
1 /* GLib testing framework examples and tests
3 * Copyright (C) 2008-2010 Red Hat, Inc.
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.
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.
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/>.
18 * Author: David Zeuthen <davidz@redhat.com>
21 #include "config.h"
23 #include <gio/gio.h>
24 #include <unistd.h>
25 #include <string.h>
27 /* for open(2) */
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include <fcntl.h>
31 #include <string.h>
33 /* for g_unlink() */
34 #include <glib/gstdio.h>
36 #include <gio/gnetworking.h>
37 #include <gio/gunixsocketaddress.h>
38 #include <gio/gunixfdlist.h>
39 #include <gio/gcredentialsprivate.h>
41 #ifdef G_OS_UNIX
42 #include <gio/gunixconnection.h>
43 #include <errno.h>
44 #endif
46 #include "gdbus-tests.h"
48 #include "gdbus-object-manager-example/gdbus-example-objectmanager-generated.h"
50 #ifdef G_OS_UNIX
51 static gboolean is_unix = TRUE;
52 #else
53 static gboolean is_unix = FALSE;
54 #endif
56 static gchar *tmp_address = NULL;
57 static gchar *test_guid = NULL;
58 static GMutex service_loop_lock;
59 static GCond service_loop_cond;
60 static GMainLoop *service_loop = NULL;
61 static GDBusServer *server = NULL;
62 static GMainLoop *loop = NULL;
64 /* ---------------------------------------------------------------------------------------------------- */
65 /* Test that peer-to-peer connections work */
66 /* ---------------------------------------------------------------------------------------------------- */
69 typedef struct
71 gboolean accept_connection;
72 gint num_connection_attempts;
73 GPtrArray *current_connections;
74 guint num_method_calls;
75 gboolean signal_received;
76 } PeerData;
78 static const gchar *test_interface_introspection_xml =
79 "<node>"
80 " <interface name='org.gtk.GDBus.PeerTestInterface'>"
81 " <method name='HelloPeer'>"
82 " <arg type='s' name='greeting' direction='in'/>"
83 " <arg type='s' name='response' direction='out'/>"
84 " </method>"
85 " <method name='EmitSignal'/>"
86 " <method name='EmitSignalWithNameSet'/>"
87 " <method name='OpenFile'>"
88 " <arg type='s' name='path' direction='in'/>"
89 " </method>"
90 " <signal name='PeerSignal'>"
91 " <arg type='s' name='a_string'/>"
92 " </signal>"
93 " <property type='s' name='PeerProperty' access='read'/>"
94 " </interface>"
95 "</node>";
96 static GDBusInterfaceInfo *test_interface_introspection_data = NULL;
98 static void
99 test_interface_method_call (GDBusConnection *connection,
100 const gchar *sender,
101 const gchar *object_path,
102 const gchar *interface_name,
103 const gchar *method_name,
104 GVariant *parameters,
105 GDBusMethodInvocation *invocation,
106 gpointer user_data)
108 PeerData *data = user_data;
109 const GDBusMethodInfo *info;
111 data->num_method_calls++;
113 g_assert_cmpstr (object_path, ==, "/org/gtk/GDBus/PeerTestObject");
114 g_assert_cmpstr (interface_name, ==, "org.gtk.GDBus.PeerTestInterface");
116 info = g_dbus_method_invocation_get_method_info (invocation);
117 g_assert_cmpstr (info->name, ==, method_name);
119 if (g_strcmp0 (method_name, "HelloPeer") == 0)
121 const gchar *greeting;
122 gchar *response;
124 g_variant_get (parameters, "(&s)", &greeting);
126 response = g_strdup_printf ("You greeted me with '%s'.",
127 greeting);
128 g_dbus_method_invocation_return_value (invocation,
129 g_variant_new ("(s)", response));
130 g_free (response);
132 else if (g_strcmp0 (method_name, "EmitSignal") == 0)
134 GError *error;
136 error = NULL;
137 g_dbus_connection_emit_signal (connection,
138 NULL,
139 "/org/gtk/GDBus/PeerTestObject",
140 "org.gtk.GDBus.PeerTestInterface",
141 "PeerSignal",
142 NULL,
143 &error);
144 g_assert_no_error (error);
145 g_dbus_method_invocation_return_value (invocation, NULL);
147 else if (g_strcmp0 (method_name, "EmitSignalWithNameSet") == 0)
149 GError *error;
150 gboolean ret;
151 GDBusMessage *message;
153 message = g_dbus_message_new_signal ("/org/gtk/GDBus/PeerTestObject",
154 "org.gtk.GDBus.PeerTestInterface",
155 "PeerSignalWithNameSet");
156 g_dbus_message_set_sender (message, ":1.42");
158 error = NULL;
159 ret = g_dbus_connection_send_message (connection, message, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, &error);
160 g_assert_no_error (error);
161 g_assert (ret);
162 g_object_unref (message);
164 g_dbus_method_invocation_return_value (invocation, NULL);
166 else if (g_strcmp0 (method_name, "OpenFile") == 0)
168 #ifdef G_OS_UNIX
169 const gchar *path;
170 GDBusMessage *reply;
171 GError *error;
172 gint fd;
173 GUnixFDList *fd_list;
175 g_variant_get (parameters, "(&s)", &path);
177 fd_list = g_unix_fd_list_new ();
179 error = NULL;
181 fd = g_open (path, O_RDONLY, 0);
182 g_assert (fd != -1);
183 g_unix_fd_list_append (fd_list, fd, &error);
184 g_assert_no_error (error);
185 close (fd);
187 reply = g_dbus_message_new_method_reply (g_dbus_method_invocation_get_message (invocation));
188 g_dbus_message_set_unix_fd_list (reply, fd_list);
189 g_object_unref (fd_list);
190 g_object_unref (invocation);
192 error = NULL;
193 g_dbus_connection_send_message (connection,
194 reply,
195 G_DBUS_SEND_MESSAGE_FLAGS_NONE,
196 NULL, /* out_serial */
197 &error);
198 g_assert_no_error (error);
199 g_object_unref (reply);
200 #else
201 g_dbus_method_invocation_return_dbus_error (invocation,
202 "org.gtk.GDBus.NotOnUnix",
203 "Your OS does not support file descriptor passing");
204 #endif
206 else
208 g_assert_not_reached ();
212 static GVariant *
213 test_interface_get_property (GDBusConnection *connection,
214 const gchar *sender,
215 const gchar *object_path,
216 const gchar *interface_name,
217 const gchar *property_name,
218 GError **error,
219 gpointer user_data)
221 g_assert_cmpstr (object_path, ==, "/org/gtk/GDBus/PeerTestObject");
222 g_assert_cmpstr (interface_name, ==, "org.gtk.GDBus.PeerTestInterface");
223 g_assert_cmpstr (property_name, ==, "PeerProperty");
225 return g_variant_new_string ("ThePropertyValue");
229 static const GDBusInterfaceVTable test_interface_vtable =
231 test_interface_method_call,
232 test_interface_get_property,
233 NULL /* set_property */
236 static void
237 on_proxy_signal_received (GDBusProxy *proxy,
238 gchar *sender_name,
239 gchar *signal_name,
240 GVariant *parameters,
241 gpointer user_data)
243 PeerData *data = user_data;
245 data->signal_received = TRUE;
247 g_assert (sender_name == NULL);
248 g_assert_cmpstr (signal_name, ==, "PeerSignal");
249 g_main_loop_quit (loop);
252 static void
253 on_proxy_signal_received_with_name_set (GDBusProxy *proxy,
254 gchar *sender_name,
255 gchar *signal_name,
256 GVariant *parameters,
257 gpointer user_data)
259 PeerData *data = user_data;
261 data->signal_received = TRUE;
263 g_assert_cmpstr (sender_name, ==, ":1.42");
264 g_assert_cmpstr (signal_name, ==, "PeerSignalWithNameSet");
265 g_main_loop_quit (loop);
268 /* ---------------------------------------------------------------------------------------------------- */
270 static gboolean
271 on_authorize_authenticated_peer (GDBusAuthObserver *observer,
272 GIOStream *stream,
273 GCredentials *credentials,
274 gpointer user_data)
276 PeerData *data = user_data;
277 gboolean authorized;
279 data->num_connection_attempts++;
281 authorized = TRUE;
282 if (!data->accept_connection)
284 authorized = FALSE;
285 g_main_loop_quit (loop);
288 return authorized;
291 /* Runs in thread we created GDBusServer in (since we didn't pass G_DBUS_SERVER_FLAGS_RUN_IN_THREAD) */
292 static gboolean
293 on_new_connection (GDBusServer *server,
294 GDBusConnection *connection,
295 gpointer user_data)
297 PeerData *data = user_data;
298 GError *error;
299 guint reg_id;
301 //g_printerr ("Client connected.\n"
302 // "Negotiated capabilities: unix-fd-passing=%d\n",
303 // g_dbus_connection_get_capabilities (connection) & G_DBUS_CAPABILITY_FLAGS_UNIX_FD_PASSING);
305 g_ptr_array_add (data->current_connections, g_object_ref (connection));
307 #if G_CREDENTIALS_SUPPORTED
309 GCredentials *credentials;
311 credentials = g_dbus_connection_get_peer_credentials (connection);
313 g_assert (credentials != NULL);
314 g_assert_cmpuint (g_credentials_get_unix_user (credentials, NULL), ==,
315 getuid ());
316 g_assert_cmpuint (g_credentials_get_unix_pid (credentials, NULL), ==,
317 getpid ());
319 #endif
321 /* export object on the newly established connection */
322 error = NULL;
323 reg_id = g_dbus_connection_register_object (connection,
324 "/org/gtk/GDBus/PeerTestObject",
325 test_interface_introspection_data,
326 &test_interface_vtable,
327 data,
328 NULL, /* GDestroyNotify for data */
329 &error);
330 g_assert_no_error (error);
331 g_assert (reg_id > 0);
333 g_main_loop_quit (loop);
335 return TRUE;
338 /* We don't tell the main thread about the new GDBusServer until it has
339 * had a chance to start listening. */
340 static gboolean
341 idle_in_service_loop (gpointer loop)
343 g_assert (service_loop == NULL);
344 g_mutex_lock (&service_loop_lock);
345 service_loop = loop;
346 g_cond_broadcast (&service_loop_cond);
347 g_mutex_unlock (&service_loop_lock);
349 return G_SOURCE_REMOVE;
352 static void
353 run_service_loop (GMainContext *service_context)
355 GMainLoop *loop;
356 GSource *source;
358 g_assert (service_loop == NULL);
360 loop = g_main_loop_new (service_context, FALSE);
361 source = g_idle_source_new ();
362 g_source_set_callback (source, idle_in_service_loop, loop, NULL);
363 g_source_attach (source, service_context);
364 g_source_unref (source);
365 g_main_loop_run (loop);
368 static void
369 teardown_service_loop (void)
371 g_mutex_lock (&service_loop_lock);
372 g_clear_pointer (&service_loop, g_main_loop_unref);
373 g_mutex_unlock (&service_loop_lock);
376 static void
377 await_service_loop (void)
379 g_mutex_lock (&service_loop_lock);
380 while (service_loop == NULL)
381 g_cond_wait (&service_loop_cond, &service_loop_lock);
382 g_mutex_unlock (&service_loop_lock);
385 static gpointer
386 service_thread_func (gpointer user_data)
388 PeerData *data = user_data;
389 GMainContext *service_context;
390 GDBusAuthObserver *observer, *o;
391 GError *error;
392 GDBusServerFlags f;
393 gchar *a, *g;
394 gboolean b;
396 service_context = g_main_context_new ();
397 g_main_context_push_thread_default (service_context);
399 error = NULL;
400 observer = g_dbus_auth_observer_new ();
401 server = g_dbus_server_new_sync (tmp_address,
402 G_DBUS_SERVER_FLAGS_NONE,
403 test_guid,
404 observer,
405 NULL, /* cancellable */
406 &error);
407 g_assert_no_error (error);
409 g_signal_connect (server,
410 "new-connection",
411 G_CALLBACK (on_new_connection),
412 data);
413 g_signal_connect (observer,
414 "authorize-authenticated-peer",
415 G_CALLBACK (on_authorize_authenticated_peer),
416 data);
418 g_assert_cmpint (g_dbus_server_get_flags (server), ==, G_DBUS_SERVER_FLAGS_NONE);
419 g_assert_cmpstr (g_dbus_server_get_guid (server), ==, test_guid);
420 g_object_get (server,
421 "flags", &f,
422 "address", &a,
423 "guid", &g,
424 "active", &b,
425 "authentication-observer", &o,
426 NULL);
427 g_assert_cmpint (f, ==, G_DBUS_SERVER_FLAGS_NONE);
428 g_assert_cmpstr (a, ==, tmp_address);
429 g_assert_cmpstr (g, ==, test_guid);
430 g_assert (!b);
431 g_assert (o == observer);
432 g_free (a);
433 g_free (g);
434 g_object_unref (o);
436 g_object_unref (observer);
438 g_dbus_server_start (server);
440 run_service_loop (service_context);
442 g_main_context_pop_thread_default (service_context);
444 teardown_service_loop ();
445 g_main_context_unref (service_context);
447 /* test code specifically unrefs the server - see below */
448 g_assert (server == NULL);
450 return NULL;
453 #if 0
454 static gboolean
455 on_incoming_connection (GSocketService *service,
456 GSocketConnection *socket_connection,
457 GObject *source_object,
458 gpointer user_data)
460 PeerData *data = user_data;
462 if (data->accept_connection)
464 GError *error;
465 guint reg_id;
466 GDBusConnection *connection;
468 error = NULL;
469 connection = g_dbus_connection_new_sync (G_IO_STREAM (socket_connection),
470 test_guid,
471 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER,
472 NULL, /* cancellable */
473 &error);
474 g_assert_no_error (error);
476 g_ptr_array_add (data->current_connections, connection);
478 /* export object on the newly established connection */
479 error = NULL;
480 reg_id = g_dbus_connection_register_object (connection,
481 "/org/gtk/GDBus/PeerTestObject",
482 &test_interface_introspection_data,
483 &test_interface_vtable,
484 data,
485 NULL, /* GDestroyNotify for data */
486 &error);
487 g_assert_no_error (error);
488 g_assert (reg_id > 0);
491 else
493 /* don't do anything */
496 data->num_connection_attempts++;
498 g_main_loop_quit (loop);
500 /* stops other signal handlers from being invoked */
501 return TRUE;
504 static gpointer
505 service_thread_func (gpointer data)
507 GMainContext *service_context;
508 gchar *socket_path;
509 GSocketAddress *address;
510 GError *error;
512 service_context = g_main_context_new ();
513 g_main_context_push_thread_default (service_context);
515 socket_path = g_strdup_printf ("/tmp/gdbus-test-pid-%d", getpid ());
516 address = g_unix_socket_address_new (socket_path);
518 service = g_socket_service_new ();
519 error = NULL;
520 g_socket_listener_add_address (G_SOCKET_LISTENER (service),
521 address,
522 G_SOCKET_TYPE_STREAM,
523 G_SOCKET_PROTOCOL_DEFAULT,
524 NULL, /* source_object */
525 NULL, /* effective_address */
526 &error);
527 g_assert_no_error (error);
528 g_signal_connect (service,
529 "incoming",
530 G_CALLBACK (on_incoming_connection),
531 data);
532 g_socket_service_start (service);
534 run_service_loop (service_context);
536 g_main_context_pop_thread_default (service_context);
538 teardown_service_loop ();
539 g_main_context_unref (service_context);
541 g_object_unref (address);
542 g_free (socket_path);
543 return NULL;
545 #endif
547 /* ---------------------------------------------------------------------------------------------------- */
549 #if 0
550 static gboolean
551 check_connection (gpointer user_data)
553 PeerData *data = user_data;
554 guint n;
556 for (n = 0; n < data->current_connections->len; n++)
558 GDBusConnection *c;
559 GIOStream *stream;
561 c = G_DBUS_CONNECTION (data->current_connections->pdata[n]);
562 stream = g_dbus_connection_get_stream (c);
564 g_debug ("In check_connection for %d: connection %p, stream %p", n, c, stream);
565 g_debug ("closed = %d", g_io_stream_is_closed (stream));
567 GSocket *socket;
568 socket = g_socket_connection_get_socket (G_SOCKET_CONNECTION (stream));
569 g_debug ("socket_closed = %d", g_socket_is_closed (socket));
570 g_debug ("socket_condition_check = %d", g_socket_condition_check (socket, G_IO_IN|G_IO_OUT|G_IO_ERR|G_IO_HUP));
572 gchar buf[128];
573 GError *error;
574 gssize num_read;
575 error = NULL;
576 num_read = g_input_stream_read (g_io_stream_get_input_stream (stream),
577 buf,
578 128,
579 NULL,
580 &error);
581 if (num_read < 0)
583 g_debug ("error: %s", error->message);
584 g_error_free (error);
586 else
588 g_debug ("no error, read %d bytes", (gint) num_read);
592 return FALSE;
595 static gboolean
596 on_do_disconnect_in_idle (gpointer data)
598 GDBusConnection *c = G_DBUS_CONNECTION (data);
599 g_debug ("GDC %p has ref_count %d", c, G_OBJECT (c)->ref_count);
600 g_dbus_connection_disconnect (c);
601 g_object_unref (c);
602 return FALSE;
604 #endif
606 #ifdef G_OS_UNIX
607 static gchar *
608 read_all_from_fd (gint fd, gsize *out_len, GError **error)
610 GString *str;
611 gchar buf[64];
612 gssize num_read;
614 str = g_string_new (NULL);
618 int errsv;
620 num_read = read (fd, buf, sizeof (buf));
621 errsv = errno;
622 if (num_read == -1)
624 if (errsv == EAGAIN || errsv == EWOULDBLOCK)
625 continue;
626 g_set_error (error,
627 G_IO_ERROR,
628 g_io_error_from_errno (errsv),
629 "Failed reading %d bytes into offset %d: %s",
630 (gint) sizeof (buf),
631 (gint) str->len,
632 g_strerror (errsv));
633 goto error;
635 else if (num_read > 0)
637 g_string_append_len (str, buf, num_read);
639 else if (num_read == 0)
641 break;
644 while (TRUE);
646 if (out_len != NULL)
647 *out_len = str->len;
648 return g_string_free (str, FALSE);
650 error:
651 if (out_len != NULL)
652 *out_len = 0;
653 g_string_free (str, TRUE);
654 return NULL;
656 #endif
658 static void
659 test_peer (void)
661 GDBusConnection *c;
662 GDBusConnection *c2;
663 GDBusProxy *proxy;
664 GError *error;
665 PeerData data;
666 GVariant *value;
667 GVariant *result;
668 const gchar *s;
669 GThread *service_thread;
670 gulong signal_handler_id;
672 memset (&data, '\0', sizeof (PeerData));
673 data.current_connections = g_ptr_array_new_with_free_func (g_object_unref);
675 /* first try to connect when there is no server */
676 error = NULL;
677 c = g_dbus_connection_new_for_address_sync (is_unix ? "unix:path=/tmp/gdbus-test-does-not-exist-pid" :
678 /* NOTE: Even if something is listening on port 12345 the connection
679 * will fail because the nonce file doesn't exist */
680 "nonce-tcp:host=localhost,port=12345,noncefile=this-does-not-exist-gdbus",
681 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
682 NULL, /* GDBusAuthObserver */
683 NULL, /* cancellable */
684 &error);
685 _g_assert_error_domain (error, G_IO_ERROR);
686 g_assert (!g_dbus_error_is_remote_error (error));
687 g_clear_error (&error);
688 g_assert (c == NULL);
690 /* bring up a server - we run the server in a different thread to avoid deadlocks */
691 service_thread = g_thread_new ("test_peer",
692 service_thread_func,
693 &data);
694 await_service_loop ();
695 g_assert (server != NULL);
697 /* bring up a connection and accept it */
698 data.accept_connection = TRUE;
699 error = NULL;
700 c = g_dbus_connection_new_for_address_sync (g_dbus_server_get_client_address (server),
701 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
702 NULL, /* GDBusAuthObserver */
703 NULL, /* cancellable */
704 &error);
705 g_assert_no_error (error);
706 g_assert (c != NULL);
707 while (data.current_connections->len < 1)
708 g_main_loop_run (loop);
709 g_assert_cmpint (data.current_connections->len, ==, 1);
710 g_assert_cmpint (data.num_connection_attempts, ==, 1);
711 g_assert (g_dbus_connection_get_unique_name (c) == NULL);
712 g_assert_cmpstr (g_dbus_connection_get_guid (c), ==, test_guid);
714 /* check that we create a proxy, read properties, receive signals and invoke
715 * the HelloPeer() method. Since the server runs in another thread it's fine
716 * to use synchronous blocking API here.
718 error = NULL;
719 proxy = g_dbus_proxy_new_sync (c,
720 G_DBUS_PROXY_FLAGS_NONE,
721 NULL,
722 NULL, /* bus_name */
723 "/org/gtk/GDBus/PeerTestObject",
724 "org.gtk.GDBus.PeerTestInterface",
725 NULL, /* GCancellable */
726 &error);
727 g_assert_no_error (error);
728 g_assert (proxy != NULL);
729 error = NULL;
730 value = g_dbus_proxy_get_cached_property (proxy, "PeerProperty");
731 g_assert_cmpstr (g_variant_get_string (value, NULL), ==, "ThePropertyValue");
733 /* try invoking a method */
734 error = NULL;
735 result = g_dbus_proxy_call_sync (proxy,
736 "HelloPeer",
737 g_variant_new ("(s)", "Hey Peer!"),
738 G_DBUS_CALL_FLAGS_NONE,
740 NULL, /* GCancellable */
741 &error);
742 g_assert_no_error (error);
743 g_variant_get (result, "(&s)", &s);
744 g_assert_cmpstr (s, ==, "You greeted me with 'Hey Peer!'.");
745 g_variant_unref (result);
746 g_assert_cmpint (data.num_method_calls, ==, 1);
748 /* make the other peer emit a signal - catch it */
749 signal_handler_id = g_signal_connect (proxy,
750 "g-signal",
751 G_CALLBACK (on_proxy_signal_received),
752 &data);
753 g_assert (!data.signal_received);
754 g_dbus_proxy_call (proxy,
755 "EmitSignal",
756 NULL, /* no arguments */
757 G_DBUS_CALL_FLAGS_NONE,
759 NULL, /* GCancellable */
760 NULL, /* GAsyncReadyCallback - we don't care about the result */
761 NULL); /* user_data */
762 g_main_loop_run (loop);
763 g_assert (data.signal_received);
764 g_assert_cmpint (data.num_method_calls, ==, 2);
765 g_signal_handler_disconnect (proxy, signal_handler_id);
767 /* Also ensure that messages with the sender header-field set gets
768 * delivered to the proxy - note that this doesn't really make sense
769 * e.g. names are meaning-less in a peer-to-peer case... but we
770 * support it because it makes sense in certain bridging
771 * applications - see e.g. #623815.
773 signal_handler_id = g_signal_connect (proxy,
774 "g-signal",
775 G_CALLBACK (on_proxy_signal_received_with_name_set),
776 &data);
777 data.signal_received = FALSE;
778 g_dbus_proxy_call (proxy,
779 "EmitSignalWithNameSet",
780 NULL, /* no arguments */
781 G_DBUS_CALL_FLAGS_NONE,
783 NULL, /* GCancellable */
784 NULL, /* GAsyncReadyCallback - we don't care about the result */
785 NULL); /* user_data */
786 g_main_loop_run (loop);
787 g_assert (data.signal_received);
788 g_assert_cmpint (data.num_method_calls, ==, 3);
789 g_signal_handler_disconnect (proxy, signal_handler_id);
791 /* check for UNIX fd passing */
792 #ifdef G_OS_UNIX
794 GDBusMessage *method_call_message;
795 GDBusMessage *method_reply_message;
796 GUnixFDList *fd_list;
797 gint fd;
798 gchar *buf;
799 gsize len;
800 gchar *buf2;
801 gsize len2;
802 const char *testfile = g_test_get_filename (G_TEST_DIST, "file.c", NULL);
804 method_call_message = g_dbus_message_new_method_call (NULL, /* name */
805 "/org/gtk/GDBus/PeerTestObject",
806 "org.gtk.GDBus.PeerTestInterface",
807 "OpenFile");
808 g_dbus_message_set_body (method_call_message, g_variant_new ("(s)", testfile));
809 error = NULL;
810 method_reply_message = g_dbus_connection_send_message_with_reply_sync (c,
811 method_call_message,
812 G_DBUS_SEND_MESSAGE_FLAGS_NONE,
814 NULL, /* out_serial */
815 NULL, /* cancellable */
816 &error);
817 g_assert_no_error (error);
818 g_assert (g_dbus_message_get_message_type (method_reply_message) == G_DBUS_MESSAGE_TYPE_METHOD_RETURN);
819 fd_list = g_dbus_message_get_unix_fd_list (method_reply_message);
820 g_assert (fd_list != NULL);
821 g_assert_cmpint (g_unix_fd_list_get_length (fd_list), ==, 1);
822 error = NULL;
823 fd = g_unix_fd_list_get (fd_list, 0, &error);
824 g_assert_no_error (error);
825 g_object_unref (method_call_message);
826 g_object_unref (method_reply_message);
828 error = NULL;
829 len = 0;
830 buf = read_all_from_fd (fd, &len, &error);
831 g_assert_no_error (error);
832 g_assert (buf != NULL);
833 close (fd);
835 error = NULL;
836 g_file_get_contents (testfile,
837 &buf2,
838 &len2,
839 &error);
840 g_assert_no_error (error);
841 g_assert_cmpmem (buf, len, buf2, len2);
842 g_free (buf2);
843 g_free (buf);
845 #else
846 error = NULL;
847 result = g_dbus_proxy_call_sync (proxy,
848 "OpenFile",
849 g_variant_new ("(s)", "boo"),
850 G_DBUS_CALL_FLAGS_NONE,
852 NULL, /* GCancellable */
853 &error);
854 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_DBUS_ERROR);
855 g_assert (result == NULL);
856 g_error_free (error);
857 #endif /* G_OS_UNIX */
859 /* Check that g_socket_get_credentials() work - (though this really
860 * should be in socket.c)
863 GSocket *socket;
864 GCredentials *credentials;
865 socket = g_socket_connection_get_socket (G_SOCKET_CONNECTION (g_dbus_connection_get_stream (c)));
866 g_assert (G_IS_SOCKET (socket));
867 error = NULL;
868 credentials = g_socket_get_credentials (socket, &error);
870 #if G_CREDENTIALS_SOCKET_GET_CREDENTIALS_SUPPORTED
871 g_assert_no_error (error);
872 g_assert (G_IS_CREDENTIALS (credentials));
874 g_assert_cmpuint (g_credentials_get_unix_user (credentials, NULL), ==,
875 getuid ());
876 g_assert_cmpuint (g_credentials_get_unix_pid (credentials, NULL), ==,
877 getpid ());
878 g_object_unref (credentials);
879 #else
880 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED);
881 g_assert (credentials == NULL);
882 #endif
886 /* bring up a connection - don't accept it - this should fail
888 data.accept_connection = FALSE;
889 error = NULL;
890 c2 = g_dbus_connection_new_for_address_sync (g_dbus_server_get_client_address (server),
891 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
892 NULL, /* GDBusAuthObserver */
893 NULL, /* cancellable */
894 &error);
895 _g_assert_error_domain (error, G_IO_ERROR);
896 g_error_free (error);
897 g_assert (c2 == NULL);
899 #if 0
900 /* TODO: THIS TEST DOESN'T WORK YET */
902 /* bring up a connection - accept it.. then disconnect from the client side - check
903 * that the server side gets the disconnect signal.
905 error = NULL;
906 data.accept_connection = TRUE;
907 c2 = g_dbus_connection_new_for_address_sync (g_dbus_server_get_client_address (server),
908 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
909 NULL, /* GDBusAuthObserver */
910 NULL, /* cancellable */
911 &error);
912 g_assert_no_error (error);
913 g_assert (c2 != NULL);
914 g_assert (!g_dbus_connection_get_is_disconnected (c2));
915 while (data.num_connection_attempts < 3)
916 g_main_loop_run (loop);
917 g_assert_cmpint (data.current_connections->len, ==, 2);
918 g_assert_cmpint (data.num_connection_attempts, ==, 3);
919 g_assert (!g_dbus_connection_get_is_disconnected (G_DBUS_CONNECTION (data.current_connections->pdata[1])));
920 g_idle_add (on_do_disconnect_in_idle, c2);
921 g_debug ("==================================================");
922 g_debug ("==================================================");
923 g_debug ("==================================================");
924 g_debug ("waiting for disconnect on connection %p, stream %p",
925 data.current_connections->pdata[1],
926 g_dbus_connection_get_stream (data.current_connections->pdata[1]));
928 g_timeout_add (2000, check_connection, &data);
929 //_g_assert_signal_received (G_DBUS_CONNECTION (data.current_connections->pdata[1]), "closed");
930 g_main_loop_run (loop);
931 g_assert (g_dbus_connection_get_is_disconnected (G_DBUS_CONNECTION (data.current_connections->pdata[1])));
932 g_ptr_array_set_size (data.current_connections, 1); /* remove disconnected connection object */
933 #endif
935 /* unref the server and stop listening for new connections
937 * This won't bring down the established connections - check that c is still connected
938 * by invoking a method
940 //g_socket_service_stop (service);
941 //g_object_unref (service);
942 g_dbus_server_stop (server);
943 g_object_unref (server);
944 server = NULL;
946 error = NULL;
947 result = g_dbus_proxy_call_sync (proxy,
948 "HelloPeer",
949 g_variant_new ("(s)", "Hey Again Peer!"),
950 G_DBUS_CALL_FLAGS_NONE,
952 NULL, /* GCancellable */
953 &error);
954 g_assert_no_error (error);
955 g_variant_get (result, "(&s)", &s);
956 g_assert_cmpstr (s, ==, "You greeted me with 'Hey Again Peer!'.");
957 g_variant_unref (result);
958 g_assert_cmpint (data.num_method_calls, ==, 5);
960 #if 0
961 /* TODO: THIS TEST DOESN'T WORK YET */
963 /* now disconnect from the server side - check that the client side gets the signal */
964 g_assert_cmpint (data.current_connections->len, ==, 1);
965 g_assert (G_DBUS_CONNECTION (data.current_connections->pdata[0]) != c);
966 g_dbus_connection_disconnect (G_DBUS_CONNECTION (data.current_connections->pdata[0]));
967 if (!g_dbus_connection_get_is_disconnected (c))
968 _g_assert_signal_received (c, "closed");
969 g_assert (g_dbus_connection_get_is_disconnected (c));
970 #endif
972 g_object_unref (c);
973 g_ptr_array_unref (data.current_connections);
974 g_object_unref (proxy);
976 g_main_loop_quit (service_loop);
977 g_thread_join (service_thread);
980 /* ---------------------------------------------------------------------------------------------------- */
982 typedef struct
984 GDBusServer *server;
985 GMainContext *context;
986 GMainLoop *loop;
988 GList *connections;
989 } DmpData;
991 static void
992 dmp_data_free (DmpData *data)
994 g_main_loop_unref (data->loop);
995 g_main_context_unref (data->context);
996 g_object_unref (data->server);
997 g_list_free_full (data->connections, g_object_unref);
998 g_free (data);
1001 static void
1002 dmp_on_method_call (GDBusConnection *connection,
1003 const gchar *sender,
1004 const gchar *object_path,
1005 const gchar *interface_name,
1006 const gchar *method_name,
1007 GVariant *parameters,
1008 GDBusMethodInvocation *invocation,
1009 gpointer user_data)
1011 //DmpData *data = user_data;
1012 gint32 first;
1013 gint32 second;
1014 g_variant_get (parameters,
1015 "(ii)",
1016 &first,
1017 &second);
1018 g_dbus_method_invocation_return_value (invocation,
1019 g_variant_new ("(i)", first + second));
1022 static const GDBusInterfaceVTable dmp_interface_vtable =
1024 dmp_on_method_call,
1025 NULL, /* get_property */
1026 NULL /* set_property */
1030 /* Runs in thread we created GDBusServer in (since we didn't pass G_DBUS_SERVER_FLAGS_RUN_IN_THREAD) */
1031 static gboolean
1032 dmp_on_new_connection (GDBusServer *server,
1033 GDBusConnection *connection,
1034 gpointer user_data)
1036 DmpData *data = user_data;
1037 GDBusNodeInfo *node;
1038 GError *error;
1040 /* accept the connection */
1041 data->connections = g_list_prepend (data->connections, g_object_ref (connection));
1043 error = NULL;
1044 node = g_dbus_node_info_new_for_xml ("<node>"
1045 " <interface name='org.gtk.GDBus.DmpInterface'>"
1046 " <method name='AddPair'>"
1047 " <arg type='i' name='first' direction='in'/>"
1048 " <arg type='i' name='second' direction='in'/>"
1049 " <arg type='i' name='sum' direction='out'/>"
1050 " </method>"
1051 " </interface>"
1052 "</node>",
1053 &error);
1054 g_assert_no_error (error);
1056 /* sleep 100ms before exporting an object - this is to test that
1057 * G_DBUS_CONNECTION_FLAGS_DELAY_MESSAGE_PROCESSING really works
1058 * (GDBusServer uses this feature).
1060 usleep (100 * 1000);
1062 /* export an object */
1063 error = NULL;
1064 g_dbus_connection_register_object (connection,
1065 "/dmp/test",
1066 node->interfaces[0],
1067 &dmp_interface_vtable,
1068 data,
1069 NULL,
1070 &error);
1071 g_dbus_node_info_unref (node);
1073 return TRUE;
1076 static gpointer
1077 dmp_thread_func (gpointer user_data)
1079 DmpData *data = user_data;
1080 GError *error;
1081 gchar *guid;
1083 data->context = g_main_context_new ();
1084 g_main_context_push_thread_default (data->context);
1086 error = NULL;
1087 guid = g_dbus_generate_guid ();
1088 data->server = g_dbus_server_new_sync (tmp_address,
1089 G_DBUS_SERVER_FLAGS_NONE,
1090 guid,
1091 NULL, /* GDBusAuthObserver */
1092 NULL, /* GCancellable */
1093 &error);
1094 g_assert_no_error (error);
1095 g_signal_connect (data->server,
1096 "new-connection",
1097 G_CALLBACK (dmp_on_new_connection),
1098 data);
1100 g_dbus_server_start (data->server);
1102 data->loop = g_main_loop_new (data->context, FALSE);
1103 g_main_loop_run (data->loop);
1105 g_main_context_pop_thread_default (data->context);
1107 g_free (guid);
1108 return NULL;
1111 static void
1112 delayed_message_processing (void)
1114 GError *error;
1115 DmpData *data;
1116 GThread *service_thread;
1117 guint n;
1119 data = g_new0 (DmpData, 1);
1121 service_thread = g_thread_new ("dmp",
1122 dmp_thread_func,
1123 data);
1124 while (data->server == NULL || !g_dbus_server_is_active (data->server))
1125 g_thread_yield ();
1127 for (n = 0; n < 5; n++)
1129 GDBusConnection *c;
1130 GVariant *res;
1131 gint32 val;
1133 error = NULL;
1134 c = g_dbus_connection_new_for_address_sync (g_dbus_server_get_client_address (data->server),
1135 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
1136 NULL, /* GDBusAuthObserver */
1137 NULL, /* GCancellable */
1138 &error);
1139 g_assert_no_error (error);
1141 error = NULL;
1142 res = g_dbus_connection_call_sync (c,
1143 NULL, /* bus name */
1144 "/dmp/test",
1145 "org.gtk.GDBus.DmpInterface",
1146 "AddPair",
1147 g_variant_new ("(ii)", 2, n),
1148 G_VARIANT_TYPE ("(i)"),
1149 G_DBUS_CALL_FLAGS_NONE,
1150 -1, /* timeout_msec */
1151 NULL, /* GCancellable */
1152 &error);
1153 g_assert_no_error (error);
1154 g_variant_get (res, "(i)", &val);
1155 g_assert_cmpint (val, ==, 2 + n);
1156 g_variant_unref (res);
1157 g_object_unref (c);
1160 g_main_loop_quit (data->loop);
1161 g_thread_join (service_thread);
1162 dmp_data_free (data);
1165 /* ---------------------------------------------------------------------------------------------------- */
1167 static gboolean
1168 nonce_tcp_on_authorize_authenticated_peer (GDBusAuthObserver *observer,
1169 GIOStream *stream,
1170 GCredentials *credentials,
1171 gpointer user_data)
1173 PeerData *data = user_data;
1174 gboolean authorized;
1176 data->num_connection_attempts++;
1178 authorized = TRUE;
1179 if (!data->accept_connection)
1181 authorized = FALSE;
1182 g_main_loop_quit (loop);
1185 return authorized;
1188 /* Runs in thread we created GDBusServer in (since we didn't pass G_DBUS_SERVER_FLAGS_RUN_IN_THREAD) */
1189 static gboolean
1190 nonce_tcp_on_new_connection (GDBusServer *server,
1191 GDBusConnection *connection,
1192 gpointer user_data)
1194 PeerData *data = user_data;
1196 g_ptr_array_add (data->current_connections, g_object_ref (connection));
1198 g_main_loop_quit (loop);
1200 return TRUE;
1203 static gpointer
1204 nonce_tcp_service_thread_func (gpointer user_data)
1206 PeerData *data = user_data;
1207 GMainContext *service_context;
1208 GDBusAuthObserver *observer;
1209 GError *error;
1211 service_context = g_main_context_new ();
1212 g_main_context_push_thread_default (service_context);
1214 error = NULL;
1215 observer = g_dbus_auth_observer_new ();
1216 server = g_dbus_server_new_sync ("nonce-tcp:",
1217 G_DBUS_SERVER_FLAGS_NONE,
1218 test_guid,
1219 observer,
1220 NULL, /* cancellable */
1221 &error);
1222 g_assert_no_error (error);
1224 g_signal_connect (server,
1225 "new-connection",
1226 G_CALLBACK (nonce_tcp_on_new_connection),
1227 data);
1228 g_signal_connect (observer,
1229 "authorize-authenticated-peer",
1230 G_CALLBACK (nonce_tcp_on_authorize_authenticated_peer),
1231 data);
1232 g_object_unref (observer);
1234 g_dbus_server_start (server);
1236 run_service_loop (service_context);
1238 g_main_context_pop_thread_default (service_context);
1240 teardown_service_loop ();
1241 g_main_context_unref (service_context);
1243 /* test code specifically unrefs the server - see below */
1244 g_assert (server == NULL);
1246 return NULL;
1249 static void
1250 test_nonce_tcp (void)
1252 PeerData data;
1253 GError *error;
1254 GThread *service_thread;
1255 GDBusConnection *c;
1256 gchar *s;
1257 gchar *nonce_file;
1258 gboolean res;
1259 const gchar *address;
1261 memset (&data, '\0', sizeof (PeerData));
1262 data.current_connections = g_ptr_array_new_with_free_func (g_object_unref);
1264 error = NULL;
1265 server = NULL;
1266 service_thread = g_thread_new ("nonce-tcp-service",
1267 nonce_tcp_service_thread_func,
1268 &data);
1269 await_service_loop ();
1270 g_assert (server != NULL);
1272 /* bring up a connection and accept it */
1273 data.accept_connection = TRUE;
1274 error = NULL;
1275 c = g_dbus_connection_new_for_address_sync (g_dbus_server_get_client_address (server),
1276 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
1277 NULL, /* GDBusAuthObserver */
1278 NULL, /* cancellable */
1279 &error);
1280 g_assert_no_error (error);
1281 g_assert (c != NULL);
1282 while (data.current_connections->len < 1)
1283 g_thread_yield ();
1284 g_assert_cmpint (data.current_connections->len, ==, 1);
1285 g_assert_cmpint (data.num_connection_attempts, ==, 1);
1286 g_assert (g_dbus_connection_get_unique_name (c) == NULL);
1287 g_assert_cmpstr (g_dbus_connection_get_guid (c), ==, test_guid);
1288 g_object_unref (c);
1290 /* now, try to subvert the nonce file (this assumes noncefile is the last key/value pair)
1293 address = g_dbus_server_get_client_address (server);
1295 s = strstr (address, "noncefile=");
1296 g_assert (s != NULL);
1297 s += sizeof "noncefile=" - 1;
1298 nonce_file = g_strdup (s);
1300 /* First try invalid data in the nonce file - this will actually
1301 * make the client send this and the server will reject it. The way
1302 * it works is that if the nonce doesn't match, the server will
1303 * simply close the connection. So, from the client point of view,
1304 * we can see a variety of errors.
1306 error = NULL;
1307 res = g_file_set_contents (nonce_file,
1308 "0123456789012345",
1310 &error);
1311 g_assert_no_error (error);
1312 g_assert (res);
1313 c = g_dbus_connection_new_for_address_sync (address,
1314 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
1315 NULL, /* GDBusAuthObserver */
1316 NULL, /* cancellable */
1317 &error);
1318 _g_assert_error_domain (error, G_IO_ERROR);
1319 g_error_free (error);
1320 g_assert (c == NULL);
1322 /* Then try with a nonce-file of incorrect length - this will make
1323 * the client complain - we won't even try connecting to the server
1324 * for this
1326 error = NULL;
1327 res = g_file_set_contents (nonce_file,
1328 "0123456789012345_",
1330 &error);
1331 g_assert_no_error (error);
1332 g_assert (res);
1333 c = g_dbus_connection_new_for_address_sync (address,
1334 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
1335 NULL, /* GDBusAuthObserver */
1336 NULL, /* cancellable */
1337 &error);
1338 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1339 g_error_free (error);
1340 g_assert (c == NULL);
1342 /* Finally try with no nonce-file at all */
1343 g_assert_cmpint (g_unlink (nonce_file), ==, 0);
1344 error = NULL;
1345 c = g_dbus_connection_new_for_address_sync (address,
1346 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
1347 NULL, /* GDBusAuthObserver */
1348 NULL, /* cancellable */
1349 &error);
1350 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1351 g_error_free (error);
1352 g_assert (c == NULL);
1354 g_free (nonce_file);
1356 g_dbus_server_stop (server);
1357 g_object_unref (server);
1358 server = NULL;
1360 g_main_loop_quit (service_loop);
1361 g_thread_join (service_thread);
1363 g_ptr_array_unref (data.current_connections);
1366 static void
1367 test_credentials (void)
1369 GCredentials *c1, *c2;
1370 GError *error;
1371 gchar *desc;
1373 c1 = g_credentials_new ();
1374 c2 = g_credentials_new ();
1376 error = NULL;
1377 if (g_credentials_set_unix_user (c2, getuid (), &error))
1378 g_assert_no_error (error);
1380 g_clear_error (&error);
1381 g_assert (g_credentials_is_same_user (c1, c2, &error));
1382 g_assert_no_error (error);
1384 desc = g_credentials_to_string (c1);
1385 g_assert (desc != NULL);
1386 g_free (desc);
1388 g_object_unref (c1);
1389 g_object_unref (c2);
1392 /* ---------------------------------------------------------------------------------------------------- */
1394 static gboolean
1395 tcp_anonymous_on_new_connection (GDBusServer *server,
1396 GDBusConnection *connection,
1397 gpointer user_data)
1399 gboolean *seen_connection = user_data;
1400 *seen_connection = TRUE;
1401 return TRUE;
1404 static gpointer
1405 tcp_anonymous_service_thread_func (gpointer user_data)
1407 gboolean *seen_connection = user_data;
1408 GMainContext *service_context;
1409 GError *error;
1411 service_context = g_main_context_new ();
1412 g_main_context_push_thread_default (service_context);
1414 error = NULL;
1415 server = g_dbus_server_new_sync ("tcp:",
1416 G_DBUS_SERVER_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS,
1417 test_guid,
1418 NULL, /* GDBusObserver* */
1419 NULL, /* GCancellable* */
1420 &error);
1421 g_assert_no_error (error);
1423 g_signal_connect (server,
1424 "new-connection",
1425 G_CALLBACK (tcp_anonymous_on_new_connection),
1426 seen_connection);
1428 g_dbus_server_start (server);
1430 run_service_loop (service_context);
1432 g_main_context_pop_thread_default (service_context);
1434 teardown_service_loop ();
1435 g_main_context_unref (service_context);
1437 return NULL;
1440 static void
1441 test_tcp_anonymous (void)
1443 gboolean seen_connection;
1444 GThread *service_thread;
1445 GDBusConnection *connection;
1446 GError *error;
1448 seen_connection = FALSE;
1449 service_thread = g_thread_new ("tcp-anon-service",
1450 tcp_anonymous_service_thread_func,
1451 &seen_connection);
1452 await_service_loop ();
1453 g_assert (server != NULL);
1455 error = NULL;
1456 connection = g_dbus_connection_new_for_address_sync (g_dbus_server_get_client_address (server),
1457 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
1458 NULL, /* GDBusAuthObserver* */
1459 NULL, /* GCancellable */
1460 &error);
1461 g_assert_no_error (error);
1462 g_assert (connection != NULL);
1464 while (!seen_connection)
1465 g_thread_yield ();
1467 g_object_unref (connection);
1469 g_main_loop_quit (service_loop);
1470 g_dbus_server_stop (server);
1471 g_object_unref (server);
1472 server = NULL;
1474 g_thread_join (service_thread);
1477 /* ---------------------------------------------------------------------------------------------------- */
1479 static GDBusServer *codegen_server = NULL;
1481 static gboolean
1482 codegen_on_animal_poke (ExampleAnimal *animal,
1483 GDBusMethodInvocation *invocation,
1484 gboolean make_sad,
1485 gboolean make_happy,
1486 gpointer user_data)
1488 if ((make_sad && make_happy) || (!make_sad && !make_happy))
1490 g_main_loop_quit (service_loop);
1492 g_dbus_method_invocation_return_dbus_error (invocation,
1493 "org.gtk.GDBus.Examples.ObjectManager.Error.Failed",
1494 "Exactly one of make_sad or make_happy must be TRUE");
1495 goto out;
1498 if (make_sad)
1500 if (g_strcmp0 (example_animal_get_mood (animal), "Sad") == 0)
1502 g_dbus_method_invocation_return_dbus_error (invocation,
1503 "org.gtk.GDBus.Examples.ObjectManager.Error.SadAnimalIsSad",
1504 "Sad animal is already sad");
1505 goto out;
1508 example_animal_set_mood (animal, "Sad");
1509 example_animal_complete_poke (animal, invocation);
1510 goto out;
1513 if (make_happy)
1515 if (g_strcmp0 (example_animal_get_mood (animal), "Happy") == 0)
1517 g_dbus_method_invocation_return_dbus_error (invocation,
1518 "org.gtk.GDBus.Examples.ObjectManager.Error.HappyAnimalIsHappy",
1519 "Happy animal is already happy");
1520 goto out;
1523 example_animal_set_mood (animal, "Happy");
1524 example_animal_complete_poke (animal, invocation);
1525 goto out;
1528 g_assert_not_reached ();
1530 out:
1531 return TRUE; /* to indicate that the method was handled */
1534 /* Runs in thread we created GDBusServer in (since we didn't pass G_DBUS_SERVER_FLAGS_RUN_IN_THREAD) */
1535 static gboolean
1536 codegen_on_new_connection (GDBusServer *server,
1537 GDBusConnection *connection,
1538 gpointer user_data)
1540 ExampleAnimal *animal = user_data;
1541 GError *error = NULL;
1543 /* g_printerr ("Client connected.\n" */
1544 /* "Negotiated capabilities: unix-fd-passing=%d\n", */
1545 /* g_dbus_connection_get_capabilities (connection) & G_DBUS_CAPABILITY_FLAGS_UNIX_FD_PASSING); */
1547 g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (animal), connection,
1548 "/Example/Animals/000", &error);
1549 g_assert_no_error (error);
1551 return TRUE;
1554 static gpointer
1555 codegen_service_thread_func (gpointer user_data)
1557 GMainContext *service_context;
1558 ExampleAnimal *animal;
1559 GError *error = NULL;
1561 service_context = g_main_context_new ();
1562 g_main_context_push_thread_default (service_context);
1564 /* Create the animal in the right thread context */
1565 animal = example_animal_skeleton_new ();
1567 /* Handle Poke() D-Bus method invocations on the .Animal interface */
1568 g_signal_connect (animal, "handle-poke",
1569 G_CALLBACK (codegen_on_animal_poke),
1570 NULL); /* user_data */
1572 codegen_server = g_dbus_server_new_sync (tmp_address,
1573 G_DBUS_SERVER_FLAGS_NONE,
1574 test_guid,
1575 NULL, /* observer */
1576 NULL, /* cancellable */
1577 &error);
1578 g_assert_no_error (error);
1579 g_dbus_server_start (codegen_server);
1581 g_signal_connect (codegen_server, "new-connection",
1582 G_CALLBACK (codegen_on_new_connection),
1583 animal);
1585 run_service_loop (service_context);
1587 g_object_unref (animal);
1589 g_main_context_pop_thread_default (service_context);
1591 teardown_service_loop ();
1592 g_main_context_unref (service_context);
1594 g_dbus_server_stop (codegen_server);
1595 g_object_unref (codegen_server);
1596 codegen_server = NULL;
1598 return NULL;
1602 static gboolean
1603 codegen_quit_mainloop_timeout (gpointer data)
1605 g_main_loop_quit (loop);
1606 return FALSE;
1609 static void
1610 codegen_test_peer (void)
1612 GDBusConnection *connection;
1613 ExampleAnimal *animal1, *animal2;
1614 GThread *service_thread;
1615 GError *error = NULL;
1616 GVariant *value;
1617 const gchar *s;
1619 /* bring up a server - we run the server in a different thread to avoid deadlocks */
1620 service_thread = g_thread_new ("codegen_test_peer",
1621 codegen_service_thread_func,
1622 NULL);
1623 await_service_loop ();
1624 g_assert (codegen_server != NULL);
1626 /* Get an animal 1 ... */
1627 connection = g_dbus_connection_new_for_address_sync (g_dbus_server_get_client_address (codegen_server),
1628 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
1629 NULL, /* GDBusAuthObserver */
1630 NULL, /* cancellable */
1631 &error);
1632 g_assert_no_error (error);
1633 g_assert (connection != NULL);
1635 animal1 = example_animal_proxy_new_sync (connection, 0, NULL,
1636 "/Example/Animals/000", NULL, &error);
1637 g_assert_no_error (error);
1638 g_assert (animal1 != NULL);
1639 g_object_unref (connection);
1641 /* Get animal 2 ... */
1642 connection = g_dbus_connection_new_for_address_sync (g_dbus_server_get_client_address (codegen_server),
1643 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
1644 NULL, /* GDBusAuthObserver */
1645 NULL, /* cancellable */
1646 &error);
1647 g_assert_no_error (error);
1648 g_assert (connection != NULL);
1650 animal2 = example_animal_proxy_new_sync (connection, 0, NULL,
1651 "/Example/Animals/000", NULL, &error);
1652 g_assert_no_error (error);
1653 g_assert (animal2 != NULL);
1654 g_object_unref (connection);
1656 /* Make animal sad via animal1 */
1657 example_animal_call_poke_sync (animal1, TRUE, FALSE, NULL, &error);
1658 g_assert_no_error (error);
1660 /* Poke server and make sure animal is updated */
1661 value = g_dbus_proxy_call_sync (G_DBUS_PROXY (animal1),
1662 "org.freedesktop.DBus.Peer.Ping",
1663 NULL, G_DBUS_CALL_FLAGS_NONE, -1,
1664 NULL, &error);
1665 g_assert_no_error (error);
1666 g_assert (value != NULL);
1667 g_variant_unref (value);
1669 /* Give the proxies a chance to refresh in the defaul main loop */
1670 g_timeout_add (100, codegen_quit_mainloop_timeout, NULL);
1671 g_main_loop_run (loop);
1673 /* Assert animals are sad */
1674 g_assert_cmpstr (example_animal_get_mood (animal1), ==, "Sad");
1675 g_assert_cmpstr (example_animal_get_mood (animal2), ==, "Sad");
1677 /* Make animal happy via animal2 */
1678 example_animal_call_poke_sync (animal2, FALSE, TRUE, NULL, &error);
1679 g_assert_no_error (error);
1681 /* Some random unrelated call, just to get some test coverage */
1682 value = g_dbus_proxy_call_sync (G_DBUS_PROXY (animal2),
1683 "org.freedesktop.DBus.Peer.GetMachineId",
1684 NULL, G_DBUS_CALL_FLAGS_NONE, -1,
1685 NULL, &error);
1686 g_assert_no_error (error);
1687 g_variant_get (value, "(&s)", &s);
1688 g_test_message ("Machine ID: %s", s);
1689 /* It's valid for machine-id inside containers to be empty, so we
1690 * need to test for that possibility
1692 g_assert ((s == NULL || *s == '\0') || g_dbus_is_guid (s));
1693 g_variant_unref (value);
1695 /* Poke server and make sure animal is updated */
1696 value = g_dbus_proxy_call_sync (G_DBUS_PROXY (animal2),
1697 "org.freedesktop.DBus.Peer.Ping",
1698 NULL, G_DBUS_CALL_FLAGS_NONE, -1,
1699 NULL, &error);
1700 g_assert_no_error (error);
1701 g_assert (value != NULL);
1702 g_variant_unref (value);
1704 /* Give the proxies a chance to refresh in the defaul main loop */
1705 g_timeout_add (1000, codegen_quit_mainloop_timeout, NULL);
1706 g_main_loop_run (loop);
1708 /* Assert animals are happy */
1709 g_assert_cmpstr (example_animal_get_mood (animal1), ==, "Happy");
1710 g_assert_cmpstr (example_animal_get_mood (animal2), ==, "Happy");
1712 /* This final call making the animal happy and sad will cause
1713 * the server to quit, when the server quits we dont get property
1714 * change notifications anyway because those are done from an idle handler
1716 example_animal_call_poke_sync (animal2, TRUE, TRUE, NULL, &error);
1717 g_clear_error (&error);
1719 g_object_unref (animal1);
1720 g_object_unref (animal2);
1721 g_thread_join (service_thread);
1724 /* ---------------------------------------------------------------------------------------------------- */
1728 main (int argc,
1729 char *argv[])
1731 gint ret;
1732 GDBusNodeInfo *introspection_data = NULL;
1733 gchar *tmpdir = NULL;
1735 g_test_init (&argc, &argv, NULL);
1737 introspection_data = g_dbus_node_info_new_for_xml (test_interface_introspection_xml, NULL);
1738 g_assert (introspection_data != NULL);
1739 test_interface_introspection_data = introspection_data->interfaces[0];
1741 test_guid = g_dbus_generate_guid ();
1743 if (is_unix)
1745 if (g_unix_socket_address_abstract_names_supported ())
1746 tmp_address = g_strdup ("unix:tmpdir=/tmp/gdbus-test-");
1747 else
1749 tmpdir = g_dir_make_tmp ("gdbus-test-XXXXXX", NULL);
1750 tmp_address = g_strdup_printf ("unix:tmpdir=%s", tmpdir);
1753 else
1754 tmp_address = g_strdup ("nonce-tcp:");
1756 /* all the tests rely on a shared main loop */
1757 loop = g_main_loop_new (NULL, FALSE);
1759 g_test_add_func ("/gdbus/peer-to-peer", test_peer);
1760 g_test_add_func ("/gdbus/delayed-message-processing", delayed_message_processing);
1761 g_test_add_func ("/gdbus/nonce-tcp", test_nonce_tcp);
1763 g_test_add_func ("/gdbus/tcp-anonymous", test_tcp_anonymous);
1764 g_test_add_func ("/gdbus/credentials", test_credentials);
1765 g_test_add_func ("/gdbus/codegen-peer-to-peer", codegen_test_peer);
1767 ret = g_test_run();
1769 g_main_loop_unref (loop);
1770 g_free (test_guid);
1771 g_dbus_node_info_unref (introspection_data);
1772 if (is_unix)
1773 g_free (tmp_address);
1774 if (tmpdir)
1776 g_rmdir (tmpdir);
1777 g_free (tmpdir);
1780 return ret;