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>
25 #include "gdbus-tests.h"
26 #include "gstrfuncsprivate.h"
28 /* all tests rely on a shared mainloop */
29 static GMainLoop *loop = NULL;
31 static GDBusConnection *c = NULL;
33 /* ---------------------------------------------------------------------------------------------------- */
34 /* Test that we can export objects, the hierarchy is correct and the right handlers are invoked */
35 /* ---------------------------------------------------------------------------------------------------- */
37 static const GDBusArgInfo foo_method1_in_args =
44 static const GDBusArgInfo * const foo_method1_in_arg_pointers[] = {&foo_method1_in_args, NULL};
46 static const GDBusArgInfo foo_method1_out_args =
53 static const GDBusArgInfo * const foo_method1_out_arg_pointers[] = {&foo_method1_out_args, NULL};
55 static const GDBusMethodInfo foo_method_info_method1 =
59 (GDBusArgInfo **) &foo_method1_in_arg_pointers,
60 (GDBusArgInfo **) &foo_method1_out_arg_pointers,
63 static const GDBusMethodInfo foo_method_info_method2 =
71 static const GDBusMethodInfo * const foo_method_info_pointers[] = {&foo_method_info_method1, &foo_method_info_method2, NULL};
73 static const GDBusSignalInfo foo_signal_info =
80 static const GDBusSignalInfo * const foo_signal_info_pointers[] = {&foo_signal_info, NULL};
82 static const GDBusPropertyInfo foo_property_info[] =
88 G_DBUS_PROPERTY_INFO_FLAGS_READABLE | G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE,
95 G_DBUS_PROPERTY_INFO_FLAGS_READABLE,
102 G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE,
106 static const GDBusPropertyInfo * const foo_property_info_pointers[] =
108 &foo_property_info[0],
109 &foo_property_info[1],
110 &foo_property_info[2],
114 static const GDBusInterfaceInfo foo_interface_info =
118 (GDBusMethodInfo **) &foo_method_info_pointers,
119 (GDBusSignalInfo **) &foo_signal_info_pointers,
120 (GDBusPropertyInfo **)&foo_property_info_pointers,
124 /* Foo2 is just Foo without the properties */
125 static const GDBusInterfaceInfo foo2_interface_info =
129 (GDBusMethodInfo **) &foo_method_info_pointers,
130 (GDBusSignalInfo **) &foo_signal_info_pointers,
134 foo_method_call (GDBusConnection *connection,
136 const gchar *object_path,
137 const gchar *interface_name,
138 const gchar *method_name,
139 GVariant *parameters,
140 GDBusMethodInvocation *invocation,
143 if (g_strcmp0 (method_name, "Method1") == 0)
147 g_variant_get (parameters, "(&s)", &input);
148 output = g_strdup_printf ("You passed the string '%s'. Jolly good!", input);
149 g_dbus_method_invocation_return_value (invocation, g_variant_new ("(s)", output));
154 g_dbus_method_invocation_return_dbus_error (invocation,
155 "org.example.SomeError",
156 "How do you like them apples, buddy!");
161 foo_get_property (GDBusConnection *connection,
163 const gchar *object_path,
164 const gchar *interface_name,
165 const gchar *property_name,
171 s = g_strdup_printf ("Property '%s' Is What It Is!", property_name);
172 ret = g_variant_new_string (s);
178 foo_set_property (GDBusConnection *connection,
180 const gchar *object_path,
181 const gchar *interface_name,
182 const gchar *property_name,
188 s = g_variant_print (value, TRUE);
191 G_DBUS_ERROR_SPAWN_FILE_INVALID,
192 "Returning some error instead of writing the value '%s' to the property '%s'",
198 static const GDBusInterfaceVTable foo_vtable =
205 /* -------------------- */
207 static const GDBusMethodInfo bar_method_info[] =
224 static const GDBusMethodInfo * const bar_method_info_pointers[] = {&bar_method_info[0], &bar_method_info[1], NULL};
226 static const GDBusSignalInfo bar_signal_info[] =
235 static const GDBusSignalInfo * const bar_signal_info_pointers[] = {&bar_signal_info[0], NULL};
237 static const GDBusPropertyInfo bar_property_info[] =
243 G_DBUS_PROPERTY_INFO_FLAGS_READABLE,
247 static const GDBusPropertyInfo * const bar_property_info_pointers[] = {&bar_property_info[0], NULL};
249 static const GDBusInterfaceInfo bar_interface_info =
253 (GDBusMethodInfo **) bar_method_info_pointers,
254 (GDBusSignalInfo **) bar_signal_info_pointers,
255 (GDBusPropertyInfo **) bar_property_info_pointers,
259 /* -------------------- */
261 static const GDBusMethodInfo dyna_method_info[] =
271 static const GDBusMethodInfo * const dyna_method_info_pointers[] = {&dyna_method_info[0], NULL};
273 static const GDBusInterfaceInfo dyna_interface_info =
277 (GDBusMethodInfo **) dyna_method_info_pointers,
278 NULL, /* no signals */
279 NULL, /* no properties */
284 dyna_cyber (GDBusConnection *connection,
286 const gchar *object_path,
287 const gchar *interface_name,
288 const gchar *method_name,
289 GVariant *parameters,
290 GDBusMethodInvocation *invocation,
293 GPtrArray *data = user_data;
297 node_name = strrchr (object_path, '/') + 1;
299 /* Add new node if it is not already known */
300 for (n = 0; n < data->len ; n++)
302 if (g_strcmp0 (g_ptr_array_index (data, n), node_name) == 0)
305 g_ptr_array_add (data, g_strdup(node_name));
308 g_dbus_method_invocation_return_value (invocation, NULL);
311 static const GDBusInterfaceVTable dyna_interface_vtable =
318 /* ---------------------------------------------------------------------------------------------------- */
321 introspect_callback (GDBusProxy *proxy,
325 gchar **xml_data = user_data;
330 result = g_dbus_proxy_call_finish (proxy,
333 g_assert_no_error (error);
334 g_assert (result != NULL);
335 g_variant_get (result, "(s)", xml_data);
336 g_variant_unref (result);
338 g_main_loop_quit (loop);
342 compare_strings (gconstpointer a,
345 const gchar *sa = *(const gchar **) a;
346 const gchar *sb = *(const gchar **) b;
348 /* Array terminator must sort last */
354 return strcmp (sa, sb);
358 get_nodes_at (GDBusConnection *c,
359 const gchar *object_path)
365 GDBusNodeInfo *node_info;
369 proxy = g_dbus_proxy_new_sync (c,
370 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
371 G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
373 g_dbus_connection_get_unique_name (c),
375 "org.freedesktop.DBus.Introspectable",
378 g_assert_no_error (error);
379 g_assert (proxy != NULL);
381 /* do this async to avoid libdbus-1 deadlocks */
383 g_dbus_proxy_call (proxy,
386 G_DBUS_CALL_FLAGS_NONE,
389 (GAsyncReadyCallback) introspect_callback,
391 g_main_loop_run (loop);
392 g_assert (xml_data != NULL);
394 node_info = g_dbus_node_info_new_for_xml (xml_data, &error);
395 g_assert_no_error (error);
396 g_assert (node_info != NULL);
398 p = g_ptr_array_new ();
399 for (n = 0; node_info->nodes != NULL && node_info->nodes[n] != NULL; n++)
401 const GDBusNodeInfo *sub_node_info = node_info->nodes[n];
402 g_ptr_array_add (p, g_strdup (sub_node_info->path));
404 g_ptr_array_add (p, NULL);
406 g_object_unref (proxy);
408 g_dbus_node_info_unref (node_info);
410 /* Nodes are semantically unordered; sort array so tests can rely on order */
411 g_ptr_array_sort (p, compare_strings);
413 return (gchar **) g_ptr_array_free (p, FALSE);
417 has_interface (GDBusConnection *c,
418 const gchar *object_path,
419 const gchar *interface_name)
424 GDBusNodeInfo *node_info;
428 proxy = g_dbus_proxy_new_sync (c,
429 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
430 G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
432 g_dbus_connection_get_unique_name (c),
434 "org.freedesktop.DBus.Introspectable",
437 g_assert_no_error (error);
438 g_assert (proxy != NULL);
440 /* do this async to avoid libdbus-1 deadlocks */
442 g_dbus_proxy_call (proxy,
445 G_DBUS_CALL_FLAGS_NONE,
448 (GAsyncReadyCallback) introspect_callback,
450 g_main_loop_run (loop);
451 g_assert (xml_data != NULL);
453 node_info = g_dbus_node_info_new_for_xml (xml_data, &error);
454 g_assert_no_error (error);
455 g_assert (node_info != NULL);
457 ret = (g_dbus_node_info_lookup_interface (node_info, interface_name) != NULL);
459 g_object_unref (proxy);
461 g_dbus_node_info_unref (node_info);
467 count_interfaces (GDBusConnection *c,
468 const gchar *object_path)
473 GDBusNodeInfo *node_info;
477 proxy = g_dbus_proxy_new_sync (c,
478 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
479 G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
481 g_dbus_connection_get_unique_name (c),
483 "org.freedesktop.DBus.Introspectable",
486 g_assert_no_error (error);
487 g_assert (proxy != NULL);
489 /* do this async to avoid libdbus-1 deadlocks */
491 g_dbus_proxy_call (proxy,
494 G_DBUS_CALL_FLAGS_NONE,
497 (GAsyncReadyCallback) introspect_callback,
499 g_main_loop_run (loop);
500 g_assert (xml_data != NULL);
502 node_info = g_dbus_node_info_new_for_xml (xml_data, &error);
503 g_assert_no_error (error);
504 g_assert (node_info != NULL);
507 while (node_info->interfaces != NULL && node_info->interfaces[ret] != NULL)
510 g_object_unref (proxy);
512 g_dbus_node_info_unref (node_info);
518 dyna_create_callback (GDBusProxy *proxy,
526 result = g_dbus_proxy_call_finish (proxy,
529 g_assert_no_error (error);
530 g_assert (result != NULL);
531 g_variant_unref (result);
533 g_main_loop_quit (loop);
536 /* Dynamically create @object_name under /foo/dyna */
538 dyna_create (GDBusConnection *c,
539 const gchar *object_name)
545 object_path = g_strconcat ("/foo/dyna/", object_name, NULL);
548 proxy = g_dbus_proxy_new_sync (c,
549 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
550 G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
552 g_dbus_connection_get_unique_name (c),
557 g_assert_no_error (error);
558 g_assert (proxy != NULL);
560 /* do this async to avoid libdbus-1 deadlocks */
561 g_dbus_proxy_call (proxy,
563 g_variant_new ("()"),
564 G_DBUS_CALL_FLAGS_NONE,
567 (GAsyncReadyCallback) dyna_create_callback,
569 g_main_loop_run (loop);
571 g_assert_no_error (error);
573 g_object_unref (proxy);
574 g_free (object_path);
581 guint num_unregistered_calls;
582 guint num_unregistered_subtree_calls;
583 guint num_subtree_nodes;
584 } ObjectRegistrationData;
587 on_object_unregistered (gpointer user_data)
589 ObjectRegistrationData *data = user_data;
591 data->num_unregistered_calls++;
595 on_subtree_unregistered (gpointer user_data)
597 ObjectRegistrationData *data = user_data;
599 data->num_unregistered_subtree_calls++;
603 _g_strv_has_string (const gchar* const * haystack,
608 for (n = 0; haystack != NULL && haystack[n] != NULL; n++)
610 if (g_strcmp0 (haystack[n], needle) == 0)
616 /* -------------------- */
619 subtree_enumerate (GDBusConnection *connection,
621 const gchar *object_path,
624 ObjectRegistrationData *data = user_data;
629 p = g_ptr_array_new ();
631 for (n = 0; n < data->num_subtree_nodes; n++)
633 g_ptr_array_add (p, g_strdup_printf ("vp%d", n));
634 g_ptr_array_add (p, g_strdup_printf ("evp%d", n));
636 g_ptr_array_add (p, NULL);
638 nodes = (gchar **) g_ptr_array_free (p, FALSE);
643 /* Only allows certain objects, and aborts on unknowns */
644 static GDBusInterfaceInfo **
645 subtree_introspect (GDBusConnection *connection,
647 const gchar *object_path,
651 const GDBusInterfaceInfo *interfaces[2] = {
652 NULL /* filled in below */, NULL
655 /* VPs implement the Foo interface, EVPs implement the Bar interface. The root
656 * does not implement any interfaces
662 else if (g_str_has_prefix (node, "vp"))
664 interfaces[0] = &foo_interface_info;
666 else if (g_str_has_prefix (node, "evp"))
668 interfaces[0] = &bar_interface_info;
672 g_assert_not_reached ();
675 return g_memdup2 (interfaces, 2 * sizeof (void *));
678 static const GDBusInterfaceVTable *
679 subtree_dispatch (GDBusConnection *connection,
681 const gchar *object_path,
682 const gchar *interface_name,
684 gpointer *out_user_data,
687 if (g_strcmp0 (interface_name, "org.example.Foo") == 0)
693 static const GDBusSubtreeVTable subtree_vtable =
700 /* -------------------- */
703 dynamic_subtree_enumerate (GDBusConnection *connection,
705 const gchar *object_path,
708 GPtrArray *data = user_data;
709 gchar **nodes = g_new (gchar*, data->len + 1);
712 for (n = 0; n < data->len; n++)
714 nodes[n] = g_strdup (g_ptr_array_index (data, n));
716 nodes[data->len] = NULL;
721 /* Allow all objects to be introspected */
722 static GDBusInterfaceInfo **
723 dynamic_subtree_introspect (GDBusConnection *connection,
725 const gchar *object_path,
729 const GDBusInterfaceInfo *interfaces[2] = { &dyna_interface_info, NULL };
731 return g_memdup2 (interfaces, 2 * sizeof (void *));
734 static const GDBusInterfaceVTable *
735 dynamic_subtree_dispatch (GDBusConnection *connection,
737 const gchar *object_path,
738 const gchar *interface_name,
740 gpointer *out_user_data,
743 *out_user_data = user_data;
744 return &dyna_interface_vtable;
747 static const GDBusSubtreeVTable dynamic_subtree_vtable =
749 dynamic_subtree_enumerate,
750 dynamic_subtree_introspect,
751 dynamic_subtree_dispatch
754 /* -------------------- */
758 const gchar *object_path;
759 gboolean check_remote_errors;
760 } TestDispatchThreadFuncArgs;
763 test_dispatch_thread_func (gpointer user_data)
765 TestDispatchThreadFuncArgs *args = user_data;
766 const gchar *object_path = args->object_path;
767 GDBusProxy *foo_proxy;
772 const gchar *value_str;
774 foo_proxy = g_dbus_proxy_new_sync (c,
775 G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS |
776 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
778 g_dbus_connection_get_unique_name (c),
783 g_assert (foo_proxy != NULL);
785 /* generic interfaces */
787 value = g_dbus_proxy_call_sync (foo_proxy,
788 "org.freedesktop.DBus.Peer.Ping",
790 G_DBUS_CALL_FLAGS_NONE,
794 g_assert_no_error (error);
795 g_assert (value != NULL);
796 g_variant_unref (value);
800 value = g_dbus_proxy_call_sync (foo_proxy,
802 g_variant_new ("(s)", "winwinwin"),
803 G_DBUS_CALL_FLAGS_NONE,
807 g_assert_no_error (error);
808 g_assert (value != NULL);
809 g_assert (g_variant_is_of_type (value, G_VARIANT_TYPE ("(s)")));
810 g_variant_get (value, "(&s)", &value_str);
811 g_assert_cmpstr (value_str, ==, "You passed the string 'winwinwin'. Jolly good!");
812 g_variant_unref (value);
815 value = g_dbus_proxy_call_sync (foo_proxy,
818 G_DBUS_CALL_FLAGS_NONE,
822 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_DBUS_ERROR);
823 g_assert_cmpstr (error->message, ==, "GDBus.Error:org.example.SomeError: How do you like them apples, buddy!");
824 g_error_free (error);
825 g_assert (value == NULL);
828 value = g_dbus_proxy_call_sync (foo_proxy,
830 g_variant_new ("(s)", "failfailfail"),
831 G_DBUS_CALL_FLAGS_NONE,
835 g_assert_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS);
836 g_assert_cmpstr (error->message, ==, "GDBus.Error:org.freedesktop.DBus.Error.InvalidArgs: Type of message, “(s)”, does not match expected type “()”");
837 g_error_free (error);
838 g_assert (value == NULL);
841 value = g_dbus_proxy_call_sync (foo_proxy,
844 G_DBUS_CALL_FLAGS_NONE,
848 g_assert_error (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD);
849 g_assert_cmpstr (error->message, ==, "GDBus.Error:org.freedesktop.DBus.Error.UnknownMethod: No such method “NonExistantMethod”");
850 g_error_free (error);
851 g_assert (value == NULL);
854 value = g_dbus_proxy_call_sync (foo_proxy,
855 "org.example.FooXYZ.NonExistant",
857 G_DBUS_CALL_FLAGS_NONE,
861 g_assert_error (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD);
862 g_error_free (error);
863 g_assert (value == NULL);
865 /* user properties */
867 value = g_dbus_proxy_call_sync (foo_proxy,
868 "org.freedesktop.DBus.Properties.Get",
869 g_variant_new ("(ss)",
872 G_DBUS_CALL_FLAGS_NONE,
876 g_assert_no_error (error);
877 g_assert (value != NULL);
878 g_assert (g_variant_is_of_type (value, G_VARIANT_TYPE ("(v)")));
879 g_variant_get (value, "(v)", &inner);
880 g_assert (g_variant_is_of_type (inner, G_VARIANT_TYPE_STRING));
881 g_assert_cmpstr (g_variant_get_string (inner, NULL), ==, "Property 'PropertyUno' Is What It Is!");
882 g_variant_unref (value);
883 g_variant_unref (inner);
886 value = g_dbus_proxy_call_sync (foo_proxy,
887 "org.freedesktop.DBus.Properties.Get",
888 g_variant_new ("(ss)",
891 G_DBUS_CALL_FLAGS_NONE,
895 g_assert (value == NULL);
896 g_assert_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS);
897 g_assert_cmpstr (error->message, ==, "GDBus.Error:org.freedesktop.DBus.Error.InvalidArgs: No such property “ThisDoesntExist”");
898 g_error_free (error);
901 value = g_dbus_proxy_call_sync (foo_proxy,
902 "org.freedesktop.DBus.Properties.Get",
903 g_variant_new ("(ss)",
906 G_DBUS_CALL_FLAGS_NONE,
910 g_assert (value == NULL);
911 g_assert_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS);
912 g_assert_cmpstr (error->message, ==, "GDBus.Error:org.freedesktop.DBus.Error.InvalidArgs: Property “NotReadable” is not readable");
913 g_error_free (error);
916 value = g_dbus_proxy_call_sync (foo_proxy,
917 "org.freedesktop.DBus.Properties.Set",
918 g_variant_new ("(ssv)",
921 g_variant_new_string ("But Writable you are!")),
922 G_DBUS_CALL_FLAGS_NONE,
926 g_assert (value == NULL);
927 if (args->check_remote_errors)
929 /* _with_closures variant doesn't support customizing error data. */
930 g_assert_error (error, G_DBUS_ERROR, G_DBUS_ERROR_SPAWN_FILE_INVALID);
931 g_assert_cmpstr (error->message, ==, "GDBus.Error:org.freedesktop.DBus.Error.Spawn.FileInvalid: Returning some error instead of writing the value ''But Writable you are!'' to the property 'NotReadable'");
933 g_assert (error != NULL && error->domain == G_DBUS_ERROR);
934 g_error_free (error);
937 value = g_dbus_proxy_call_sync (foo_proxy,
938 "org.freedesktop.DBus.Properties.Set",
939 g_variant_new ("(ssv)",
942 g_variant_new_uint32 (42)),
943 G_DBUS_CALL_FLAGS_NONE,
947 g_assert (value == NULL);
948 g_assert_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS);
949 g_assert_cmpstr (error->message, ==, "GDBus.Error:org.freedesktop.DBus.Error.InvalidArgs: Property “NotWritable” is not writable");
950 g_error_free (error);
953 value = g_dbus_proxy_call_sync (foo_proxy,
954 "org.freedesktop.DBus.Properties.GetAll",
955 g_variant_new ("(s)",
957 G_DBUS_CALL_FLAGS_NONE,
961 g_assert_no_error (error);
962 g_assert (value != NULL);
963 g_assert (g_variant_is_of_type (value, G_VARIANT_TYPE ("(a{sv})")));
964 s = g_variant_print (value, TRUE);
965 g_assert_cmpstr (s, ==, "({'PropertyUno': <\"Property 'PropertyUno' Is What It Is!\">, 'NotWritable': <\"Property 'NotWritable' Is What It Is!\">},)");
967 g_variant_unref (value);
969 g_object_unref (foo_proxy);
971 g_main_loop_quit (loop);
976 test_dispatch (const gchar *object_path,
977 gboolean check_remote_errors)
981 TestDispatchThreadFuncArgs args = {object_path, check_remote_errors};
983 /* run this in a thread to avoid deadlocks */
984 thread = g_thread_new ("test_dispatch",
985 test_dispatch_thread_func,
987 g_main_loop_run (loop);
988 g_thread_join (thread);
992 test_object_registration (void)
995 ObjectRegistrationData data;
996 GPtrArray *dyna_data;
998 guint boss_foo_reg_id;
999 guint boss_bar_reg_id;
1000 guint worker1_foo_reg_id;
1001 guint worker1p1_foo_reg_id;
1002 guint worker2_bar_reg_id;
1003 guint intern1_foo_reg_id;
1004 guint intern2_bar_reg_id;
1005 guint intern2_foo_reg_id;
1006 guint intern3_bar_reg_id;
1007 guint registration_id;
1008 guint subtree_registration_id;
1009 guint non_subtree_object_path_foo_reg_id;
1010 guint non_subtree_object_path_bar_reg_id;
1011 guint dyna_subtree_registration_id;
1012 guint num_successful_registrations;
1014 data.num_unregistered_calls = 0;
1015 data.num_unregistered_subtree_calls = 0;
1016 data.num_subtree_nodes = 0;
1018 num_successful_registrations = 0;
1021 c = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
1022 g_assert_no_error (error);
1023 g_assert (c != NULL);
1025 registration_id = g_dbus_connection_register_object (c,
1027 (GDBusInterfaceInfo *) &foo_interface_info,
1030 on_object_unregistered,
1032 g_assert_no_error (error);
1033 g_assert (registration_id > 0);
1034 boss_foo_reg_id = registration_id;
1035 num_successful_registrations++;
1037 registration_id = g_dbus_connection_register_object (c,
1039 (GDBusInterfaceInfo *) &bar_interface_info,
1042 on_object_unregistered,
1044 g_assert_no_error (error);
1045 g_assert (registration_id > 0);
1046 boss_bar_reg_id = registration_id;
1047 num_successful_registrations++;
1049 registration_id = g_dbus_connection_register_object (c,
1050 "/foo/boss/worker1",
1051 (GDBusInterfaceInfo *) &foo_interface_info,
1054 on_object_unregistered,
1056 g_assert_no_error (error);
1057 g_assert (registration_id > 0);
1058 worker1_foo_reg_id = registration_id;
1059 num_successful_registrations++;
1061 registration_id = g_dbus_connection_register_object (c,
1062 "/foo/boss/worker1p1",
1063 (GDBusInterfaceInfo *) &foo_interface_info,
1066 on_object_unregistered,
1068 g_assert_no_error (error);
1069 g_assert (registration_id > 0);
1070 worker1p1_foo_reg_id = registration_id;
1071 num_successful_registrations++;
1073 registration_id = g_dbus_connection_register_object (c,
1074 "/foo/boss/worker2",
1075 (GDBusInterfaceInfo *) &bar_interface_info,
1078 on_object_unregistered,
1080 g_assert_no_error (error);
1081 g_assert (registration_id > 0);
1082 worker2_bar_reg_id = registration_id;
1083 num_successful_registrations++;
1085 registration_id = g_dbus_connection_register_object (c,
1086 "/foo/boss/interns/intern1",
1087 (GDBusInterfaceInfo *) &foo_interface_info,
1090 on_object_unregistered,
1092 g_assert_no_error (error);
1093 g_assert (registration_id > 0);
1094 intern1_foo_reg_id = registration_id;
1095 num_successful_registrations++;
1097 /* ... and try again at another path */
1098 registration_id = g_dbus_connection_register_object (c,
1099 "/foo/boss/interns/intern2",
1100 (GDBusInterfaceInfo *) &bar_interface_info,
1103 on_object_unregistered,
1105 g_assert_no_error (error);
1106 g_assert (registration_id > 0);
1107 intern2_bar_reg_id = registration_id;
1108 num_successful_registrations++;
1110 /* register at the same path/interface - this should fail */
1111 registration_id = g_dbus_connection_register_object (c,
1112 "/foo/boss/interns/intern2",
1113 (GDBusInterfaceInfo *) &bar_interface_info,
1116 on_object_unregistered,
1118 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_EXISTS);
1119 g_assert (!g_dbus_error_is_remote_error (error));
1120 g_error_free (error);
1122 g_assert (registration_id == 0);
1124 /* register at different interface - shouldn't fail */
1125 registration_id = g_dbus_connection_register_object (c,
1126 "/foo/boss/interns/intern2",
1127 (GDBusInterfaceInfo *) &foo_interface_info,
1130 on_object_unregistered,
1132 g_assert_no_error (error);
1133 g_assert (registration_id > 0);
1134 intern2_foo_reg_id = registration_id;
1135 num_successful_registrations++;
1137 /* unregister it via the id */
1138 g_assert (g_dbus_connection_unregister_object (c, registration_id));
1139 g_main_context_iteration (NULL, FALSE);
1140 g_assert_cmpint (data.num_unregistered_calls, ==, 1);
1141 intern2_foo_reg_id = 0;
1143 /* register it back */
1144 registration_id = g_dbus_connection_register_object (c,
1145 "/foo/boss/interns/intern2",
1146 (GDBusInterfaceInfo *) &foo_interface_info,
1149 on_object_unregistered,
1151 g_assert_no_error (error);
1152 g_assert (registration_id > 0);
1153 intern2_foo_reg_id = registration_id;
1154 num_successful_registrations++;
1156 registration_id = g_dbus_connection_register_object (c,
1157 "/foo/boss/interns/intern3",
1158 (GDBusInterfaceInfo *) &bar_interface_info,
1161 on_object_unregistered,
1163 g_assert_no_error (error);
1164 g_assert (registration_id > 0);
1165 intern3_bar_reg_id = registration_id;
1166 num_successful_registrations++;
1168 /* now register a whole subtree at /foo/boss/executives */
1169 subtree_registration_id = g_dbus_connection_register_subtree (c,
1170 "/foo/boss/executives",
1172 G_DBUS_SUBTREE_FLAGS_NONE,
1174 on_subtree_unregistered,
1176 g_assert_no_error (error);
1177 g_assert (subtree_registration_id > 0);
1178 /* try registering it again.. this should fail */
1179 registration_id = g_dbus_connection_register_subtree (c,
1180 "/foo/boss/executives",
1182 G_DBUS_SUBTREE_FLAGS_NONE,
1184 on_subtree_unregistered,
1186 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_EXISTS);
1187 g_assert (!g_dbus_error_is_remote_error (error));
1188 g_error_free (error);
1190 g_assert (registration_id == 0);
1192 /* unregister it, then register it again */
1193 g_assert_cmpint (data.num_unregistered_subtree_calls, ==, 0);
1194 g_assert (g_dbus_connection_unregister_subtree (c, subtree_registration_id));
1195 g_main_context_iteration (NULL, FALSE);
1196 g_assert_cmpint (data.num_unregistered_subtree_calls, ==, 1);
1197 subtree_registration_id = g_dbus_connection_register_subtree (c,
1198 "/foo/boss/executives",
1200 G_DBUS_SUBTREE_FLAGS_NONE,
1202 on_subtree_unregistered,
1204 g_assert_no_error (error);
1205 g_assert (subtree_registration_id > 0);
1207 /* try to register something under /foo/boss/executives - this should work
1208 * because registered subtrees and registered objects can coexist.
1210 * Make the exported object implement *two* interfaces so we can check
1211 * that the right introspection handler is invoked.
1213 registration_id = g_dbus_connection_register_object (c,
1214 "/foo/boss/executives/non_subtree_object",
1215 (GDBusInterfaceInfo *) &bar_interface_info,
1218 on_object_unregistered,
1220 g_assert_no_error (error);
1221 g_assert (registration_id > 0);
1222 non_subtree_object_path_bar_reg_id = registration_id;
1223 num_successful_registrations++;
1224 registration_id = g_dbus_connection_register_object (c,
1225 "/foo/boss/executives/non_subtree_object",
1226 (GDBusInterfaceInfo *) &foo_interface_info,
1229 on_object_unregistered,
1231 g_assert_no_error (error);
1232 g_assert (registration_id > 0);
1233 non_subtree_object_path_foo_reg_id = registration_id;
1234 num_successful_registrations++;
1236 /* now register a dynamic subtree, spawning objects as they are called */
1237 dyna_data = g_ptr_array_new_with_free_func (g_free);
1238 dyna_subtree_registration_id = g_dbus_connection_register_subtree (c,
1240 &dynamic_subtree_vtable,
1241 G_DBUS_SUBTREE_FLAGS_DISPATCH_TO_UNENUMERATED_NODES,
1243 (GDestroyNotify)g_ptr_array_unref,
1245 g_assert_no_error (error);
1246 g_assert (dyna_subtree_registration_id > 0);
1248 /* First assert that we have no nodes in the dynamic subtree */
1249 nodes = get_nodes_at (c, "/foo/dyna");
1250 g_assert (nodes != NULL);
1251 g_assert_cmpint (g_strv_length (nodes), ==, 0);
1253 g_assert_cmpint (count_interfaces (c, "/foo/dyna"), ==, 4);
1255 /* Install three nodes in the dynamic subtree via the dyna_data backdoor and
1256 * assert that they show up correctly in the introspection data */
1257 g_ptr_array_add (dyna_data, g_strdup ("lol"));
1258 g_ptr_array_add (dyna_data, g_strdup ("cat"));
1259 g_ptr_array_add (dyna_data, g_strdup ("cheezburger"));
1260 nodes = get_nodes_at (c, "/foo/dyna");
1261 g_assert (nodes != NULL);
1262 g_assert_cmpint (g_strv_length (nodes), ==, 3);
1263 g_assert_cmpstr (nodes[0], ==, "cat");
1264 g_assert_cmpstr (nodes[1], ==, "cheezburger");
1265 g_assert_cmpstr (nodes[2], ==, "lol");
1267 g_assert_cmpint (count_interfaces (c, "/foo/dyna/lol"), ==, 4);
1268 g_assert_cmpint (count_interfaces (c, "/foo/dyna/cat"), ==, 4);
1269 g_assert_cmpint (count_interfaces (c, "/foo/dyna/cheezburger"), ==, 4);
1271 /* Call a non-existing object path and assert that it has been created */
1272 dyna_create (c, "dynamicallycreated");
1273 nodes = get_nodes_at (c, "/foo/dyna");
1274 g_assert (nodes != NULL);
1275 g_assert_cmpint (g_strv_length (nodes), ==, 4);
1276 g_assert_cmpstr (nodes[0], ==, "cat");
1277 g_assert_cmpstr (nodes[1], ==, "cheezburger");
1278 g_assert_cmpstr (nodes[2], ==, "dynamicallycreated");
1279 g_assert_cmpstr (nodes[3], ==, "lol");
1281 g_assert_cmpint (count_interfaces (c, "/foo/dyna/dynamicallycreated"), ==, 4);
1283 /* now check that the object hierarchy is properly generated... yes, it's a bit
1284 * perverse that we round-trip to the bus to introspect ourselves ;-)
1286 nodes = get_nodes_at (c, "/");
1287 g_assert (nodes != NULL);
1288 g_assert_cmpint (g_strv_length (nodes), ==, 1);
1289 g_assert_cmpstr (nodes[0], ==, "foo");
1291 g_assert_cmpint (count_interfaces (c, "/"), ==, 0);
1293 nodes = get_nodes_at (c, "/foo");
1294 g_assert (nodes != NULL);
1295 g_assert_cmpint (g_strv_length (nodes), ==, 2);
1296 g_assert_cmpstr (nodes[0], ==, "boss");
1297 g_assert_cmpstr (nodes[1], ==, "dyna");
1299 g_assert_cmpint (count_interfaces (c, "/foo"), ==, 0);
1301 nodes = get_nodes_at (c, "/foo/boss");
1302 g_assert (nodes != NULL);
1303 g_assert_cmpint (g_strv_length (nodes), ==, 5);
1304 g_assert (_g_strv_has_string ((const gchar* const *) nodes, "worker1"));
1305 g_assert (_g_strv_has_string ((const gchar* const *) nodes, "worker1p1"));
1306 g_assert (_g_strv_has_string ((const gchar* const *) nodes, "worker2"));
1307 g_assert (_g_strv_has_string ((const gchar* const *) nodes, "interns"));
1308 g_assert (_g_strv_has_string ((const gchar* const *) nodes, "executives"));
1310 /* any registered object always implement org.freedesktop.DBus.[Peer,Introspectable,Properties] */
1311 g_assert_cmpint (count_interfaces (c, "/foo/boss"), ==, 5);
1312 g_assert (has_interface (c, "/foo/boss", foo_interface_info.name));
1313 g_assert (has_interface (c, "/foo/boss", bar_interface_info.name));
1315 /* check subtree nodes - we should have only non_subtree_object in /foo/boss/executives
1316 * because data.num_subtree_nodes is 0
1318 nodes = get_nodes_at (c, "/foo/boss/executives");
1319 g_assert (nodes != NULL);
1320 g_assert (_g_strv_has_string ((const gchar* const *) nodes, "non_subtree_object"));
1321 g_assert_cmpint (g_strv_length (nodes), ==, 1);
1323 g_assert_cmpint (count_interfaces (c, "/foo/boss/executives"), ==, 0);
1325 /* now change data.num_subtree_nodes and check */
1326 data.num_subtree_nodes = 2;
1327 nodes = get_nodes_at (c, "/foo/boss/executives");
1328 g_assert (nodes != NULL);
1329 g_assert_cmpint (g_strv_length (nodes), ==, 5);
1330 g_assert (_g_strv_has_string ((const gchar* const *) nodes, "non_subtree_object"));
1331 g_assert (_g_strv_has_string ((const gchar* const *) nodes, "vp0"));
1332 g_assert (_g_strv_has_string ((const gchar* const *) nodes, "vp1"));
1333 g_assert (_g_strv_has_string ((const gchar* const *) nodes, "evp0"));
1334 g_assert (_g_strv_has_string ((const gchar* const *) nodes, "evp1"));
1335 /* check that /foo/boss/executives/non_subtree_object is not handled by the
1336 * subtree handlers - we can do this because objects from subtree handlers
1337 * has exactly one interface and non_subtree_object has two
1339 g_assert_cmpint (count_interfaces (c, "/foo/boss/executives/non_subtree_object"), ==, 5);
1340 g_assert (has_interface (c, "/foo/boss/executives/non_subtree_object", foo_interface_info.name));
1341 g_assert (has_interface (c, "/foo/boss/executives/non_subtree_object", bar_interface_info.name));
1342 /* check that the vp and evp objects are handled by the subtree handlers */
1343 g_assert_cmpint (count_interfaces (c, "/foo/boss/executives/vp0"), ==, 4);
1344 g_assert_cmpint (count_interfaces (c, "/foo/boss/executives/vp1"), ==, 4);
1345 g_assert_cmpint (count_interfaces (c, "/foo/boss/executives/evp0"), ==, 4);
1346 g_assert_cmpint (count_interfaces (c, "/foo/boss/executives/evp1"), ==, 4);
1347 g_assert (has_interface (c, "/foo/boss/executives/vp0", foo_interface_info.name));
1348 g_assert (has_interface (c, "/foo/boss/executives/vp1", foo_interface_info.name));
1349 g_assert (has_interface (c, "/foo/boss/executives/evp0", bar_interface_info.name));
1350 g_assert (has_interface (c, "/foo/boss/executives/evp1", bar_interface_info.name));
1352 data.num_subtree_nodes = 3;
1353 nodes = get_nodes_at (c, "/foo/boss/executives");
1354 g_assert (nodes != NULL);
1355 g_assert_cmpint (g_strv_length (nodes), ==, 7);
1356 g_assert (_g_strv_has_string ((const gchar* const *) nodes, "non_subtree_object"));
1357 g_assert (_g_strv_has_string ((const gchar* const *) nodes, "vp0"));
1358 g_assert (_g_strv_has_string ((const gchar* const *) nodes, "vp1"));
1359 g_assert (_g_strv_has_string ((const gchar* const *) nodes, "vp2"));
1360 g_assert (_g_strv_has_string ((const gchar* const *) nodes, "evp0"));
1361 g_assert (_g_strv_has_string ((const gchar* const *) nodes, "evp1"));
1362 g_assert (_g_strv_has_string ((const gchar* const *) nodes, "evp2"));
1365 /* This is to check that a bug (rather, class of bugs) in gdbusconnection.c's
1367 * g_dbus_connection_list_registered_unlocked()
1369 * where /foo/boss/worker1 reported a child '1', is now fixed.
1371 nodes = get_nodes_at (c, "/foo/boss/worker1");
1372 g_assert (nodes != NULL);
1373 g_assert_cmpint (g_strv_length (nodes), ==, 0);
1376 /* check that calls are properly dispatched to the functions in foo_vtable for objects
1377 * implementing the org.example.Foo interface
1379 * We do this for both a regular registered object (/foo/boss) and also for an object
1380 * registered through the subtree mechanism.
1382 test_dispatch ("/foo/boss", TRUE);
1383 test_dispatch ("/foo/boss/executives/vp0", TRUE);
1385 /* To prevent from exiting and attaching a D-Bus tool like D-Feet; uncomment: */
1387 g_debug ("Point D-feet or other tool at: %s", g_test_dbus_get_temporary_address());
1388 g_main_loop_run (loop);
1391 /* check that unregistering the subtree handler works */
1392 g_assert_cmpint (data.num_unregistered_subtree_calls, ==, 1);
1393 g_assert (g_dbus_connection_unregister_subtree (c, subtree_registration_id));
1394 g_main_context_iteration (NULL, FALSE);
1395 g_assert_cmpint (data.num_unregistered_subtree_calls, ==, 2);
1396 nodes = get_nodes_at (c, "/foo/boss/executives");
1397 g_assert (nodes != NULL);
1398 g_assert_cmpint (g_strv_length (nodes), ==, 1);
1399 g_assert (_g_strv_has_string ((const gchar* const *) nodes, "non_subtree_object"));
1402 g_assert (g_dbus_connection_unregister_object (c, boss_foo_reg_id));
1403 g_assert (g_dbus_connection_unregister_object (c, boss_bar_reg_id));
1404 g_assert (g_dbus_connection_unregister_object (c, worker1_foo_reg_id));
1405 g_assert (g_dbus_connection_unregister_object (c, worker1p1_foo_reg_id));
1406 g_assert (g_dbus_connection_unregister_object (c, worker2_bar_reg_id));
1407 g_assert (g_dbus_connection_unregister_object (c, intern1_foo_reg_id));
1408 g_assert (g_dbus_connection_unregister_object (c, intern2_bar_reg_id));
1409 g_assert (g_dbus_connection_unregister_object (c, intern2_foo_reg_id));
1410 g_assert (g_dbus_connection_unregister_object (c, intern3_bar_reg_id));
1411 g_assert (g_dbus_connection_unregister_object (c, non_subtree_object_path_bar_reg_id));
1412 g_assert (g_dbus_connection_unregister_object (c, non_subtree_object_path_foo_reg_id));
1414 g_main_context_iteration (NULL, FALSE);
1415 g_assert_cmpint (data.num_unregistered_calls, ==, num_successful_registrations);
1417 /* check that we no longer export any objects - TODO: it looks like there's a bug in
1418 * libdbus-1 here: libdbus still reports the '/foo' object; so disable the test for now
1421 nodes = get_nodes_at (c, "/");
1422 g_assert (nodes != NULL);
1423 g_assert_cmpint (g_strv_length (nodes), ==, 0);
1431 test_object_registration_with_closures (void)
1434 guint registration_id;
1437 c = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
1438 g_assert_no_error (error);
1439 g_assert (c != NULL);
1441 registration_id = g_dbus_connection_register_object_with_closures (c,
1443 (GDBusInterfaceInfo *) &foo_interface_info,
1444 g_cclosure_new (G_CALLBACK (foo_method_call), NULL, NULL),
1445 g_cclosure_new (G_CALLBACK (foo_get_property), NULL, NULL),
1446 g_cclosure_new (G_CALLBACK (foo_set_property), NULL, NULL),
1448 g_assert_no_error (error);
1449 g_assert (registration_id > 0);
1451 test_dispatch ("/foo/boss", FALSE);
1453 g_assert (g_dbus_connection_unregister_object (c, registration_id));
1458 static const GDBusInterfaceInfo test_interface_info1 =
1462 (GDBusMethodInfo **) NULL,
1463 (GDBusSignalInfo **) NULL,
1464 (GDBusPropertyInfo **) NULL,
1468 static const GDBusInterfaceInfo test_interface_info2 =
1471 "org.freedesktop.DBus.Properties",
1472 (GDBusMethodInfo **) NULL,
1473 (GDBusSignalInfo **) NULL,
1474 (GDBusPropertyInfo **) NULL,
1479 check_interfaces (GDBusConnection *c,
1480 const gchar *object_path,
1481 const gchar **interfaces)
1486 GDBusNodeInfo *node_info;
1490 proxy = g_dbus_proxy_new_sync (c,
1491 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
1492 G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
1494 g_dbus_connection_get_unique_name (c),
1496 "org.freedesktop.DBus.Introspectable",
1499 g_assert_no_error (error);
1500 g_assert (proxy != NULL);
1502 /* do this async to avoid libdbus-1 deadlocks */
1504 g_dbus_proxy_call (proxy,
1507 G_DBUS_CALL_FLAGS_NONE,
1510 (GAsyncReadyCallback) introspect_callback,
1512 g_main_loop_run (loop);
1513 g_assert (xml_data != NULL);
1515 node_info = g_dbus_node_info_new_for_xml (xml_data, &error);
1516 g_assert_no_error (error);
1517 g_assert (node_info != NULL);
1519 g_assert (node_info->interfaces != NULL);
1520 for (i = 0; node_info->interfaces[i]; i++) ;
1522 if (g_strv_length ((gchar**)interfaces) != i - 1)
1524 g_printerr ("expected ");
1525 for (i = 0; interfaces[i]; i++)
1526 g_printerr ("%s ", interfaces[i]);
1527 g_printerr ("\ngot ");
1528 for (i = 0; node_info->interfaces[i]; i++)
1529 g_printerr ("%s ", node_info->interfaces[i]->name);
1533 g_assert_cmpint (g_strv_length ((gchar**)interfaces), ==, i - 1);
1535 for (i = 0; interfaces[i]; i++)
1537 for (j = 0; node_info->interfaces[j]; j++)
1539 if (strcmp (interfaces[i], node_info->interfaces[j]->name) == 0)
1543 g_assert_not_reached ();
1548 g_object_unref (proxy);
1550 g_dbus_node_info_unref (node_info);
1554 test_registered_interfaces (void)
1558 const gchar *interfaces[] = {
1560 "org.freedesktop.DBus.Properties",
1561 "org.freedesktop.DBus.Introspectable",
1566 c = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
1567 g_assert_no_error (error);
1568 g_assert (c != NULL);
1570 id1 = g_dbus_connection_register_object (c,
1572 (GDBusInterfaceInfo *) &test_interface_info1,
1577 g_assert_no_error (error);
1579 id2 = g_dbus_connection_register_object (c,
1581 (GDBusInterfaceInfo *) &test_interface_info2,
1586 g_assert_no_error (error);
1589 check_interfaces (c, "/test", interfaces);
1591 g_assert (g_dbus_connection_unregister_object (c, id1));
1592 g_assert (g_dbus_connection_unregister_object (c, id2));
1597 /* ---------------------------------------------------------------------------------------------------- */
1600 test_async_method_call (GDBusConnection *connection,
1601 const gchar *sender,
1602 const gchar *object_path,
1603 const gchar *interface_name,
1604 const gchar *method_name,
1605 GVariant *parameters,
1606 GDBusMethodInvocation *invocation,
1609 const GDBusPropertyInfo *property;
1611 /* Strictly speaking, this function should also expect to receive
1612 * method calls not on the org.freedesktop.DBus.Properties interface,
1613 * but we don't do any during this testcase, so assert that.
1615 g_assert_cmpstr (interface_name, ==, "org.freedesktop.DBus.Properties");
1616 g_assert (g_dbus_method_invocation_get_method_info (invocation) == NULL);
1618 property = g_dbus_method_invocation_get_property_info (invocation);
1620 /* We should never be seeing any property calls on the com.example.Bar
1621 * interface because it doesn't export any properties.
1623 * In each case below make sure the interface is org.example.Foo.
1626 /* Do a whole lot of asserts to make sure that invalid calls are still
1627 * getting properly rejected by GDBusConnection and that our
1628 * environment is as we expect it to be.
1630 if (g_str_equal (method_name, "Get"))
1632 const gchar *iface_name, *prop_name;
1634 g_variant_get (parameters, "(&s&s)", &iface_name, &prop_name);
1635 g_assert_cmpstr (iface_name, ==, "org.example.Foo");
1636 g_assert (property != NULL);
1637 g_assert_cmpstr (prop_name, ==, property->name);
1638 g_assert (property->flags & G_DBUS_PROPERTY_INFO_FLAGS_READABLE);
1639 g_dbus_method_invocation_return_value (invocation, g_variant_new ("(v)", g_variant_new_string (prop_name)));
1642 else if (g_str_equal (method_name, "Set"))
1644 const gchar *iface_name, *prop_name;
1647 g_variant_get (parameters, "(&s&sv)", &iface_name, &prop_name, &value);
1648 g_assert_cmpstr (iface_name, ==, "org.example.Foo");
1649 g_assert (property != NULL);
1650 g_assert_cmpstr (prop_name, ==, property->name);
1651 g_assert (property->flags & G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE);
1652 g_assert (g_variant_is_of_type (value, G_VARIANT_TYPE (property->signature)));
1653 g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
1654 g_variant_unref (value);
1657 else if (g_str_equal (method_name, "GetAll"))
1659 const gchar *iface_name;
1661 g_variant_get (parameters, "(&s)", &iface_name);
1662 g_assert_cmpstr (iface_name, ==, "org.example.Foo");
1663 g_assert (property == NULL);
1664 g_dbus_method_invocation_return_value (invocation,
1665 g_variant_new_parsed ("({ 'PropertyUno': < 'uno' >,"
1666 " 'NotWritable': < 'notwrite' > },)"));
1670 g_assert_not_reached ();
1673 static gint outstanding_cases;
1676 ensure_result_cb (GObject *source,
1677 GAsyncResult *result,
1680 GDBusConnection *connection = G_DBUS_CONNECTION (source);
1683 reply = g_dbus_connection_call_finish (connection, result, NULL);
1685 if (user_data == NULL)
1687 /* Expected an error */
1688 g_assert (reply == NULL);
1692 /* Expected a reply of a particular format. */
1695 g_assert (reply != NULL);
1696 str = g_variant_print (reply, TRUE);
1697 g_assert_cmpstr (str, ==, (const gchar *) user_data);
1700 g_variant_unref (reply);
1703 g_assert_cmpint (outstanding_cases, >, 0);
1704 outstanding_cases--;
1708 test_async_case (GDBusConnection *connection,
1709 const gchar *expected_reply,
1710 const gchar *method,
1711 const gchar *format_string,
1716 va_start (ap, format_string);
1718 g_dbus_connection_call (connection, g_dbus_connection_get_unique_name (connection), "/foo",
1719 "org.freedesktop.DBus.Properties", method, g_variant_new_va (format_string, NULL, &ap),
1720 NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, ensure_result_cb, (gpointer) expected_reply);
1724 outstanding_cases++;
1728 test_async_properties (void)
1730 GError *error = NULL;
1731 guint registration_id, registration_id2;
1732 static const GDBusInterfaceVTable vtable = {
1733 test_async_method_call, NULL, NULL
1736 c = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
1737 g_assert_no_error (error);
1738 g_assert (c != NULL);
1740 registration_id = g_dbus_connection_register_object (c,
1742 (GDBusInterfaceInfo *) &foo_interface_info,
1743 &vtable, NULL, NULL, &error);
1744 g_assert_no_error (error);
1745 g_assert (registration_id);
1746 registration_id2 = g_dbus_connection_register_object (c,
1748 (GDBusInterfaceInfo *) &foo2_interface_info,
1749 &vtable, NULL, NULL, &error);
1750 g_assert_no_error (error);
1751 g_assert (registration_id);
1753 test_async_case (c, NULL, "random", "()");
1755 /* Test a variety of error cases */
1756 test_async_case (c, NULL, "Get", "(si)", "wrong signature", 5);
1757 test_async_case (c, NULL, "Get", "(ss)", "org.example.WrongInterface", "zzz");
1758 test_async_case (c, NULL, "Get", "(ss)", "org.example.Foo", "NoSuchProperty");
1759 test_async_case (c, NULL, "Get", "(ss)", "org.example.Foo", "NotReadable");
1761 test_async_case (c, NULL, "Set", "(si)", "wrong signature", 5);
1762 test_async_case (c, NULL, "Set", "(ssv)", "org.example.WrongInterface", "zzz", g_variant_new_string (""));
1763 test_async_case (c, NULL, "Set", "(ssv)", "org.example.Foo", "NoSuchProperty", g_variant_new_string (""));
1764 test_async_case (c, NULL, "Set", "(ssv)", "org.example.Foo", "NotWritable", g_variant_new_string (""));
1765 test_async_case (c, NULL, "Set", "(ssv)", "org.example.Foo", "PropertyUno", g_variant_new_object_path ("/wrong"));
1767 test_async_case (c, NULL, "GetAll", "(si)", "wrong signature", 5);
1768 test_async_case (c, NULL, "GetAll", "(s)", "org.example.WrongInterface");
1770 /* Make sure that we get no unexpected async property calls for com.example.Foo2 */
1771 test_async_case (c, NULL, "Get", "(ss)", "org.example.Foo2", "zzz");
1772 test_async_case (c, NULL, "Set", "(ssv)", "org.example.Foo2", "zzz", g_variant_new_string (""));
1773 test_async_case (c, "(@a{sv} {},)", "GetAll", "(s)", "org.example.Foo2");
1775 /* Now do the proper things */
1776 test_async_case (c, "(<'PropertyUno'>,)", "Get", "(ss)", "org.example.Foo", "PropertyUno");
1777 test_async_case (c, "(<'NotWritable'>,)", "Get", "(ss)", "org.example.Foo", "NotWritable");
1778 test_async_case (c, "()", "Set", "(ssv)", "org.example.Foo", "PropertyUno", g_variant_new_string (""));
1779 test_async_case (c, "()", "Set", "(ssv)", "org.example.Foo", "NotReadable", g_variant_new_string (""));
1780 test_async_case (c, "({'PropertyUno': <'uno'>, 'NotWritable': <'notwrite'>},)", "GetAll", "(s)", "org.example.Foo");
1782 while (outstanding_cases)
1783 g_main_context_iteration (NULL, TRUE);
1785 g_dbus_connection_unregister_object (c, registration_id);
1786 g_dbus_connection_unregister_object (c, registration_id2);
1790 /* ---------------------------------------------------------------------------------------------------- */
1798 g_test_init (&argc, &argv, NULL);
1800 /* all the tests rely on a shared main loop */
1801 loop = g_main_loop_new (NULL, FALSE);
1803 g_test_add_func ("/gdbus/object-registration", test_object_registration);
1804 g_test_add_func ("/gdbus/object-registration-with-closures", test_object_registration_with_closures);
1805 g_test_add_func ("/gdbus/registered-interfaces", test_registered_interfaces);
1806 g_test_add_func ("/gdbus/async-properties", test_async_properties);
1808 /* TODO: check that we spit out correct introspection data */
1809 /* TODO: check that registering a whole subtree works */
1811 ret = session_bus_run ();
1813 g_main_loop_unref (loop);