GSettings: small internal refactor
[glib.git] / gio / tests / gdbus-peer.c
blobf0e93b4d70d0e252866253dd03cb355bc0ad295e
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 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, write to the
17 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18 * Boston, MA 02111-1307, USA.
20 * Author: David Zeuthen <davidz@redhat.com>
23 #include "config.h"
25 #include <gio/gio.h>
26 #include <unistd.h>
27 #include <string.h>
29 /* for open(2) */
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <fcntl.h>
33 #include <string.h>
35 /* for g_unlink() */
36 #include <glib/gstdio.h>
38 #include <gio/gnetworking.h>
39 #include <gio/gunixsocketaddress.h>
40 #include <gio/gunixfdlist.h>
41 #include <gio/gcredentialsprivate.h>
43 #ifdef G_OS_UNIX
44 #include <gio/gunixconnection.h>
45 #include <errno.h>
46 #endif
48 #include "gdbus-tests.h"
50 #include "gdbus-object-manager-example/gdbus-example-objectmanager-generated.h"
52 #ifdef G_OS_UNIX
53 static gboolean is_unix = TRUE;
54 #else
55 static gboolean is_unix = FALSE;
56 #endif
58 static gchar *tmp_address = NULL;
59 static gchar *test_guid = NULL;
60 static GMutex service_loop_lock;
61 static GCond service_loop_cond;
62 static GMainLoop *service_loop = NULL;
63 static GDBusServer *server = NULL;
64 static GMainLoop *loop = NULL;
66 /* ---------------------------------------------------------------------------------------------------- */
67 /* Test that peer-to-peer connections work */
68 /* ---------------------------------------------------------------------------------------------------- */
71 typedef struct
73 gboolean accept_connection;
74 gint num_connection_attempts;
75 GPtrArray *current_connections;
76 guint num_method_calls;
77 gboolean signal_received;
78 } PeerData;
80 static const gchar *test_interface_introspection_xml =
81 "<node>"
82 " <interface name='org.gtk.GDBus.PeerTestInterface'>"
83 " <method name='HelloPeer'>"
84 " <arg type='s' name='greeting' direction='in'/>"
85 " <arg type='s' name='response' direction='out'/>"
86 " </method>"
87 " <method name='EmitSignal'/>"
88 " <method name='EmitSignalWithNameSet'/>"
89 " <method name='OpenFile'>"
90 " <arg type='s' name='path' direction='in'/>"
91 " </method>"
92 " <signal name='PeerSignal'>"
93 " <arg type='s' name='a_string'/>"
94 " </signal>"
95 " <property type='s' name='PeerProperty' access='read'/>"
96 " </interface>"
97 "</node>";
98 static GDBusInterfaceInfo *test_interface_introspection_data = NULL;
100 static void
101 test_interface_method_call (GDBusConnection *connection,
102 const gchar *sender,
103 const gchar *object_path,
104 const gchar *interface_name,
105 const gchar *method_name,
106 GVariant *parameters,
107 GDBusMethodInvocation *invocation,
108 gpointer user_data)
110 PeerData *data = user_data;
111 const GDBusMethodInfo *info;
113 data->num_method_calls++;
115 g_assert_cmpstr (object_path, ==, "/org/gtk/GDBus/PeerTestObject");
116 g_assert_cmpstr (interface_name, ==, "org.gtk.GDBus.PeerTestInterface");
118 info = g_dbus_method_invocation_get_method_info (invocation);
119 g_assert_cmpstr (info->name, ==, method_name);
121 if (g_strcmp0 (method_name, "HelloPeer") == 0)
123 const gchar *greeting;
124 gchar *response;
126 g_variant_get (parameters, "(&s)", &greeting);
128 response = g_strdup_printf ("You greeted me with '%s'.",
129 greeting);
130 g_dbus_method_invocation_return_value (invocation,
131 g_variant_new ("(s)", response));
132 g_free (response);
134 else if (g_strcmp0 (method_name, "EmitSignal") == 0)
136 GError *error;
138 error = NULL;
139 g_dbus_connection_emit_signal (connection,
140 NULL,
141 "/org/gtk/GDBus/PeerTestObject",
142 "org.gtk.GDBus.PeerTestInterface",
143 "PeerSignal",
144 NULL,
145 &error);
146 g_assert_no_error (error);
147 g_dbus_method_invocation_return_value (invocation, NULL);
149 else if (g_strcmp0 (method_name, "EmitSignalWithNameSet") == 0)
151 GError *error;
152 gboolean ret;
153 GDBusMessage *message;
155 message = g_dbus_message_new_signal ("/org/gtk/GDBus/PeerTestObject",
156 "org.gtk.GDBus.PeerTestInterface",
157 "PeerSignalWithNameSet");
158 g_dbus_message_set_sender (message, ":1.42");
160 error = NULL;
161 ret = g_dbus_connection_send_message (connection, message, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, &error);
162 g_assert_no_error (error);
163 g_assert (ret);
164 g_object_unref (message);
166 g_dbus_method_invocation_return_value (invocation, NULL);
168 else if (g_strcmp0 (method_name, "OpenFile") == 0)
170 #ifdef G_OS_UNIX
171 const gchar *path;
172 GDBusMessage *reply;
173 GError *error;
174 gint fd;
175 GUnixFDList *fd_list;
177 g_variant_get (parameters, "(&s)", &path);
179 fd_list = g_unix_fd_list_new ();
181 error = NULL;
183 fd = g_open (path, O_RDONLY, 0);
184 g_assert (fd != -1);
185 g_unix_fd_list_append (fd_list, fd, &error);
186 g_assert_no_error (error);
187 close (fd);
189 reply = g_dbus_message_new_method_reply (g_dbus_method_invocation_get_message (invocation));
190 g_dbus_message_set_unix_fd_list (reply, fd_list);
191 g_object_unref (fd_list);
192 g_object_unref (invocation);
194 error = NULL;
195 g_dbus_connection_send_message (connection,
196 reply,
197 G_DBUS_SEND_MESSAGE_FLAGS_NONE,
198 NULL, /* out_serial */
199 &error);
200 g_assert_no_error (error);
201 g_object_unref (reply);
202 #else
203 g_dbus_method_invocation_return_dbus_error (invocation,
204 "org.gtk.GDBus.NotOnUnix",
205 "Your OS does not support file descriptor passing");
206 #endif
208 else
210 g_assert_not_reached ();
214 static GVariant *
215 test_interface_get_property (GDBusConnection *connection,
216 const gchar *sender,
217 const gchar *object_path,
218 const gchar *interface_name,
219 const gchar *property_name,
220 GError **error,
221 gpointer user_data)
223 g_assert_cmpstr (object_path, ==, "/org/gtk/GDBus/PeerTestObject");
224 g_assert_cmpstr (interface_name, ==, "org.gtk.GDBus.PeerTestInterface");
225 g_assert_cmpstr (property_name, ==, "PeerProperty");
227 return g_variant_new_string ("ThePropertyValue");
231 static const GDBusInterfaceVTable test_interface_vtable =
233 test_interface_method_call,
234 test_interface_get_property,
235 NULL /* set_property */
238 static void
239 on_proxy_signal_received (GDBusProxy *proxy,
240 gchar *sender_name,
241 gchar *signal_name,
242 GVariant *parameters,
243 gpointer user_data)
245 PeerData *data = user_data;
247 data->signal_received = TRUE;
249 g_assert (sender_name == NULL);
250 g_assert_cmpstr (signal_name, ==, "PeerSignal");
251 g_main_loop_quit (loop);
254 static void
255 on_proxy_signal_received_with_name_set (GDBusProxy *proxy,
256 gchar *sender_name,
257 gchar *signal_name,
258 GVariant *parameters,
259 gpointer user_data)
261 PeerData *data = user_data;
263 data->signal_received = TRUE;
265 g_assert_cmpstr (sender_name, ==, ":1.42");
266 g_assert_cmpstr (signal_name, ==, "PeerSignalWithNameSet");
267 g_main_loop_quit (loop);
270 /* ---------------------------------------------------------------------------------------------------- */
272 static gboolean
273 on_authorize_authenticated_peer (GDBusAuthObserver *observer,
274 GIOStream *stream,
275 GCredentials *credentials,
276 gpointer user_data)
278 PeerData *data = user_data;
279 gboolean authorized;
281 data->num_connection_attempts++;
283 authorized = TRUE;
284 if (!data->accept_connection)
286 authorized = FALSE;
287 g_main_loop_quit (loop);
290 return authorized;
293 /* Runs in thread we created GDBusServer in (since we didn't pass G_DBUS_SERVER_FLAGS_RUN_IN_THREAD) */
294 static gboolean
295 on_new_connection (GDBusServer *server,
296 GDBusConnection *connection,
297 gpointer user_data)
299 PeerData *data = user_data;
300 GError *error;
301 guint reg_id;
303 //g_print ("Client connected.\n"
304 // "Negotiated capabilities: unix-fd-passing=%d\n",
305 // g_dbus_connection_get_capabilities (connection) & G_DBUS_CAPABILITY_FLAGS_UNIX_FD_PASSING);
307 g_ptr_array_add (data->current_connections, g_object_ref (connection));
309 #if G_CREDENTIALS_SUPPORTED
311 GCredentials *credentials;
313 credentials = g_dbus_connection_get_peer_credentials (connection);
315 g_assert (credentials != NULL);
316 g_assert_cmpuint (g_credentials_get_unix_user (credentials, NULL), ==,
317 getuid ());
318 g_assert_cmpuint (g_credentials_get_unix_pid (credentials, NULL), ==,
319 getpid ());
321 #endif
323 /* export object on the newly established connection */
324 error = NULL;
325 reg_id = g_dbus_connection_register_object (connection,
326 "/org/gtk/GDBus/PeerTestObject",
327 test_interface_introspection_data,
328 &test_interface_vtable,
329 data,
330 NULL, /* GDestroyNotify for data */
331 &error);
332 g_assert_no_error (error);
333 g_assert (reg_id > 0);
335 g_main_loop_quit (loop);
337 return TRUE;
340 static void
341 create_service_loop (GMainContext *service_context)
343 g_assert (service_loop == NULL);
344 g_mutex_lock (&service_loop_lock);
345 service_loop = g_main_loop_new (service_context, FALSE);
346 g_cond_broadcast (&service_loop_cond);
347 g_mutex_unlock (&service_loop_lock);
350 static void
351 teardown_service_loop (void)
353 g_mutex_lock (&service_loop_lock);
354 g_clear_pointer (&service_loop, g_main_loop_unref);
355 g_mutex_unlock (&service_loop_lock);
358 static void
359 await_service_loop (void)
361 g_mutex_lock (&service_loop_lock);
362 while (service_loop == NULL)
363 g_cond_wait (&service_loop_cond, &service_loop_lock);
364 g_mutex_unlock (&service_loop_lock);
367 static gpointer
368 service_thread_func (gpointer user_data)
370 PeerData *data = user_data;
371 GMainContext *service_context;
372 GDBusAuthObserver *observer, *o;
373 GError *error;
374 GDBusServerFlags f;
375 gchar *a, *g;
376 gboolean b;
378 service_context = g_main_context_new ();
379 g_main_context_push_thread_default (service_context);
381 error = NULL;
382 observer = g_dbus_auth_observer_new ();
383 server = g_dbus_server_new_sync (tmp_address,
384 G_DBUS_SERVER_FLAGS_NONE,
385 test_guid,
386 observer,
387 NULL, /* cancellable */
388 &error);
389 g_assert_no_error (error);
391 g_signal_connect (server,
392 "new-connection",
393 G_CALLBACK (on_new_connection),
394 data);
395 g_signal_connect (observer,
396 "authorize-authenticated-peer",
397 G_CALLBACK (on_authorize_authenticated_peer),
398 data);
400 g_assert_cmpint (g_dbus_server_get_flags (server), ==, G_DBUS_SERVER_FLAGS_NONE);
401 g_assert_cmpstr (g_dbus_server_get_guid (server), ==, test_guid);
402 g_object_get (server,
403 "flags", &f,
404 "address", &a,
405 "guid", &g,
406 "active", &b,
407 "authentication-observer", &o,
408 NULL);
409 g_assert_cmpint (f, ==, G_DBUS_SERVER_FLAGS_NONE);
410 g_assert_cmpstr (a, ==, tmp_address);
411 g_assert_cmpstr (g, ==, test_guid);
412 g_assert (!b);
413 g_assert (o == observer);
414 g_free (a);
415 g_free (g);
416 g_object_unref (o);
418 g_object_unref (observer);
420 g_dbus_server_start (server);
422 create_service_loop (service_context);
423 g_main_loop_run (service_loop);
425 g_main_context_pop_thread_default (service_context);
427 teardown_service_loop ();
428 g_main_context_unref (service_context);
430 /* test code specifically unrefs the server - see below */
431 g_assert (server == NULL);
433 return NULL;
436 #if 0
437 static gboolean
438 on_incoming_connection (GSocketService *service,
439 GSocketConnection *socket_connection,
440 GObject *source_object,
441 gpointer user_data)
443 PeerData *data = user_data;
445 if (data->accept_connection)
447 GError *error;
448 guint reg_id;
449 GDBusConnection *connection;
451 error = NULL;
452 connection = g_dbus_connection_new_sync (G_IO_STREAM (socket_connection),
453 test_guid,
454 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER,
455 NULL, /* cancellable */
456 &error);
457 g_assert_no_error (error);
459 g_ptr_array_add (data->current_connections, connection);
461 /* export object on the newly established connection */
462 error = NULL;
463 reg_id = g_dbus_connection_register_object (connection,
464 "/org/gtk/GDBus/PeerTestObject",
465 &test_interface_introspection_data,
466 &test_interface_vtable,
467 data,
468 NULL, /* GDestroyNotify for data */
469 &error);
470 g_assert_no_error (error);
471 g_assert (reg_id > 0);
474 else
476 /* don't do anything */
479 data->num_connection_attempts++;
481 g_main_loop_quit (loop);
483 /* stops other signal handlers from being invoked */
484 return TRUE;
487 static gpointer
488 service_thread_func (gpointer data)
490 GMainContext *service_context;
491 gchar *socket_path;
492 GSocketAddress *address;
493 GError *error;
495 service_context = g_main_context_new ();
496 g_main_context_push_thread_default (service_context);
498 socket_path = g_strdup_printf ("/tmp/gdbus-test-pid-%d", getpid ());
499 address = g_unix_socket_address_new (socket_path);
501 service = g_socket_service_new ();
502 error = NULL;
503 g_socket_listener_add_address (G_SOCKET_LISTENER (service),
504 address,
505 G_SOCKET_TYPE_STREAM,
506 G_SOCKET_PROTOCOL_DEFAULT,
507 NULL, /* source_object */
508 NULL, /* effective_address */
509 &error);
510 g_assert_no_error (error);
511 g_signal_connect (service,
512 "incoming",
513 G_CALLBACK (on_incoming_connection),
514 data);
515 g_socket_service_start (service);
517 create_service_loop (service_context);
518 g_main_loop_run (service_loop);
520 g_main_context_pop_thread_default (service_context);
522 teardown_service_loop ();
523 g_main_context_unref (service_context);
525 g_object_unref (address);
526 g_free (socket_path);
527 return NULL;
529 #endif
531 /* ---------------------------------------------------------------------------------------------------- */
533 #if 0
534 static gboolean
535 check_connection (gpointer user_data)
537 PeerData *data = user_data;
538 guint n;
540 for (n = 0; n < data->current_connections->len; n++)
542 GDBusConnection *c;
543 GIOStream *stream;
545 c = G_DBUS_CONNECTION (data->current_connections->pdata[n]);
546 stream = g_dbus_connection_get_stream (c);
548 g_debug ("In check_connection for %d: connection %p, stream %p", n, c, stream);
549 g_debug ("closed = %d", g_io_stream_is_closed (stream));
551 GSocket *socket;
552 socket = g_socket_connection_get_socket (G_SOCKET_CONNECTION (stream));
553 g_debug ("socket_closed = %d", g_socket_is_closed (socket));
554 g_debug ("socket_condition_check = %d", g_socket_condition_check (socket, G_IO_IN|G_IO_OUT|G_IO_ERR|G_IO_HUP));
556 gchar buf[128];
557 GError *error;
558 gssize num_read;
559 error = NULL;
560 num_read = g_input_stream_read (g_io_stream_get_input_stream (stream),
561 buf,
562 128,
563 NULL,
564 &error);
565 if (num_read < 0)
567 g_debug ("error: %s", error->message);
568 g_error_free (error);
570 else
572 g_debug ("no error, read %d bytes", (gint) num_read);
576 return FALSE;
579 static gboolean
580 on_do_disconnect_in_idle (gpointer data)
582 GDBusConnection *c = G_DBUS_CONNECTION (data);
583 g_debug ("GDC %p has ref_count %d", c, G_OBJECT (c)->ref_count);
584 g_dbus_connection_disconnect (c);
585 g_object_unref (c);
586 return FALSE;
588 #endif
590 #ifdef G_OS_UNIX
591 static gchar *
592 read_all_from_fd (gint fd, gsize *out_len, GError **error)
594 GString *str;
595 gchar buf[64];
596 gssize num_read;
598 str = g_string_new (NULL);
602 num_read = read (fd, buf, sizeof (buf));
603 if (num_read == -1)
605 if (errno == EAGAIN || errno == EWOULDBLOCK)
606 continue;
607 g_set_error (error,
608 G_IO_ERROR,
609 g_io_error_from_errno (errno),
610 "Failed reading %d bytes into offset %d: %s",
611 (gint) sizeof (buf),
612 (gint) str->len,
613 strerror (errno));
614 goto error;
616 else if (num_read > 0)
618 g_string_append_len (str, buf, num_read);
620 else if (num_read == 0)
622 break;
625 while (TRUE);
627 if (out_len != NULL)
628 *out_len = str->len;
629 return g_string_free (str, FALSE);
631 error:
632 if (out_len != NULL)
633 out_len = 0;
634 g_string_free (str, TRUE);
635 return NULL;
637 #endif
639 static void
640 test_peer (void)
642 GDBusConnection *c;
643 GDBusConnection *c2;
644 GDBusProxy *proxy;
645 GError *error;
646 PeerData data;
647 GVariant *value;
648 GVariant *result;
649 const gchar *s;
650 GThread *service_thread;
651 gulong signal_handler_id;
653 memset (&data, '\0', sizeof (PeerData));
654 data.current_connections = g_ptr_array_new_with_free_func (g_object_unref);
656 /* first try to connect when there is no server */
657 error = NULL;
658 c = g_dbus_connection_new_for_address_sync (is_unix ? "unix:path=/tmp/gdbus-test-does-not-exist-pid" :
659 /* NOTE: Even if something is listening on port 12345 the connection
660 * will fail because the nonce file doesn't exist */
661 "nonce-tcp:host=localhost,port=12345,noncefile=this-does-not-exist-gdbus",
662 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
663 NULL, /* GDBusAuthObserver */
664 NULL, /* cancellable */
665 &error);
666 _g_assert_error_domain (error, G_IO_ERROR);
667 g_assert (!g_dbus_error_is_remote_error (error));
668 g_clear_error (&error);
669 g_assert (c == NULL);
671 /* bring up a server - we run the server in a different thread to avoid deadlocks */
672 service_thread = g_thread_new ("test_peer",
673 service_thread_func,
674 &data);
675 await_service_loop ();
676 g_assert (server != NULL);
678 /* bring up a connection and accept it */
679 data.accept_connection = TRUE;
680 error = NULL;
681 c = g_dbus_connection_new_for_address_sync (g_dbus_server_get_client_address (server),
682 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
683 NULL, /* GDBusAuthObserver */
684 NULL, /* cancellable */
685 &error);
686 g_assert_no_error (error);
687 g_assert (c != NULL);
688 while (data.current_connections->len < 1)
689 g_main_loop_run (loop);
690 g_assert_cmpint (data.current_connections->len, ==, 1);
691 g_assert_cmpint (data.num_connection_attempts, ==, 1);
692 g_assert (g_dbus_connection_get_unique_name (c) == NULL);
693 g_assert_cmpstr (g_dbus_connection_get_guid (c), ==, test_guid);
695 /* check that we create a proxy, read properties, receive signals and invoke
696 * the HelloPeer() method. Since the server runs in another thread it's fine
697 * to use synchronous blocking API here.
699 error = NULL;
700 proxy = g_dbus_proxy_new_sync (c,
701 G_DBUS_PROXY_FLAGS_NONE,
702 NULL,
703 NULL, /* bus_name */
704 "/org/gtk/GDBus/PeerTestObject",
705 "org.gtk.GDBus.PeerTestInterface",
706 NULL, /* GCancellable */
707 &error);
708 g_assert_no_error (error);
709 g_assert (proxy != NULL);
710 error = NULL;
711 value = g_dbus_proxy_get_cached_property (proxy, "PeerProperty");
712 g_assert_cmpstr (g_variant_get_string (value, NULL), ==, "ThePropertyValue");
714 /* try invoking a method */
715 error = NULL;
716 result = g_dbus_proxy_call_sync (proxy,
717 "HelloPeer",
718 g_variant_new ("(s)", "Hey Peer!"),
719 G_DBUS_CALL_FLAGS_NONE,
721 NULL, /* GCancellable */
722 &error);
723 g_assert_no_error (error);
724 g_variant_get (result, "(&s)", &s);
725 g_assert_cmpstr (s, ==, "You greeted me with 'Hey Peer!'.");
726 g_variant_unref (result);
727 g_assert_cmpint (data.num_method_calls, ==, 1);
729 /* make the other peer emit a signal - catch it */
730 signal_handler_id = g_signal_connect (proxy,
731 "g-signal",
732 G_CALLBACK (on_proxy_signal_received),
733 &data);
734 g_assert (!data.signal_received);
735 g_dbus_proxy_call (proxy,
736 "EmitSignal",
737 NULL, /* no arguments */
738 G_DBUS_CALL_FLAGS_NONE,
740 NULL, /* GCancellable */
741 NULL, /* GAsyncReadyCallback - we don't care about the result */
742 NULL); /* user_data */
743 g_main_loop_run (loop);
744 g_assert (data.signal_received);
745 g_assert_cmpint (data.num_method_calls, ==, 2);
746 g_signal_handler_disconnect (proxy, signal_handler_id);
748 /* Also ensure that messages with the sender header-field set gets
749 * delivered to the proxy - note that this doesn't really make sense
750 * e.g. names are meaning-less in a peer-to-peer case... but we
751 * support it because it makes sense in certain bridging
752 * applications - see e.g. #623815.
754 signal_handler_id = g_signal_connect (proxy,
755 "g-signal",
756 G_CALLBACK (on_proxy_signal_received_with_name_set),
757 &data);
758 data.signal_received = FALSE;
759 g_dbus_proxy_call (proxy,
760 "EmitSignalWithNameSet",
761 NULL, /* no arguments */
762 G_DBUS_CALL_FLAGS_NONE,
764 NULL, /* GCancellable */
765 NULL, /* GAsyncReadyCallback - we don't care about the result */
766 NULL); /* user_data */
767 g_main_loop_run (loop);
768 g_assert (data.signal_received);
769 g_assert_cmpint (data.num_method_calls, ==, 3);
770 g_signal_handler_disconnect (proxy, signal_handler_id);
772 /* check for UNIX fd passing */
773 #ifdef G_OS_UNIX
775 GDBusMessage *method_call_message;
776 GDBusMessage *method_reply_message;
777 GUnixFDList *fd_list;
778 gint fd;
779 gchar *buf;
780 gsize len;
781 gchar *buf2;
782 gsize len2;
783 const char *testfile = g_test_get_filename (G_TEST_DIST, "file.c", NULL);
785 method_call_message = g_dbus_message_new_method_call (NULL, /* name */
786 "/org/gtk/GDBus/PeerTestObject",
787 "org.gtk.GDBus.PeerTestInterface",
788 "OpenFile");
789 g_dbus_message_set_body (method_call_message, g_variant_new ("(s)", testfile));
790 error = NULL;
791 method_reply_message = g_dbus_connection_send_message_with_reply_sync (c,
792 method_call_message,
793 G_DBUS_SEND_MESSAGE_FLAGS_NONE,
795 NULL, /* out_serial */
796 NULL, /* cancellable */
797 &error);
798 g_assert_no_error (error);
799 g_assert (g_dbus_message_get_message_type (method_reply_message) == G_DBUS_MESSAGE_TYPE_METHOD_RETURN);
800 fd_list = g_dbus_message_get_unix_fd_list (method_reply_message);
801 g_assert (fd_list != NULL);
802 g_assert_cmpint (g_unix_fd_list_get_length (fd_list), ==, 1);
803 error = NULL;
804 fd = g_unix_fd_list_get (fd_list, 0, &error);
805 g_assert_no_error (error);
806 g_object_unref (method_call_message);
807 g_object_unref (method_reply_message);
809 error = NULL;
810 len = 0;
811 buf = read_all_from_fd (fd, &len, &error);
812 g_assert_no_error (error);
813 g_assert (buf != NULL);
814 close (fd);
816 error = NULL;
817 g_file_get_contents (testfile,
818 &buf2,
819 &len2,
820 &error);
821 g_assert_no_error (error);
822 g_assert_cmpint (len, ==, len2);
823 g_assert (memcmp (buf, buf2, len) == 0);
824 g_free (buf2);
825 g_free (buf);
827 #else
828 error = NULL;
829 result = g_dbus_proxy_call_sync (proxy,
830 "OpenFile",
831 g_variant_new ("(s)", "boo"),
832 G_DBUS_CALL_FLAGS_NONE,
834 NULL, /* GCancellable */
835 &error);
836 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_DBUS_ERROR);
837 g_assert (result == NULL);
838 g_error_free (error);
839 #endif /* G_OS_UNIX */
841 /* Check that g_socket_get_credentials() work - (though this really
842 * should be in socket.c)
845 GSocket *socket;
846 GCredentials *credentials;
847 socket = g_socket_connection_get_socket (G_SOCKET_CONNECTION (g_dbus_connection_get_stream (c)));
848 g_assert (G_IS_SOCKET (socket));
849 error = NULL;
850 credentials = g_socket_get_credentials (socket, &error);
852 #if G_CREDENTIALS_SOCKET_GET_CREDENTIALS_SUPPORTED
853 g_assert_no_error (error);
854 g_assert (G_IS_CREDENTIALS (credentials));
856 g_assert_cmpuint (g_credentials_get_unix_user (credentials, NULL), ==,
857 getuid ());
858 g_assert_cmpuint (g_credentials_get_unix_pid (credentials, NULL), ==,
859 getpid ());
860 #else
861 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED);
862 g_assert (credentials == NULL);
863 #endif
867 /* bring up a connection - don't accept it - this should fail
869 data.accept_connection = FALSE;
870 error = NULL;
871 c2 = g_dbus_connection_new_for_address_sync (g_dbus_server_get_client_address (server),
872 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
873 NULL, /* GDBusAuthObserver */
874 NULL, /* cancellable */
875 &error);
876 _g_assert_error_domain (error, G_IO_ERROR);
877 g_error_free (error);
878 g_assert (c2 == NULL);
880 #if 0
881 /* TODO: THIS TEST DOESN'T WORK YET */
883 /* bring up a connection - accept it.. then disconnect from the client side - check
884 * that the server side gets the disconnect signal.
886 error = NULL;
887 data.accept_connection = TRUE;
888 c2 = g_dbus_connection_new_for_address_sync (g_dbus_server_get_client_address (server),
889 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
890 NULL, /* GDBusAuthObserver */
891 NULL, /* cancellable */
892 &error);
893 g_assert_no_error (error);
894 g_assert (c2 != NULL);
895 g_assert (!g_dbus_connection_get_is_disconnected (c2));
896 while (data.num_connection_attempts < 3)
897 g_main_loop_run (loop);
898 g_assert_cmpint (data.current_connections->len, ==, 2);
899 g_assert_cmpint (data.num_connection_attempts, ==, 3);
900 g_assert (!g_dbus_connection_get_is_disconnected (G_DBUS_CONNECTION (data.current_connections->pdata[1])));
901 g_idle_add (on_do_disconnect_in_idle, c2);
902 g_debug ("==================================================");
903 g_debug ("==================================================");
904 g_debug ("==================================================");
905 g_debug ("waiting for disconnect on connection %p, stream %p",
906 data.current_connections->pdata[1],
907 g_dbus_connection_get_stream (data.current_connections->pdata[1]));
909 g_timeout_add (2000, check_connection, &data);
910 //_g_assert_signal_received (G_DBUS_CONNECTION (data.current_connections->pdata[1]), "closed");
911 g_main_loop_run (loop);
912 g_assert (g_dbus_connection_get_is_disconnected (G_DBUS_CONNECTION (data.current_connections->pdata[1])));
913 g_ptr_array_set_size (data.current_connections, 1); /* remove disconnected connection object */
914 #endif
916 /* unref the server and stop listening for new connections
918 * This won't bring down the established connections - check that c is still connected
919 * by invoking a method
921 //g_socket_service_stop (service);
922 //g_object_unref (service);
923 g_dbus_server_stop (server);
924 g_object_unref (server);
925 server = NULL;
927 error = NULL;
928 result = g_dbus_proxy_call_sync (proxy,
929 "HelloPeer",
930 g_variant_new ("(s)", "Hey Again Peer!"),
931 G_DBUS_CALL_FLAGS_NONE,
933 NULL, /* GCancellable */
934 &error);
935 g_assert_no_error (error);
936 g_variant_get (result, "(&s)", &s);
937 g_assert_cmpstr (s, ==, "You greeted me with 'Hey Again Peer!'.");
938 g_variant_unref (result);
939 g_assert_cmpint (data.num_method_calls, ==, 5);
941 #if 0
942 /* TODO: THIS TEST DOESN'T WORK YET */
944 /* now disconnect from the server side - check that the client side gets the signal */
945 g_assert_cmpint (data.current_connections->len, ==, 1);
946 g_assert (G_DBUS_CONNECTION (data.current_connections->pdata[0]) != c);
947 g_dbus_connection_disconnect (G_DBUS_CONNECTION (data.current_connections->pdata[0]));
948 if (!g_dbus_connection_get_is_disconnected (c))
949 _g_assert_signal_received (c, "closed");
950 g_assert (g_dbus_connection_get_is_disconnected (c));
951 #endif
953 g_object_unref (c);
954 g_ptr_array_unref (data.current_connections);
955 g_object_unref (proxy);
957 g_main_loop_quit (service_loop);
958 g_thread_join (service_thread);
961 /* ---------------------------------------------------------------------------------------------------- */
963 typedef struct
965 GDBusServer *server;
966 GMainContext *context;
967 GMainLoop *loop;
969 GList *connections;
970 } DmpData;
972 static void
973 dmp_data_free (DmpData *data)
975 g_main_loop_unref (data->loop);
976 g_main_context_unref (data->context);
977 g_object_unref (data->server);
978 g_list_free_full (data->connections, g_object_unref);
979 g_free (data);
982 static void
983 dmp_on_method_call (GDBusConnection *connection,
984 const gchar *sender,
985 const gchar *object_path,
986 const gchar *interface_name,
987 const gchar *method_name,
988 GVariant *parameters,
989 GDBusMethodInvocation *invocation,
990 gpointer user_data)
992 //DmpData *data = user_data;
993 gint32 first;
994 gint32 second;
995 g_variant_get (parameters,
996 "(ii)",
997 &first,
998 &second);
999 g_dbus_method_invocation_return_value (invocation,
1000 g_variant_new ("(i)", first + second));
1003 static const GDBusInterfaceVTable dmp_interface_vtable =
1005 dmp_on_method_call,
1006 NULL, /* get_property */
1007 NULL /* set_property */
1011 /* Runs in thread we created GDBusServer in (since we didn't pass G_DBUS_SERVER_FLAGS_RUN_IN_THREAD) */
1012 static gboolean
1013 dmp_on_new_connection (GDBusServer *server,
1014 GDBusConnection *connection,
1015 gpointer user_data)
1017 DmpData *data = user_data;
1018 GDBusNodeInfo *node;
1019 GError *error;
1021 /* accept the connection */
1022 data->connections = g_list_prepend (data->connections, g_object_ref (connection));
1024 error = NULL;
1025 node = g_dbus_node_info_new_for_xml ("<node>"
1026 " <interface name='org.gtk.GDBus.DmpInterface'>"
1027 " <method name='AddPair'>"
1028 " <arg type='i' name='first' direction='in'/>"
1029 " <arg type='i' name='second' direction='in'/>"
1030 " <arg type='i' name='sum' direction='out'/>"
1031 " </method>"
1032 " </interface>"
1033 "</node>",
1034 &error);
1035 g_assert_no_error (error);
1037 /* sleep 100ms before exporting an object - this is to test that
1038 * G_DBUS_CONNECTION_FLAGS_DELAY_MESSAGE_PROCESSING really works
1039 * (GDBusServer uses this feature).
1041 usleep (100 * 1000);
1043 /* export an object */
1044 error = NULL;
1045 g_dbus_connection_register_object (connection,
1046 "/dmp/test",
1047 node->interfaces[0],
1048 &dmp_interface_vtable,
1049 data,
1050 NULL,
1051 &error);
1052 g_dbus_node_info_unref (node);
1054 return TRUE;
1057 static gpointer
1058 dmp_thread_func (gpointer user_data)
1060 DmpData *data = user_data;
1061 GError *error;
1062 gchar *guid;
1064 data->context = g_main_context_new ();
1065 g_main_context_push_thread_default (data->context);
1067 error = NULL;
1068 guid = g_dbus_generate_guid ();
1069 data->server = g_dbus_server_new_sync (tmp_address,
1070 G_DBUS_SERVER_FLAGS_NONE,
1071 guid,
1072 NULL, /* GDBusAuthObserver */
1073 NULL, /* GCancellable */
1074 &error);
1075 g_assert_no_error (error);
1076 g_signal_connect (data->server,
1077 "new-connection",
1078 G_CALLBACK (dmp_on_new_connection),
1079 data);
1081 g_dbus_server_start (data->server);
1083 data->loop = g_main_loop_new (data->context, FALSE);
1084 g_main_loop_run (data->loop);
1086 g_main_context_pop_thread_default (data->context);
1088 g_free (guid);
1089 return NULL;
1092 static void
1093 delayed_message_processing (void)
1095 GError *error;
1096 DmpData *data;
1097 GThread *service_thread;
1098 guint n;
1100 data = g_new0 (DmpData, 1);
1102 service_thread = g_thread_new ("dmp",
1103 dmp_thread_func,
1104 data);
1105 while (data->server == NULL || !g_dbus_server_is_active (data->server))
1106 g_thread_yield ();
1108 for (n = 0; n < 5; n++)
1110 GDBusConnection *c;
1111 GVariant *res;
1112 gint32 val;
1114 error = NULL;
1115 c = g_dbus_connection_new_for_address_sync (g_dbus_server_get_client_address (data->server),
1116 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
1117 NULL, /* GDBusAuthObserver */
1118 NULL, /* GCancellable */
1119 &error);
1120 g_assert_no_error (error);
1122 error = NULL;
1123 res = g_dbus_connection_call_sync (c,
1124 NULL, /* bus name */
1125 "/dmp/test",
1126 "org.gtk.GDBus.DmpInterface",
1127 "AddPair",
1128 g_variant_new ("(ii)", 2, n),
1129 G_VARIANT_TYPE ("(i)"),
1130 G_DBUS_CALL_FLAGS_NONE,
1131 -1, /* timeout_msec */
1132 NULL, /* GCancellable */
1133 &error);
1134 g_assert_no_error (error);
1135 g_variant_get (res, "(i)", &val);
1136 g_assert_cmpint (val, ==, 2 + n);
1137 g_variant_unref (res);
1138 g_object_unref (c);
1141 g_main_loop_quit (data->loop);
1142 g_thread_join (service_thread);
1143 dmp_data_free (data);
1146 /* ---------------------------------------------------------------------------------------------------- */
1148 static gboolean
1149 nonce_tcp_on_authorize_authenticated_peer (GDBusAuthObserver *observer,
1150 GIOStream *stream,
1151 GCredentials *credentials,
1152 gpointer user_data)
1154 PeerData *data = user_data;
1155 gboolean authorized;
1157 data->num_connection_attempts++;
1159 authorized = TRUE;
1160 if (!data->accept_connection)
1162 authorized = FALSE;
1163 g_main_loop_quit (loop);
1166 return authorized;
1169 /* Runs in thread we created GDBusServer in (since we didn't pass G_DBUS_SERVER_FLAGS_RUN_IN_THREAD) */
1170 static gboolean
1171 nonce_tcp_on_new_connection (GDBusServer *server,
1172 GDBusConnection *connection,
1173 gpointer user_data)
1175 PeerData *data = user_data;
1177 g_ptr_array_add (data->current_connections, g_object_ref (connection));
1179 g_main_loop_quit (loop);
1181 return TRUE;
1184 static gpointer
1185 nonce_tcp_service_thread_func (gpointer user_data)
1187 PeerData *data = user_data;
1188 GMainContext *service_context;
1189 GDBusAuthObserver *observer;
1190 GError *error;
1192 service_context = g_main_context_new ();
1193 g_main_context_push_thread_default (service_context);
1195 error = NULL;
1196 observer = g_dbus_auth_observer_new ();
1197 server = g_dbus_server_new_sync ("nonce-tcp:",
1198 G_DBUS_SERVER_FLAGS_NONE,
1199 test_guid,
1200 observer,
1201 NULL, /* cancellable */
1202 &error);
1203 g_assert_no_error (error);
1205 g_signal_connect (server,
1206 "new-connection",
1207 G_CALLBACK (nonce_tcp_on_new_connection),
1208 data);
1209 g_signal_connect (observer,
1210 "authorize-authenticated-peer",
1211 G_CALLBACK (nonce_tcp_on_authorize_authenticated_peer),
1212 data);
1213 g_object_unref (observer);
1215 g_dbus_server_start (server);
1217 create_service_loop (service_context);
1218 g_main_loop_run (service_loop);
1220 g_main_context_pop_thread_default (service_context);
1222 teardown_service_loop ();
1223 g_main_context_unref (service_context);
1225 /* test code specifically unrefs the server - see below */
1226 g_assert (server == NULL);
1228 return NULL;
1231 static void
1232 test_nonce_tcp (void)
1234 PeerData data;
1235 GError *error;
1236 GThread *service_thread;
1237 GDBusConnection *c;
1238 gchar *s;
1239 gchar *nonce_file;
1240 gboolean res;
1241 const gchar *address;
1243 memset (&data, '\0', sizeof (PeerData));
1244 data.current_connections = g_ptr_array_new_with_free_func (g_object_unref);
1246 error = NULL;
1247 server = NULL;
1248 service_thread = g_thread_new ("nonce-tcp-service",
1249 nonce_tcp_service_thread_func,
1250 &data);
1251 await_service_loop ();
1252 g_assert (server != NULL);
1254 /* bring up a connection and accept it */
1255 data.accept_connection = TRUE;
1256 error = NULL;
1257 c = g_dbus_connection_new_for_address_sync (g_dbus_server_get_client_address (server),
1258 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
1259 NULL, /* GDBusAuthObserver */
1260 NULL, /* cancellable */
1261 &error);
1262 g_assert_no_error (error);
1263 g_assert (c != NULL);
1264 while (data.current_connections->len < 1)
1265 g_thread_yield ();
1266 g_assert_cmpint (data.current_connections->len, ==, 1);
1267 g_assert_cmpint (data.num_connection_attempts, ==, 1);
1268 g_assert (g_dbus_connection_get_unique_name (c) == NULL);
1269 g_assert_cmpstr (g_dbus_connection_get_guid (c), ==, test_guid);
1270 g_object_unref (c);
1272 /* now, try to subvert the nonce file (this assumes noncefile is the last key/value pair)
1275 address = g_dbus_server_get_client_address (server);
1277 s = strstr (address, "noncefile=");
1278 g_assert (s != NULL);
1279 s += sizeof "noncefile=" - 1;
1280 nonce_file = g_strdup (s);
1282 /* First try invalid data in the nonce file - this will actually
1283 * make the client send this and the server will reject it. The way
1284 * it works is that if the nonce doesn't match, the server will
1285 * simply close the connection. So, from the client point of view,
1286 * we can see a variety of errors.
1288 error = NULL;
1289 res = g_file_set_contents (nonce_file,
1290 "0123456789012345",
1292 &error);
1293 g_assert_no_error (error);
1294 g_assert (res);
1295 c = g_dbus_connection_new_for_address_sync (address,
1296 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
1297 NULL, /* GDBusAuthObserver */
1298 NULL, /* cancellable */
1299 &error);
1300 _g_assert_error_domain (error, G_IO_ERROR);
1301 g_error_free (error);
1302 g_assert (c == NULL);
1304 /* Then try with a nonce-file of incorrect length - this will make
1305 * the client complain - we won't even try connecting to the server
1306 * for this
1308 error = NULL;
1309 res = g_file_set_contents (nonce_file,
1310 "0123456789012345_",
1312 &error);
1313 g_assert_no_error (error);
1314 g_assert (res);
1315 c = g_dbus_connection_new_for_address_sync (address,
1316 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
1317 NULL, /* GDBusAuthObserver */
1318 NULL, /* cancellable */
1319 &error);
1320 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1321 g_error_free (error);
1322 g_assert (c == NULL);
1324 /* Finally try with no nonce-file at all */
1325 g_assert_cmpint (g_unlink (nonce_file), ==, 0);
1326 error = NULL;
1327 c = g_dbus_connection_new_for_address_sync (address,
1328 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
1329 NULL, /* GDBusAuthObserver */
1330 NULL, /* cancellable */
1331 &error);
1332 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
1333 g_error_free (error);
1334 g_assert (c == NULL);
1336 g_free (nonce_file);
1338 g_dbus_server_stop (server);
1339 g_object_unref (server);
1340 server = NULL;
1342 g_main_loop_quit (service_loop);
1343 g_thread_join (service_thread);
1346 static void
1347 test_credentials (void)
1349 GCredentials *c1, *c2;
1350 GError *error;
1351 gchar *desc;
1353 c1 = g_credentials_new ();
1354 c2 = g_credentials_new ();
1356 error = NULL;
1357 if (g_credentials_set_unix_user (c2, getuid (), &error))
1358 g_assert_no_error (error);
1360 g_clear_error (&error);
1361 g_assert (g_credentials_is_same_user (c1, c2, &error));
1362 g_assert_no_error (error);
1364 desc = g_credentials_to_string (c1);
1365 g_assert (desc != NULL);
1366 g_free (desc);
1368 g_object_unref (c1);
1369 g_object_unref (c2);
1372 /* ---------------------------------------------------------------------------------------------------- */
1374 static gboolean
1375 tcp_anonymous_on_new_connection (GDBusServer *server,
1376 GDBusConnection *connection,
1377 gpointer user_data)
1379 gboolean *seen_connection = user_data;
1380 *seen_connection = TRUE;
1381 return TRUE;
1384 static gpointer
1385 tcp_anonymous_service_thread_func (gpointer user_data)
1387 gboolean *seen_connection = user_data;
1388 GMainContext *service_context;
1389 GError *error;
1391 service_context = g_main_context_new ();
1392 g_main_context_push_thread_default (service_context);
1394 error = NULL;
1395 server = g_dbus_server_new_sync ("tcp:",
1396 G_DBUS_SERVER_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS,
1397 test_guid,
1398 NULL, /* GDBusObserver* */
1399 NULL, /* GCancellable* */
1400 &error);
1401 g_assert_no_error (error);
1403 g_signal_connect (server,
1404 "new-connection",
1405 G_CALLBACK (tcp_anonymous_on_new_connection),
1406 seen_connection);
1408 g_dbus_server_start (server);
1410 create_service_loop (service_context);
1411 g_main_loop_run (service_loop);
1413 g_main_context_pop_thread_default (service_context);
1415 teardown_service_loop ();
1416 g_main_context_unref (service_context);
1418 return NULL;
1421 static void
1422 test_tcp_anonymous (void)
1424 gboolean seen_connection;
1425 GThread *service_thread;
1426 GDBusConnection *connection;
1427 GError *error;
1429 seen_connection = FALSE;
1430 service_thread = g_thread_new ("tcp-anon-service",
1431 tcp_anonymous_service_thread_func,
1432 &seen_connection);
1433 await_service_loop ();
1434 g_assert (server != NULL);
1436 error = NULL;
1437 connection = g_dbus_connection_new_for_address_sync (g_dbus_server_get_client_address (server),
1438 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
1439 NULL, /* GDBusAuthObserver* */
1440 NULL, /* GCancellable */
1441 &error);
1442 g_assert_no_error (error);
1443 g_assert (connection != NULL);
1445 while (!seen_connection)
1446 g_thread_yield ();
1448 g_object_unref (connection);
1450 g_main_loop_quit (service_loop);
1451 g_dbus_server_stop (server);
1452 g_object_unref (server);
1453 server = NULL;
1455 g_thread_join (service_thread);
1458 /* ---------------------------------------------------------------------------------------------------- */
1460 static GDBusServer *codegen_server = NULL;
1462 static gboolean
1463 codegen_on_animal_poke (ExampleAnimal *animal,
1464 GDBusMethodInvocation *invocation,
1465 gboolean make_sad,
1466 gboolean make_happy,
1467 gpointer user_data)
1469 if ((make_sad && make_happy) || (!make_sad && !make_happy))
1471 g_main_loop_quit (service_loop);
1473 g_dbus_method_invocation_return_dbus_error (invocation,
1474 "org.gtk.GDBus.Examples.ObjectManager.Error.Failed",
1475 "Exactly one of make_sad or make_happy must be TRUE");
1476 goto out;
1479 if (make_sad)
1481 if (g_strcmp0 (example_animal_get_mood (animal), "Sad") == 0)
1483 g_dbus_method_invocation_return_dbus_error (invocation,
1484 "org.gtk.GDBus.Examples.ObjectManager.Error.SadAnimalIsSad",
1485 "Sad animal is already sad");
1486 goto out;
1489 example_animal_set_mood (animal, "Sad");
1490 example_animal_complete_poke (animal, invocation);
1491 goto out;
1494 if (make_happy)
1496 if (g_strcmp0 (example_animal_get_mood (animal), "Happy") == 0)
1498 g_dbus_method_invocation_return_dbus_error (invocation,
1499 "org.gtk.GDBus.Examples.ObjectManager.Error.HappyAnimalIsHappy",
1500 "Happy animal is already happy");
1501 goto out;
1504 example_animal_set_mood (animal, "Happy");
1505 example_animal_complete_poke (animal, invocation);
1506 goto out;
1509 g_assert_not_reached ();
1511 out:
1512 return TRUE; /* to indicate that the method was handled */
1515 /* Runs in thread we created GDBusServer in (since we didn't pass G_DBUS_SERVER_FLAGS_RUN_IN_THREAD) */
1516 static gboolean
1517 codegen_on_new_connection (GDBusServer *server,
1518 GDBusConnection *connection,
1519 gpointer user_data)
1521 ExampleAnimal *animal = user_data;
1522 GError *error = NULL;
1524 /* g_print ("Client connected.\n" */
1525 /* "Negotiated capabilities: unix-fd-passing=%d\n", */
1526 /* g_dbus_connection_get_capabilities (connection) & G_DBUS_CAPABILITY_FLAGS_UNIX_FD_PASSING); */
1528 g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (animal), connection,
1529 "/Example/Animals/000", &error);
1530 g_assert_no_error (error);
1532 return TRUE;
1535 static gpointer
1536 codegen_service_thread_func (gpointer user_data)
1538 GMainContext *service_context;
1539 ExampleAnimal *animal;
1540 GError *error = NULL;
1542 service_context = g_main_context_new ();
1543 g_main_context_push_thread_default (service_context);
1545 /* Create the animal in the right thread context */
1546 animal = example_animal_skeleton_new ();
1548 /* Handle Poke() D-Bus method invocations on the .Animal interface */
1549 g_signal_connect (animal, "handle-poke",
1550 G_CALLBACK (codegen_on_animal_poke),
1551 NULL); /* user_data */
1553 codegen_server = g_dbus_server_new_sync (tmp_address,
1554 G_DBUS_SERVER_FLAGS_NONE,
1555 test_guid,
1556 NULL, /* observer */
1557 NULL, /* cancellable */
1558 &error);
1559 g_assert_no_error (error);
1560 g_dbus_server_start (codegen_server);
1562 g_signal_connect (codegen_server, "new-connection",
1563 G_CALLBACK (codegen_on_new_connection),
1564 animal);
1566 create_service_loop (service_context);
1567 g_main_loop_run (service_loop);
1569 g_object_unref (animal);
1571 g_main_context_pop_thread_default (service_context);
1573 teardown_service_loop ();
1574 g_main_context_unref (service_context);
1576 g_dbus_server_stop (codegen_server);
1577 g_object_unref (codegen_server);
1578 codegen_server = NULL;
1580 return NULL;
1584 static gboolean
1585 codegen_quit_mainloop_timeout (gpointer data)
1587 g_main_loop_quit (loop);
1588 return FALSE;
1591 static void
1592 codegen_test_peer (void)
1594 GDBusConnection *connection;
1595 ExampleAnimal *animal1, *animal2;
1596 GThread *service_thread;
1597 GError *error = NULL;
1598 GVariant *value;
1600 /* bring up a server - we run the server in a different thread to avoid deadlocks */
1601 service_thread = g_thread_new ("codegen_test_peer",
1602 codegen_service_thread_func,
1603 NULL);
1604 await_service_loop ();
1605 g_assert (codegen_server != NULL);
1607 /* Get an animal 1 ... */
1608 connection = g_dbus_connection_new_for_address_sync (g_dbus_server_get_client_address (codegen_server),
1609 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
1610 NULL, /* GDBusAuthObserver */
1611 NULL, /* cancellable */
1612 &error);
1613 g_assert_no_error (error);
1614 g_assert (connection != NULL);
1616 animal1 = example_animal_proxy_new_sync (connection, 0, NULL,
1617 "/Example/Animals/000", NULL, &error);
1618 g_assert_no_error (error);
1619 g_assert (animal1 != NULL);
1620 g_object_unref (connection);
1622 /* Get animal 2 ... */
1623 connection = g_dbus_connection_new_for_address_sync (g_dbus_server_get_client_address (codegen_server),
1624 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
1625 NULL, /* GDBusAuthObserver */
1626 NULL, /* cancellable */
1627 &error);
1628 g_assert_no_error (error);
1629 g_assert (connection != NULL);
1631 animal2 = example_animal_proxy_new_sync (connection, 0, NULL,
1632 "/Example/Animals/000", NULL, &error);
1633 g_assert_no_error (error);
1634 g_assert (animal2 != NULL);
1635 g_object_unref (connection);
1637 /* Make animal sad via animal1 */
1638 example_animal_call_poke_sync (animal1, TRUE, FALSE, NULL, &error);
1639 g_assert_no_error (error);
1641 /* Poke server and make sure animal is updated */
1642 value = g_dbus_proxy_call_sync (G_DBUS_PROXY (animal1),
1643 "org.freedesktop.DBus.Peer.Ping",
1644 NULL, G_DBUS_CALL_FLAGS_NONE, -1,
1645 NULL, &error);
1646 g_assert_no_error (error);
1647 g_assert (value != NULL);
1648 g_variant_unref (value);
1650 /* Give the proxies a chance to refresh in the defaul main loop */
1651 g_timeout_add (100, codegen_quit_mainloop_timeout, NULL);
1652 g_main_loop_run (loop);
1654 /* Assert animals are sad */
1655 g_assert_cmpstr (example_animal_get_mood (animal1), ==, "Sad");
1656 g_assert_cmpstr (example_animal_get_mood (animal2), ==, "Sad");
1658 /* Make animal happy via animal2 */
1659 example_animal_call_poke_sync (animal2, FALSE, TRUE, NULL, &error);
1660 g_assert_no_error (error);
1662 /* Poke server and make sure animal is updated */
1663 value = g_dbus_proxy_call_sync (G_DBUS_PROXY (animal2),
1664 "org.freedesktop.DBus.Peer.Ping",
1665 NULL, G_DBUS_CALL_FLAGS_NONE, -1,
1666 NULL, &error);
1667 g_assert_no_error (error);
1668 g_assert (value != NULL);
1669 g_variant_unref (value);
1671 /* Give the proxies a chance to refresh in the defaul main loop */
1672 g_timeout_add (1000, codegen_quit_mainloop_timeout, NULL);
1673 g_main_loop_run (loop);
1675 /* Assert animals are happy */
1676 g_assert_cmpstr (example_animal_get_mood (animal1), ==, "Happy");
1677 g_assert_cmpstr (example_animal_get_mood (animal2), ==, "Happy");
1679 /* This final call making the animal happy and sad will cause
1680 * the server to quit, when the server quits we dont get property
1681 * change notifications anyway because those are done from an idle handler
1683 example_animal_call_poke_sync (animal2, TRUE, TRUE, NULL, &error);
1685 g_object_unref (animal1);
1686 g_object_unref (animal2);
1687 g_thread_join (service_thread);
1690 /* ---------------------------------------------------------------------------------------------------- */
1694 main (int argc,
1695 char *argv[])
1697 gint ret;
1698 GDBusNodeInfo *introspection_data = NULL;
1699 gchar *tmpdir = NULL;
1701 g_test_init (&argc, &argv, NULL);
1703 introspection_data = g_dbus_node_info_new_for_xml (test_interface_introspection_xml, NULL);
1704 g_assert (introspection_data != NULL);
1705 test_interface_introspection_data = introspection_data->interfaces[0];
1707 test_guid = g_dbus_generate_guid ();
1709 if (is_unix)
1711 if (g_unix_socket_address_abstract_names_supported ())
1712 tmp_address = g_strdup ("unix:tmpdir=/tmp/gdbus-test-");
1713 else
1715 tmpdir = g_dir_make_tmp ("gdbus-test-XXXXXX", NULL);
1716 tmp_address = g_strdup_printf ("unix:tmpdir=%s", tmpdir);
1719 else
1720 tmp_address = g_strdup ("nonce-tcp:");
1722 /* all the tests rely on a shared main loop */
1723 loop = g_main_loop_new (NULL, FALSE);
1725 g_test_add_func ("/gdbus/peer-to-peer", test_peer);
1726 g_test_add_func ("/gdbus/delayed-message-processing", delayed_message_processing);
1727 g_test_add_func ("/gdbus/nonce-tcp", test_nonce_tcp);
1729 g_test_add_func ("/gdbus/tcp-anonymous", test_tcp_anonymous);
1730 g_test_add_func ("/gdbus/credentials", test_credentials);
1731 g_test_add_func ("/gdbus/codegen-peer-to-peer", codegen_test_peer);
1733 ret = g_test_run();
1735 g_main_loop_unref (loop);
1736 g_free (test_guid);
1737 g_dbus_node_info_unref (introspection_data);
1738 if (is_unix)
1739 g_free (tmp_address);
1740 if (tmpdir)
1742 g_rmdir (tmpdir);
1743 g_free (tmpdir);
1746 return ret;