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, see <http://www.gnu.org/licenses/>.
18 * Author: David Zeuthen <davidz@redhat.com>
25 #include "gdbus-tests.h"
27 /* all tests rely on a shared mainloop */
28 static GMainLoop
*loop
= NULL
;
30 static GDBusConnection
*c
= NULL
;
32 /* ---------------------------------------------------------------------------------------------------- */
33 /* Test that we can export objects, the hierarchy is correct and the right handlers are invoked */
34 /* ---------------------------------------------------------------------------------------------------- */
36 static const GDBusArgInfo foo_method1_in_args
=
43 static const GDBusArgInfo
* const foo_method1_in_arg_pointers
[] = {&foo_method1_in_args
, NULL
};
45 static const GDBusArgInfo foo_method1_out_args
=
52 static const GDBusArgInfo
* const foo_method1_out_arg_pointers
[] = {&foo_method1_out_args
, NULL
};
54 static const GDBusMethodInfo foo_method_info_method1
=
58 (GDBusArgInfo
**) &foo_method1_in_arg_pointers
,
59 (GDBusArgInfo
**) &foo_method1_out_arg_pointers
,
62 static const GDBusMethodInfo foo_method_info_method2
=
70 static const GDBusMethodInfo
* const foo_method_info_pointers
[] = {&foo_method_info_method1
, &foo_method_info_method2
, NULL
};
72 static const GDBusSignalInfo foo_signal_info
=
79 static const GDBusSignalInfo
* const foo_signal_info_pointers
[] = {&foo_signal_info
, NULL
};
81 static const GDBusPropertyInfo foo_property_info
[] =
87 G_DBUS_PROPERTY_INFO_FLAGS_READABLE
| G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE
,
94 G_DBUS_PROPERTY_INFO_FLAGS_READABLE
,
101 G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE
,
105 static const GDBusPropertyInfo
* const foo_property_info_pointers
[] =
107 &foo_property_info
[0],
108 &foo_property_info
[1],
109 &foo_property_info
[2],
113 static const GDBusInterfaceInfo foo_interface_info
=
117 (GDBusMethodInfo
**) &foo_method_info_pointers
,
118 (GDBusSignalInfo
**) &foo_signal_info_pointers
,
119 (GDBusPropertyInfo
**)&foo_property_info_pointers
,
123 /* Foo2 is just Foo without the properties */
124 static const GDBusInterfaceInfo foo2_interface_info
=
128 (GDBusMethodInfo
**) &foo_method_info_pointers
,
129 (GDBusSignalInfo
**) &foo_signal_info_pointers
,
133 foo_method_call (GDBusConnection
*connection
,
135 const gchar
*object_path
,
136 const gchar
*interface_name
,
137 const gchar
*method_name
,
138 GVariant
*parameters
,
139 GDBusMethodInvocation
*invocation
,
142 if (g_strcmp0 (method_name
, "Method1") == 0)
146 g_variant_get (parameters
, "(&s)", &input
);
147 output
= g_strdup_printf ("You passed the string '%s'. Jolly good!", input
);
148 g_dbus_method_invocation_return_value (invocation
, g_variant_new ("(s)", output
));
153 g_dbus_method_invocation_return_dbus_error (invocation
,
154 "org.example.SomeError",
155 "How do you like them apples, buddy!");
160 foo_get_property (GDBusConnection
*connection
,
162 const gchar
*object_path
,
163 const gchar
*interface_name
,
164 const gchar
*property_name
,
170 s
= g_strdup_printf ("Property '%s' Is What It Is!", property_name
);
171 ret
= g_variant_new_string (s
);
177 foo_set_property (GDBusConnection
*connection
,
179 const gchar
*object_path
,
180 const gchar
*interface_name
,
181 const gchar
*property_name
,
187 s
= g_variant_print (value
, TRUE
);
190 G_DBUS_ERROR_SPAWN_FILE_INVALID
,
191 "Returning some error instead of writing the value '%s' to the property '%s'",
197 static const GDBusInterfaceVTable foo_vtable
=
204 /* -------------------- */
206 static const GDBusMethodInfo bar_method_info
[] =
223 static const GDBusMethodInfo
* const bar_method_info_pointers
[] = {&bar_method_info
[0], &bar_method_info
[1], NULL
};
225 static const GDBusSignalInfo bar_signal_info
[] =
234 static const GDBusSignalInfo
* const bar_signal_info_pointers
[] = {&bar_signal_info
[0], NULL
};
236 static const GDBusPropertyInfo bar_property_info
[] =
242 G_DBUS_PROPERTY_INFO_FLAGS_READABLE
,
246 static const GDBusPropertyInfo
* const bar_property_info_pointers
[] = {&bar_property_info
[0], NULL
};
248 static const GDBusInterfaceInfo bar_interface_info
=
252 (GDBusMethodInfo
**) bar_method_info_pointers
,
253 (GDBusSignalInfo
**) bar_signal_info_pointers
,
254 (GDBusPropertyInfo
**) bar_property_info_pointers
,
258 /* -------------------- */
260 static const GDBusMethodInfo dyna_method_info
[] =
270 static const GDBusMethodInfo
* const dyna_method_info_pointers
[] = {&dyna_method_info
[0], NULL
};
272 static const GDBusInterfaceInfo dyna_interface_info
=
276 (GDBusMethodInfo
**) dyna_method_info_pointers
,
277 NULL
, /* no signals */
278 NULL
, /* no properties */
283 dyna_cyber (GDBusConnection
*connection
,
285 const gchar
*object_path
,
286 const gchar
*interface_name
,
287 const gchar
*method_name
,
288 GVariant
*parameters
,
289 GDBusMethodInvocation
*invocation
,
292 GPtrArray
*data
= user_data
;
296 node_name
= strrchr (object_path
, '/') + 1;
298 /* Add new node if it is not already known */
299 for (n
= 0; n
< data
->len
; n
++)
301 if (g_strcmp0 (g_ptr_array_index (data
, n
), node_name
) == 0)
304 g_ptr_array_add (data
, g_strdup(node_name
));
307 g_dbus_method_invocation_return_value (invocation
, NULL
);
310 static const GDBusInterfaceVTable dyna_interface_vtable
=
317 /* ---------------------------------------------------------------------------------------------------- */
320 introspect_callback (GDBusProxy
*proxy
,
324 gchar
**xml_data
= user_data
;
329 result
= g_dbus_proxy_call_finish (proxy
,
332 g_assert_no_error (error
);
333 g_assert (result
!= NULL
);
334 g_variant_get (result
, "(s)", xml_data
);
335 g_variant_unref (result
);
337 g_main_loop_quit (loop
);
341 get_nodes_at (GDBusConnection
*c
,
342 const gchar
*object_path
)
348 GDBusNodeInfo
*node_info
;
352 proxy
= g_dbus_proxy_new_sync (c
,
353 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES
|
354 G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS
,
356 g_dbus_connection_get_unique_name (c
),
358 "org.freedesktop.DBus.Introspectable",
361 g_assert_no_error (error
);
362 g_assert (proxy
!= NULL
);
364 /* do this async to avoid libdbus-1 deadlocks */
366 g_dbus_proxy_call (proxy
,
369 G_DBUS_CALL_FLAGS_NONE
,
372 (GAsyncReadyCallback
) introspect_callback
,
374 g_main_loop_run (loop
);
375 g_assert (xml_data
!= NULL
);
377 node_info
= g_dbus_node_info_new_for_xml (xml_data
, &error
);
378 g_assert_no_error (error
);
379 g_assert (node_info
!= NULL
);
381 p
= g_ptr_array_new ();
382 for (n
= 0; node_info
->nodes
!= NULL
&& node_info
->nodes
[n
] != NULL
; n
++)
384 const GDBusNodeInfo
*sub_node_info
= node_info
->nodes
[n
];
385 g_ptr_array_add (p
, g_strdup (sub_node_info
->path
));
387 g_ptr_array_add (p
, NULL
);
389 g_object_unref (proxy
);
391 g_dbus_node_info_unref (node_info
);
393 return (gchar
**) g_ptr_array_free (p
, FALSE
);
397 has_interface (GDBusConnection
*c
,
398 const gchar
*object_path
,
399 const gchar
*interface_name
)
404 GDBusNodeInfo
*node_info
;
408 proxy
= g_dbus_proxy_new_sync (c
,
409 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES
|
410 G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS
,
412 g_dbus_connection_get_unique_name (c
),
414 "org.freedesktop.DBus.Introspectable",
417 g_assert_no_error (error
);
418 g_assert (proxy
!= NULL
);
420 /* do this async to avoid libdbus-1 deadlocks */
422 g_dbus_proxy_call (proxy
,
425 G_DBUS_CALL_FLAGS_NONE
,
428 (GAsyncReadyCallback
) introspect_callback
,
430 g_main_loop_run (loop
);
431 g_assert (xml_data
!= NULL
);
433 node_info
= g_dbus_node_info_new_for_xml (xml_data
, &error
);
434 g_assert_no_error (error
);
435 g_assert (node_info
!= NULL
);
437 ret
= (g_dbus_node_info_lookup_interface (node_info
, interface_name
) != NULL
);
439 g_object_unref (proxy
);
441 g_dbus_node_info_unref (node_info
);
447 count_interfaces (GDBusConnection
*c
,
448 const gchar
*object_path
)
453 GDBusNodeInfo
*node_info
;
457 proxy
= g_dbus_proxy_new_sync (c
,
458 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES
|
459 G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS
,
461 g_dbus_connection_get_unique_name (c
),
463 "org.freedesktop.DBus.Introspectable",
466 g_assert_no_error (error
);
467 g_assert (proxy
!= NULL
);
469 /* do this async to avoid libdbus-1 deadlocks */
471 g_dbus_proxy_call (proxy
,
474 G_DBUS_CALL_FLAGS_NONE
,
477 (GAsyncReadyCallback
) introspect_callback
,
479 g_main_loop_run (loop
);
480 g_assert (xml_data
!= NULL
);
482 node_info
= g_dbus_node_info_new_for_xml (xml_data
, &error
);
483 g_assert_no_error (error
);
484 g_assert (node_info
!= NULL
);
487 while (node_info
->interfaces
!= NULL
&& node_info
->interfaces
[ret
] != NULL
)
490 g_object_unref (proxy
);
492 g_dbus_node_info_unref (node_info
);
498 dyna_create_callback (GDBusProxy
*proxy
,
506 result
= g_dbus_proxy_call_finish (proxy
,
509 g_assert_no_error (error
);
510 g_assert (result
!= NULL
);
511 g_variant_unref (result
);
513 g_main_loop_quit (loop
);
516 /* Dynamically create @object_name under /foo/dyna */
518 dyna_create (GDBusConnection
*c
,
519 const gchar
*object_name
)
525 object_path
= g_strconcat ("/foo/dyna/", object_name
, NULL
);
528 proxy
= g_dbus_proxy_new_sync (c
,
529 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES
|
530 G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS
,
532 g_dbus_connection_get_unique_name (c
),
537 g_assert_no_error (error
);
538 g_assert (proxy
!= NULL
);
540 /* do this async to avoid libdbus-1 deadlocks */
541 g_dbus_proxy_call (proxy
,
543 g_variant_new ("()"),
544 G_DBUS_CALL_FLAGS_NONE
,
547 (GAsyncReadyCallback
) dyna_create_callback
,
549 g_main_loop_run (loop
);
551 g_assert_no_error (error
);
553 g_object_unref (proxy
);
554 g_free (object_path
);
561 guint num_unregistered_calls
;
562 guint num_unregistered_subtree_calls
;
563 guint num_subtree_nodes
;
564 } ObjectRegistrationData
;
567 on_object_unregistered (gpointer user_data
)
569 ObjectRegistrationData
*data
= user_data
;
571 data
->num_unregistered_calls
++;
575 on_subtree_unregistered (gpointer user_data
)
577 ObjectRegistrationData
*data
= user_data
;
579 data
->num_unregistered_subtree_calls
++;
583 _g_strv_has_string (const gchar
* const * haystack
,
588 for (n
= 0; haystack
!= NULL
&& haystack
[n
] != NULL
; n
++)
590 if (g_strcmp0 (haystack
[n
], needle
) == 0)
596 /* -------------------- */
599 subtree_enumerate (GDBusConnection
*connection
,
601 const gchar
*object_path
,
604 ObjectRegistrationData
*data
= user_data
;
609 p
= g_ptr_array_new ();
611 for (n
= 0; n
< data
->num_subtree_nodes
; n
++)
613 g_ptr_array_add (p
, g_strdup_printf ("vp%d", n
));
614 g_ptr_array_add (p
, g_strdup_printf ("evp%d", n
));
616 g_ptr_array_add (p
, NULL
);
618 nodes
= (gchar
**) g_ptr_array_free (p
, FALSE
);
623 /* Only allows certain objects, and aborts on unknowns */
624 static GDBusInterfaceInfo
**
625 subtree_introspect (GDBusConnection
*connection
,
627 const gchar
*object_path
,
631 const GDBusInterfaceInfo
*interfaces
[2] = {
632 NULL
/* filled in below */, NULL
635 /* VPs implement the Foo interface, EVPs implement the Bar interface. The root
636 * does not implement any interfaces
642 else if (g_str_has_prefix (node
, "vp"))
644 interfaces
[0] = &foo_interface_info
;
646 else if (g_str_has_prefix (node
, "evp"))
648 interfaces
[0] = &bar_interface_info
;
652 g_assert_not_reached ();
655 return g_memdup (interfaces
, 2 * sizeof (void *));
658 static const GDBusInterfaceVTable
*
659 subtree_dispatch (GDBusConnection
*connection
,
661 const gchar
*object_path
,
662 const gchar
*interface_name
,
664 gpointer
*out_user_data
,
667 if (g_strcmp0 (interface_name
, "org.example.Foo") == 0)
673 static const GDBusSubtreeVTable subtree_vtable
=
680 /* -------------------- */
683 dynamic_subtree_enumerate (GDBusConnection
*connection
,
685 const gchar
*object_path
,
688 GPtrArray
*data
= user_data
;
689 gchar
**nodes
= g_new (gchar
*, data
->len
+ 1);
692 for (n
= 0; n
< data
->len
; n
++)
694 nodes
[n
] = g_strdup (g_ptr_array_index (data
, n
));
696 nodes
[data
->len
] = NULL
;
701 /* Allow all objects to be introspected */
702 static GDBusInterfaceInfo
**
703 dynamic_subtree_introspect (GDBusConnection
*connection
,
705 const gchar
*object_path
,
709 const GDBusInterfaceInfo
*interfaces
[2] = { &dyna_interface_info
, NULL
};
711 return g_memdup (interfaces
, 2 * sizeof (void *));
714 static const GDBusInterfaceVTable
*
715 dynamic_subtree_dispatch (GDBusConnection
*connection
,
717 const gchar
*object_path
,
718 const gchar
*interface_name
,
720 gpointer
*out_user_data
,
723 *out_user_data
= user_data
;
724 return &dyna_interface_vtable
;
727 static const GDBusSubtreeVTable dynamic_subtree_vtable
=
729 dynamic_subtree_enumerate
,
730 dynamic_subtree_introspect
,
731 dynamic_subtree_dispatch
734 /* -------------------- */
737 test_dispatch_thread_func (gpointer user_data
)
739 const gchar
*object_path
= user_data
;
740 GDBusProxy
*foo_proxy
;
745 const gchar
*value_str
;
747 foo_proxy
= g_dbus_proxy_new_sync (c
,
748 G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS
|
749 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES
,
751 g_dbus_connection_get_unique_name (c
),
756 g_assert (foo_proxy
!= NULL
);
758 /* generic interfaces */
760 value
= g_dbus_proxy_call_sync (foo_proxy
,
761 "org.freedesktop.DBus.Peer.Ping",
763 G_DBUS_CALL_FLAGS_NONE
,
767 g_assert_no_error (error
);
768 g_assert (value
!= NULL
);
769 g_variant_unref (value
);
773 value
= g_dbus_proxy_call_sync (foo_proxy
,
775 g_variant_new ("(s)", "winwinwin"),
776 G_DBUS_CALL_FLAGS_NONE
,
780 g_assert_no_error (error
);
781 g_assert (value
!= NULL
);
782 g_assert (g_variant_is_of_type (value
, G_VARIANT_TYPE ("(s)")));
783 g_variant_get (value
, "(&s)", &value_str
);
784 g_assert_cmpstr (value_str
, ==, "You passed the string 'winwinwin'. Jolly good!");
785 g_variant_unref (value
);
788 value
= g_dbus_proxy_call_sync (foo_proxy
,
791 G_DBUS_CALL_FLAGS_NONE
,
795 g_assert_error (error
, G_IO_ERROR
, G_IO_ERROR_DBUS_ERROR
);
796 g_assert_cmpstr (error
->message
, ==, "GDBus.Error:org.example.SomeError: How do you like them apples, buddy!");
797 g_error_free (error
);
798 g_assert (value
== NULL
);
801 value
= g_dbus_proxy_call_sync (foo_proxy
,
803 g_variant_new ("(s)", "failfailfail"),
804 G_DBUS_CALL_FLAGS_NONE
,
808 g_assert_error (error
, G_DBUS_ERROR
, G_DBUS_ERROR_INVALID_ARGS
);
809 g_assert_cmpstr (error
->message
, ==, "GDBus.Error:org.freedesktop.DBus.Error.InvalidArgs: Type of message, '(s)', does not match expected type '()'");
810 g_error_free (error
);
811 g_assert (value
== NULL
);
814 value
= g_dbus_proxy_call_sync (foo_proxy
,
817 G_DBUS_CALL_FLAGS_NONE
,
821 g_assert_error (error
, G_DBUS_ERROR
, G_DBUS_ERROR_UNKNOWN_METHOD
);
822 g_assert_cmpstr (error
->message
, ==, "GDBus.Error:org.freedesktop.DBus.Error.UnknownMethod: No such method 'NonExistantMethod'");
823 g_error_free (error
);
824 g_assert (value
== NULL
);
827 value
= g_dbus_proxy_call_sync (foo_proxy
,
828 "org.example.FooXYZ.NonExistant",
830 G_DBUS_CALL_FLAGS_NONE
,
834 g_assert_error (error
, G_DBUS_ERROR
, G_DBUS_ERROR_UNKNOWN_METHOD
);
835 g_error_free (error
);
836 g_assert (value
== NULL
);
838 /* user properties */
840 value
= g_dbus_proxy_call_sync (foo_proxy
,
841 "org.freedesktop.DBus.Properties.Get",
842 g_variant_new ("(ss)",
845 G_DBUS_CALL_FLAGS_NONE
,
849 g_assert_no_error (error
);
850 g_assert (value
!= NULL
);
851 g_assert (g_variant_is_of_type (value
, G_VARIANT_TYPE ("(v)")));
852 g_variant_get (value
, "(v)", &inner
);
853 g_assert (g_variant_is_of_type (inner
, G_VARIANT_TYPE_STRING
));
854 g_assert_cmpstr (g_variant_get_string (inner
, NULL
), ==, "Property 'PropertyUno' Is What It Is!");
855 g_variant_unref (value
);
856 g_variant_unref (inner
);
859 value
= g_dbus_proxy_call_sync (foo_proxy
,
860 "org.freedesktop.DBus.Properties.Get",
861 g_variant_new ("(ss)",
864 G_DBUS_CALL_FLAGS_NONE
,
868 g_assert (value
== NULL
);
869 g_assert_error (error
, G_DBUS_ERROR
, G_DBUS_ERROR_INVALID_ARGS
);
870 g_assert_cmpstr (error
->message
, ==, "GDBus.Error:org.freedesktop.DBus.Error.InvalidArgs: No such property 'ThisDoesntExist'");
871 g_error_free (error
);
874 value
= g_dbus_proxy_call_sync (foo_proxy
,
875 "org.freedesktop.DBus.Properties.Get",
876 g_variant_new ("(ss)",
879 G_DBUS_CALL_FLAGS_NONE
,
883 g_assert (value
== NULL
);
884 g_assert_error (error
, G_DBUS_ERROR
, G_DBUS_ERROR_INVALID_ARGS
);
885 g_assert_cmpstr (error
->message
, ==, "GDBus.Error:org.freedesktop.DBus.Error.InvalidArgs: Property 'NotReadable' is not readable");
886 g_error_free (error
);
889 value
= g_dbus_proxy_call_sync (foo_proxy
,
890 "org.freedesktop.DBus.Properties.Set",
891 g_variant_new ("(ssv)",
894 g_variant_new_string ("But Writable you are!")),
895 G_DBUS_CALL_FLAGS_NONE
,
899 g_assert (value
== NULL
);
900 g_assert_error (error
, G_DBUS_ERROR
, G_DBUS_ERROR_SPAWN_FILE_INVALID
);
901 g_assert_cmpstr (error
->message
, ==, "GDBus.Error:org.freedesktop.DBus.Error.Spawn.FileInvalid: Returning some error instead of writing the value 'NotReadable' to the property ''But Writable you are!''");
902 g_error_free (error
);
905 value
= g_dbus_proxy_call_sync (foo_proxy
,
906 "org.freedesktop.DBus.Properties.Set",
907 g_variant_new ("(ssv)",
910 g_variant_new_uint32 (42)),
911 G_DBUS_CALL_FLAGS_NONE
,
915 g_assert (value
== NULL
);
916 g_assert_error (error
, G_DBUS_ERROR
, G_DBUS_ERROR_INVALID_ARGS
);
917 g_assert_cmpstr (error
->message
, ==, "GDBus.Error:org.freedesktop.DBus.Error.InvalidArgs: Property 'NotWritable' is not writable");
918 g_error_free (error
);
921 value
= g_dbus_proxy_call_sync (foo_proxy
,
922 "org.freedesktop.DBus.Properties.GetAll",
923 g_variant_new ("(s)",
925 G_DBUS_CALL_FLAGS_NONE
,
929 g_assert_no_error (error
);
930 g_assert (value
!= NULL
);
931 g_assert (g_variant_is_of_type (value
, G_VARIANT_TYPE ("(a{sv})")));
932 s
= g_variant_print (value
, TRUE
);
933 g_assert_cmpstr (s
, ==, "({'PropertyUno': <\"Property 'PropertyUno' Is What It Is!\">, 'NotWritable': <\"Property 'NotWritable' Is What It Is!\">},)");
935 g_variant_unref (value
);
937 g_object_unref (foo_proxy
);
939 g_main_loop_quit (loop
);
944 test_dispatch (const gchar
*object_path
)
948 /* run this in a thread to avoid deadlocks */
949 thread
= g_thread_new ("test_dispatch",
950 test_dispatch_thread_func
,
951 (gpointer
) object_path
);
952 g_main_loop_run (loop
);
953 g_thread_join (thread
);
957 test_object_registration (void)
960 ObjectRegistrationData data
;
961 GPtrArray
*dyna_data
;
963 guint boss_foo_reg_id
;
964 guint boss_bar_reg_id
;
965 guint worker1_foo_reg_id
;
966 guint worker1p1_foo_reg_id
;
967 guint worker2_bar_reg_id
;
968 guint intern1_foo_reg_id
;
969 guint intern2_bar_reg_id
;
970 guint intern2_foo_reg_id
;
971 guint intern3_bar_reg_id
;
972 guint registration_id
;
973 guint subtree_registration_id
;
974 guint non_subtree_object_path_foo_reg_id
;
975 guint non_subtree_object_path_bar_reg_id
;
976 guint dyna_subtree_registration_id
;
977 guint num_successful_registrations
;
979 data
.num_unregistered_calls
= 0;
980 data
.num_unregistered_subtree_calls
= 0;
981 data
.num_subtree_nodes
= 0;
983 num_successful_registrations
= 0;
986 c
= g_bus_get_sync (G_BUS_TYPE_SESSION
, NULL
, &error
);
987 g_assert_no_error (error
);
988 g_assert (c
!= NULL
);
990 registration_id
= g_dbus_connection_register_object (c
,
992 (GDBusInterfaceInfo
*) &foo_interface_info
,
995 on_object_unregistered
,
997 g_assert_no_error (error
);
998 g_assert (registration_id
> 0);
999 boss_foo_reg_id
= registration_id
;
1000 num_successful_registrations
++;
1002 registration_id
= g_dbus_connection_register_object (c
,
1004 (GDBusInterfaceInfo
*) &bar_interface_info
,
1007 on_object_unregistered
,
1009 g_assert_no_error (error
);
1010 g_assert (registration_id
> 0);
1011 boss_bar_reg_id
= registration_id
;
1012 num_successful_registrations
++;
1014 registration_id
= g_dbus_connection_register_object (c
,
1015 "/foo/boss/worker1",
1016 (GDBusInterfaceInfo
*) &foo_interface_info
,
1019 on_object_unregistered
,
1021 g_assert_no_error (error
);
1022 g_assert (registration_id
> 0);
1023 worker1_foo_reg_id
= registration_id
;
1024 num_successful_registrations
++;
1026 registration_id
= g_dbus_connection_register_object (c
,
1027 "/foo/boss/worker1p1",
1028 (GDBusInterfaceInfo
*) &foo_interface_info
,
1031 on_object_unregistered
,
1033 g_assert_no_error (error
);
1034 g_assert (registration_id
> 0);
1035 worker1p1_foo_reg_id
= registration_id
;
1036 num_successful_registrations
++;
1038 registration_id
= g_dbus_connection_register_object (c
,
1039 "/foo/boss/worker2",
1040 (GDBusInterfaceInfo
*) &bar_interface_info
,
1043 on_object_unregistered
,
1045 g_assert_no_error (error
);
1046 g_assert (registration_id
> 0);
1047 worker2_bar_reg_id
= registration_id
;
1048 num_successful_registrations
++;
1050 registration_id
= g_dbus_connection_register_object (c
,
1051 "/foo/boss/interns/intern1",
1052 (GDBusInterfaceInfo
*) &foo_interface_info
,
1055 on_object_unregistered
,
1057 g_assert_no_error (error
);
1058 g_assert (registration_id
> 0);
1059 intern1_foo_reg_id
= registration_id
;
1060 num_successful_registrations
++;
1062 /* ... and try again at another path */
1063 registration_id
= g_dbus_connection_register_object (c
,
1064 "/foo/boss/interns/intern2",
1065 (GDBusInterfaceInfo
*) &bar_interface_info
,
1068 on_object_unregistered
,
1070 g_assert_no_error (error
);
1071 g_assert (registration_id
> 0);
1072 intern2_bar_reg_id
= registration_id
;
1073 num_successful_registrations
++;
1075 /* register at the same path/interface - this should fail */
1076 registration_id
= g_dbus_connection_register_object (c
,
1077 "/foo/boss/interns/intern2",
1078 (GDBusInterfaceInfo
*) &bar_interface_info
,
1081 on_object_unregistered
,
1083 g_assert_error (error
, G_IO_ERROR
, G_IO_ERROR_EXISTS
);
1084 g_assert (!g_dbus_error_is_remote_error (error
));
1085 g_error_free (error
);
1087 g_assert (registration_id
== 0);
1089 /* register at different interface - shouldn't fail */
1090 registration_id
= g_dbus_connection_register_object (c
,
1091 "/foo/boss/interns/intern2",
1092 (GDBusInterfaceInfo
*) &foo_interface_info
,
1095 on_object_unregistered
,
1097 g_assert_no_error (error
);
1098 g_assert (registration_id
> 0);
1099 intern2_foo_reg_id
= registration_id
;
1100 num_successful_registrations
++;
1102 /* unregister it via the id */
1103 g_assert (g_dbus_connection_unregister_object (c
, registration_id
));
1104 g_main_context_iteration (NULL
, FALSE
);
1105 g_assert_cmpint (data
.num_unregistered_calls
, ==, 1);
1106 intern2_foo_reg_id
= 0;
1108 /* register it back */
1109 registration_id
= g_dbus_connection_register_object (c
,
1110 "/foo/boss/interns/intern2",
1111 (GDBusInterfaceInfo
*) &foo_interface_info
,
1114 on_object_unregistered
,
1116 g_assert_no_error (error
);
1117 g_assert (registration_id
> 0);
1118 intern2_foo_reg_id
= registration_id
;
1119 num_successful_registrations
++;
1121 registration_id
= g_dbus_connection_register_object (c
,
1122 "/foo/boss/interns/intern3",
1123 (GDBusInterfaceInfo
*) &bar_interface_info
,
1126 on_object_unregistered
,
1128 g_assert_no_error (error
);
1129 g_assert (registration_id
> 0);
1130 intern3_bar_reg_id
= registration_id
;
1131 num_successful_registrations
++;
1133 /* now register a whole subtree at /foo/boss/executives */
1134 subtree_registration_id
= g_dbus_connection_register_subtree (c
,
1135 "/foo/boss/executives",
1137 G_DBUS_SUBTREE_FLAGS_NONE
,
1139 on_subtree_unregistered
,
1141 g_assert_no_error (error
);
1142 g_assert (subtree_registration_id
> 0);
1143 /* try registering it again.. this should fail */
1144 registration_id
= g_dbus_connection_register_subtree (c
,
1145 "/foo/boss/executives",
1147 G_DBUS_SUBTREE_FLAGS_NONE
,
1149 on_subtree_unregistered
,
1151 g_assert_error (error
, G_IO_ERROR
, G_IO_ERROR_EXISTS
);
1152 g_assert (!g_dbus_error_is_remote_error (error
));
1153 g_error_free (error
);
1155 g_assert (registration_id
== 0);
1157 /* unregister it, then register it again */
1158 g_assert_cmpint (data
.num_unregistered_subtree_calls
, ==, 0);
1159 g_assert (g_dbus_connection_unregister_subtree (c
, subtree_registration_id
));
1160 g_main_context_iteration (NULL
, FALSE
);
1161 g_assert_cmpint (data
.num_unregistered_subtree_calls
, ==, 1);
1162 subtree_registration_id
= g_dbus_connection_register_subtree (c
,
1163 "/foo/boss/executives",
1165 G_DBUS_SUBTREE_FLAGS_NONE
,
1167 on_subtree_unregistered
,
1169 g_assert_no_error (error
);
1170 g_assert (subtree_registration_id
> 0);
1172 /* try to register something under /foo/boss/executives - this should work
1173 * because registered subtrees and registered objects can coexist.
1175 * Make the exported object implement *two* interfaces so we can check
1176 * that the right introspection handler is invoked.
1178 registration_id
= g_dbus_connection_register_object (c
,
1179 "/foo/boss/executives/non_subtree_object",
1180 (GDBusInterfaceInfo
*) &bar_interface_info
,
1183 on_object_unregistered
,
1185 g_assert_no_error (error
);
1186 g_assert (registration_id
> 0);
1187 non_subtree_object_path_bar_reg_id
= registration_id
;
1188 num_successful_registrations
++;
1189 registration_id
= g_dbus_connection_register_object (c
,
1190 "/foo/boss/executives/non_subtree_object",
1191 (GDBusInterfaceInfo
*) &foo_interface_info
,
1194 on_object_unregistered
,
1196 g_assert_no_error (error
);
1197 g_assert (registration_id
> 0);
1198 non_subtree_object_path_foo_reg_id
= registration_id
;
1199 num_successful_registrations
++;
1201 /* now register a dynamic subtree, spawning objects as they are called */
1202 dyna_data
= g_ptr_array_new_with_free_func (g_free
);
1203 dyna_subtree_registration_id
= g_dbus_connection_register_subtree (c
,
1205 &dynamic_subtree_vtable
,
1206 G_DBUS_SUBTREE_FLAGS_DISPATCH_TO_UNENUMERATED_NODES
,
1208 (GDestroyNotify
)g_ptr_array_unref
,
1210 g_assert_no_error (error
);
1211 g_assert (dyna_subtree_registration_id
> 0);
1213 /* First assert that we have no nodes in the dynamic subtree */
1214 nodes
= get_nodes_at (c
, "/foo/dyna");
1215 g_assert (nodes
!= NULL
);
1216 g_assert_cmpint (g_strv_length (nodes
), ==, 0);
1218 g_assert_cmpint (count_interfaces (c
, "/foo/dyna"), ==, 4);
1220 /* Install three nodes in the dynamic subtree via the dyna_data backdoor and
1221 * assert that they show up correctly in the introspection data */
1222 g_ptr_array_add (dyna_data
, g_strdup ("lol"));
1223 g_ptr_array_add (dyna_data
, g_strdup ("cat"));
1224 g_ptr_array_add (dyna_data
, g_strdup ("cheezburger"));
1225 nodes
= get_nodes_at (c
, "/foo/dyna");
1226 g_assert (nodes
!= NULL
);
1227 g_assert_cmpint (g_strv_length (nodes
), ==, 3);
1228 g_assert_cmpstr (nodes
[0], ==, "lol");
1229 g_assert_cmpstr (nodes
[1], ==, "cat");
1230 g_assert_cmpstr (nodes
[2], ==, "cheezburger");
1232 g_assert_cmpint (count_interfaces (c
, "/foo/dyna/lol"), ==, 4);
1233 g_assert_cmpint (count_interfaces (c
, "/foo/dyna/cat"), ==, 4);
1234 g_assert_cmpint (count_interfaces (c
, "/foo/dyna/cheezburger"), ==, 4);
1236 /* Call a non-existing object path and assert that it has been created */
1237 dyna_create (c
, "dynamicallycreated");
1238 nodes
= get_nodes_at (c
, "/foo/dyna");
1239 g_assert (nodes
!= NULL
);
1240 g_assert_cmpint (g_strv_length (nodes
), ==, 4);
1241 g_assert_cmpstr (nodes
[0], ==, "lol");
1242 g_assert_cmpstr (nodes
[1], ==, "cat");
1243 g_assert_cmpstr (nodes
[2], ==, "cheezburger");
1244 g_assert_cmpstr (nodes
[3], ==, "dynamicallycreated");
1246 g_assert_cmpint (count_interfaces (c
, "/foo/dyna/dynamicallycreated"), ==, 4);
1248 /* now check that the object hierarachy is properly generated... yes, it's a bit
1249 * perverse that we round-trip to the bus to introspect ourselves ;-)
1251 nodes
= get_nodes_at (c
, "/");
1252 g_assert (nodes
!= NULL
);
1253 g_assert_cmpint (g_strv_length (nodes
), ==, 1);
1254 g_assert_cmpstr (nodes
[0], ==, "foo");
1256 g_assert_cmpint (count_interfaces (c
, "/"), ==, 0);
1258 nodes
= get_nodes_at (c
, "/foo");
1259 g_assert (nodes
!= NULL
);
1260 g_assert_cmpint (g_strv_length (nodes
), ==, 2);
1261 g_assert_cmpstr (nodes
[0], ==, "boss");
1262 g_assert_cmpstr (nodes
[1], ==, "dyna");
1264 g_assert_cmpint (count_interfaces (c
, "/foo"), ==, 0);
1266 nodes
= get_nodes_at (c
, "/foo/boss");
1267 g_assert (nodes
!= NULL
);
1268 g_assert_cmpint (g_strv_length (nodes
), ==, 5);
1269 g_assert (_g_strv_has_string ((const gchar
* const *) nodes
, "worker1"));
1270 g_assert (_g_strv_has_string ((const gchar
* const *) nodes
, "worker1p1"));
1271 g_assert (_g_strv_has_string ((const gchar
* const *) nodes
, "worker2"));
1272 g_assert (_g_strv_has_string ((const gchar
* const *) nodes
, "interns"));
1273 g_assert (_g_strv_has_string ((const gchar
* const *) nodes
, "executives"));
1275 /* any registered object always implement org.freedesktop.DBus.[Peer,Introspectable,Properties] */
1276 g_assert_cmpint (count_interfaces (c
, "/foo/boss"), ==, 5);
1277 g_assert (has_interface (c
, "/foo/boss", foo_interface_info
.name
));
1278 g_assert (has_interface (c
, "/foo/boss", bar_interface_info
.name
));
1280 /* check subtree nodes - we should have only non_subtree_object in /foo/boss/executives
1281 * because data.num_subtree_nodes is 0
1283 nodes
= get_nodes_at (c
, "/foo/boss/executives");
1284 g_assert (nodes
!= NULL
);
1285 g_assert (_g_strv_has_string ((const gchar
* const *) nodes
, "non_subtree_object"));
1286 g_assert_cmpint (g_strv_length (nodes
), ==, 1);
1288 g_assert_cmpint (count_interfaces (c
, "/foo/boss/executives"), ==, 0);
1290 /* now change data.num_subtree_nodes and check */
1291 data
.num_subtree_nodes
= 2;
1292 nodes
= get_nodes_at (c
, "/foo/boss/executives");
1293 g_assert (nodes
!= NULL
);
1294 g_assert_cmpint (g_strv_length (nodes
), ==, 5);
1295 g_assert (_g_strv_has_string ((const gchar
* const *) nodes
, "non_subtree_object"));
1296 g_assert (_g_strv_has_string ((const gchar
* const *) nodes
, "vp0"));
1297 g_assert (_g_strv_has_string ((const gchar
* const *) nodes
, "vp1"));
1298 g_assert (_g_strv_has_string ((const gchar
* const *) nodes
, "evp0"));
1299 g_assert (_g_strv_has_string ((const gchar
* const *) nodes
, "evp1"));
1300 /* check that /foo/boss/executives/non_subtree_object is not handled by the
1301 * subtree handlers - we can do this because objects from subtree handlers
1302 * has exactly one interface and non_subtree_object has two
1304 g_assert_cmpint (count_interfaces (c
, "/foo/boss/executives/non_subtree_object"), ==, 5);
1305 g_assert (has_interface (c
, "/foo/boss/executives/non_subtree_object", foo_interface_info
.name
));
1306 g_assert (has_interface (c
, "/foo/boss/executives/non_subtree_object", bar_interface_info
.name
));
1307 /* check that the vp and evp objects are handled by the subtree handlers */
1308 g_assert_cmpint (count_interfaces (c
, "/foo/boss/executives/vp0"), ==, 4);
1309 g_assert_cmpint (count_interfaces (c
, "/foo/boss/executives/vp1"), ==, 4);
1310 g_assert_cmpint (count_interfaces (c
, "/foo/boss/executives/evp0"), ==, 4);
1311 g_assert_cmpint (count_interfaces (c
, "/foo/boss/executives/evp1"), ==, 4);
1312 g_assert (has_interface (c
, "/foo/boss/executives/vp0", foo_interface_info
.name
));
1313 g_assert (has_interface (c
, "/foo/boss/executives/vp1", foo_interface_info
.name
));
1314 g_assert (has_interface (c
, "/foo/boss/executives/evp0", bar_interface_info
.name
));
1315 g_assert (has_interface (c
, "/foo/boss/executives/evp1", bar_interface_info
.name
));
1317 data
.num_subtree_nodes
= 3;
1318 nodes
= get_nodes_at (c
, "/foo/boss/executives");
1319 g_assert (nodes
!= NULL
);
1320 g_assert_cmpint (g_strv_length (nodes
), ==, 7);
1321 g_assert (_g_strv_has_string ((const gchar
* const *) nodes
, "non_subtree_object"));
1322 g_assert (_g_strv_has_string ((const gchar
* const *) nodes
, "vp0"));
1323 g_assert (_g_strv_has_string ((const gchar
* const *) nodes
, "vp1"));
1324 g_assert (_g_strv_has_string ((const gchar
* const *) nodes
, "vp2"));
1325 g_assert (_g_strv_has_string ((const gchar
* const *) nodes
, "evp0"));
1326 g_assert (_g_strv_has_string ((const gchar
* const *) nodes
, "evp1"));
1327 g_assert (_g_strv_has_string ((const gchar
* const *) nodes
, "evp2"));
1330 /* This is to check that a bug (rather, class of bugs) in gdbusconnection.c's
1332 * g_dbus_connection_list_registered_unlocked()
1334 * where /foo/boss/worker1 reported a child '1', is now fixed.
1336 nodes
= get_nodes_at (c
, "/foo/boss/worker1");
1337 g_assert (nodes
!= NULL
);
1338 g_assert_cmpint (g_strv_length (nodes
), ==, 0);
1341 /* check that calls are properly dispatched to the functions in foo_vtable for objects
1342 * implementing the org.example.Foo interface
1344 * We do this for both a regular registered object (/foo/boss) and also for an object
1345 * registered through the subtree mechanism.
1347 test_dispatch ("/foo/boss");
1348 test_dispatch ("/foo/boss/executives/vp0");
1350 /* To prevent from exiting and attaching a D-Bus tool like D-Feet; uncomment: */
1352 g_debug ("Point D-feet or other tool at: %s", g_test_dbus_get_temporary_address());
1353 g_main_loop_run (loop
);
1356 /* check that unregistering the subtree handler works */
1357 g_assert_cmpint (data
.num_unregistered_subtree_calls
, ==, 1);
1358 g_assert (g_dbus_connection_unregister_subtree (c
, subtree_registration_id
));
1359 g_main_context_iteration (NULL
, FALSE
);
1360 g_assert_cmpint (data
.num_unregistered_subtree_calls
, ==, 2);
1361 nodes
= get_nodes_at (c
, "/foo/boss/executives");
1362 g_assert (nodes
!= NULL
);
1363 g_assert_cmpint (g_strv_length (nodes
), ==, 1);
1364 g_assert (_g_strv_has_string ((const gchar
* const *) nodes
, "non_subtree_object"));
1367 g_assert (g_dbus_connection_unregister_object (c
, boss_foo_reg_id
));
1368 g_assert (g_dbus_connection_unregister_object (c
, boss_bar_reg_id
));
1369 g_assert (g_dbus_connection_unregister_object (c
, worker1_foo_reg_id
));
1370 g_assert (g_dbus_connection_unregister_object (c
, worker1p1_foo_reg_id
));
1371 g_assert (g_dbus_connection_unregister_object (c
, worker2_bar_reg_id
));
1372 g_assert (g_dbus_connection_unregister_object (c
, intern1_foo_reg_id
));
1373 g_assert (g_dbus_connection_unregister_object (c
, intern2_bar_reg_id
));
1374 g_assert (g_dbus_connection_unregister_object (c
, intern2_foo_reg_id
));
1375 g_assert (g_dbus_connection_unregister_object (c
, intern3_bar_reg_id
));
1376 g_assert (g_dbus_connection_unregister_object (c
, non_subtree_object_path_bar_reg_id
));
1377 g_assert (g_dbus_connection_unregister_object (c
, non_subtree_object_path_foo_reg_id
));
1379 g_main_context_iteration (NULL
, FALSE
);
1380 g_assert_cmpint (data
.num_unregistered_calls
, ==, num_successful_registrations
);
1382 /* check that we no longer export any objects - TODO: it looks like there's a bug in
1383 * libdbus-1 here: libdbus still reports the '/foo' object; so disable the test for now
1386 nodes
= get_nodes_at (c
, "/");
1387 g_assert (nodes
!= NULL
);
1388 g_assert_cmpint (g_strv_length (nodes
), ==, 0);
1395 static const GDBusInterfaceInfo test_interface_info1
=
1399 (GDBusMethodInfo
**) NULL
,
1400 (GDBusSignalInfo
**) NULL
,
1401 (GDBusPropertyInfo
**) NULL
,
1405 static const GDBusInterfaceInfo test_interface_info2
=
1408 "org.freedesktop.DBus.Properties",
1409 (GDBusMethodInfo
**) NULL
,
1410 (GDBusSignalInfo
**) NULL
,
1411 (GDBusPropertyInfo
**) NULL
,
1416 check_interfaces (GDBusConnection
*c
,
1417 const gchar
*object_path
,
1418 const gchar
**interfaces
)
1423 GDBusNodeInfo
*node_info
;
1427 proxy
= g_dbus_proxy_new_sync (c
,
1428 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES
|
1429 G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS
,
1431 g_dbus_connection_get_unique_name (c
),
1433 "org.freedesktop.DBus.Introspectable",
1436 g_assert_no_error (error
);
1437 g_assert (proxy
!= NULL
);
1439 /* do this async to avoid libdbus-1 deadlocks */
1441 g_dbus_proxy_call (proxy
,
1444 G_DBUS_CALL_FLAGS_NONE
,
1447 (GAsyncReadyCallback
) introspect_callback
,
1449 g_main_loop_run (loop
);
1450 g_assert (xml_data
!= NULL
);
1452 node_info
= g_dbus_node_info_new_for_xml (xml_data
, &error
);
1453 g_assert_no_error (error
);
1454 g_assert (node_info
!= NULL
);
1456 g_assert (node_info
->interfaces
!= NULL
);
1457 for (i
= 0; node_info
->interfaces
[i
]; i
++) ;
1459 if (g_strv_length ((gchar
**)interfaces
) != i
- 1)
1461 g_print ("expected ");
1462 for (i
= 0; interfaces
[i
]; i
++)
1463 g_print ("%s ", interfaces
[i
]);
1465 for (i
= 0; node_info
->interfaces
[i
]; i
++)
1466 g_print ("%s ", node_info
->interfaces
[i
]->name
);
1470 g_assert_cmpint (g_strv_length ((gchar
**)interfaces
), ==, i
- 1);
1472 for (i
= 0; interfaces
[i
]; i
++)
1474 for (j
= 0; node_info
->interfaces
[j
]; j
++)
1476 if (strcmp (interfaces
[i
], node_info
->interfaces
[j
]->name
) == 0)
1480 g_assert_not_reached ();
1485 g_object_unref (proxy
);
1487 g_dbus_node_info_unref (node_info
);
1491 test_registered_interfaces (void)
1495 const gchar
*interfaces
[] = {
1497 "org.freedesktop.DBus.Properties",
1498 "org.freedesktop.DBus.Introspectable",
1503 c
= g_bus_get_sync (G_BUS_TYPE_SESSION
, NULL
, &error
);
1504 g_assert_no_error (error
);
1505 g_assert (c
!= NULL
);
1507 id1
= g_dbus_connection_register_object (c
,
1509 (GDBusInterfaceInfo
*) &test_interface_info1
,
1514 g_assert_no_error (error
);
1516 id2
= g_dbus_connection_register_object (c
,
1518 (GDBusInterfaceInfo
*) &test_interface_info2
,
1523 g_assert_no_error (error
);
1526 check_interfaces (c
, "/test", interfaces
);
1528 g_assert (g_dbus_connection_unregister_object (c
, id1
));
1529 g_assert (g_dbus_connection_unregister_object (c
, id2
));
1534 /* ---------------------------------------------------------------------------------------------------- */
1537 test_async_method_call (GDBusConnection
*connection
,
1538 const gchar
*sender
,
1539 const gchar
*object_path
,
1540 const gchar
*interface_name
,
1541 const gchar
*method_name
,
1542 GVariant
*parameters
,
1543 GDBusMethodInvocation
*invocation
,
1546 const GDBusPropertyInfo
*property
;
1548 /* Strictly speaking, this function should also expect to receive
1549 * method calls not on the org.freedesktop.DBus.Properties interface,
1550 * but we don't do any during this testcase, so assert that.
1552 g_assert_cmpstr (interface_name
, ==, "org.freedesktop.DBus.Properties");
1553 g_assert (g_dbus_method_invocation_get_method_info (invocation
) == NULL
);
1555 property
= g_dbus_method_invocation_get_property_info (invocation
);
1557 /* We should never be seeing any property calls on the com.example.Bar
1558 * interface because it doesn't export any properties.
1560 * In each case below make sure the interface is org.example.Foo.
1563 /* Do a whole lot of asserts to make sure that invalid calls are still
1564 * getting properly rejected by GDBusConnection and that our
1565 * environment is as we expect it to be.
1567 if (g_str_equal (method_name
, "Get"))
1569 const gchar
*iface_name
, *prop_name
;
1571 g_variant_get (parameters
, "(&s&s)", &iface_name
, &prop_name
);
1572 g_assert_cmpstr (iface_name
, ==, "org.example.Foo");
1573 g_assert (property
!= NULL
);
1574 g_assert_cmpstr (prop_name
, ==, property
->name
);
1575 g_assert (property
->flags
& G_DBUS_PROPERTY_INFO_FLAGS_READABLE
);
1576 g_dbus_method_invocation_return_value (invocation
, g_variant_new ("(v)", g_variant_new_string (prop_name
)));
1579 else if (g_str_equal (method_name
, "Set"))
1581 const gchar
*iface_name
, *prop_name
;
1584 g_variant_get (parameters
, "(&s&sv)", &iface_name
, &prop_name
, &value
);
1585 g_assert_cmpstr (iface_name
, ==, "org.example.Foo");
1586 g_assert (property
!= NULL
);
1587 g_assert_cmpstr (prop_name
, ==, property
->name
);
1588 g_assert (property
->flags
& G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE
);
1589 g_assert (g_variant_is_of_type (value
, G_VARIANT_TYPE (property
->signature
)));
1590 g_dbus_method_invocation_return_value (invocation
, g_variant_new ("()"));
1591 g_variant_unref (value
);
1594 else if (g_str_equal (method_name
, "GetAll"))
1596 const gchar
*iface_name
;
1598 g_variant_get (parameters
, "(&s)", &iface_name
);
1599 g_assert_cmpstr (iface_name
, ==, "org.example.Foo");
1600 g_assert (property
== NULL
);
1601 g_dbus_method_invocation_return_value (invocation
,
1602 g_variant_new_parsed ("({ 'PropertyUno': < 'uno' >,"
1603 " 'NotWritable': < 'notwrite' > },)"));
1607 g_assert_not_reached ();
1610 static gint outstanding_cases
;
1613 ensure_result_cb (GObject
*source
,
1614 GAsyncResult
*result
,
1617 GDBusConnection
*connection
= G_DBUS_CONNECTION (source
);
1620 reply
= g_dbus_connection_call_finish (connection
, result
, NULL
);
1622 if (user_data
== NULL
)
1624 /* Expected an error */
1625 g_assert (reply
== NULL
);
1629 /* Expected a reply of a particular format. */
1632 g_assert (reply
!= NULL
);
1633 str
= g_variant_print (reply
, TRUE
);
1634 g_assert_cmpstr (str
, ==, (const gchar
*) user_data
);
1637 g_variant_unref (reply
);
1640 g_assert_cmpint (outstanding_cases
, >, 0);
1641 outstanding_cases
--;
1645 test_async_case (GDBusConnection
*connection
,
1646 const gchar
*expected_reply
,
1647 const gchar
*method
,
1648 const gchar
*format_string
,
1653 va_start (ap
, format_string
);
1655 g_dbus_connection_call (connection
, g_dbus_connection_get_unique_name (connection
), "/foo",
1656 "org.freedesktop.DBus.Properties", method
, g_variant_new_va (format_string
, NULL
, &ap
),
1657 NULL
, G_DBUS_CALL_FLAGS_NONE
, -1, NULL
, ensure_result_cb
, (gpointer
) expected_reply
);
1661 outstanding_cases
++;
1665 test_async_properties (void)
1667 GError
*error
= NULL
;
1668 guint registration_id
, registration_id2
;
1669 static const GDBusInterfaceVTable vtable
= {
1670 test_async_method_call
, NULL
, NULL
1673 c
= g_bus_get_sync (G_BUS_TYPE_SESSION
, NULL
, &error
);
1674 g_assert_no_error (error
);
1675 g_assert (c
!= NULL
);
1677 registration_id
= g_dbus_connection_register_object (c
,
1679 (GDBusInterfaceInfo
*) &foo_interface_info
,
1680 &vtable
, NULL
, NULL
, &error
);
1681 g_assert_no_error (error
);
1682 g_assert (registration_id
);
1683 registration_id2
= g_dbus_connection_register_object (c
,
1685 (GDBusInterfaceInfo
*) &foo2_interface_info
,
1686 &vtable
, NULL
, NULL
, &error
);
1687 g_assert_no_error (error
);
1688 g_assert (registration_id
);
1690 test_async_case (c
, NULL
, "random", "()");
1692 /* Test a variety of error cases */
1693 test_async_case (c
, NULL
, "Get", "(si)", "wrong signature", 5);
1694 test_async_case (c
, NULL
, "Get", "(ss)", "org.example.WrongInterface", "zzz");
1695 test_async_case (c
, NULL
, "Get", "(ss)", "org.example.Foo", "NoSuchProperty");
1696 test_async_case (c
, NULL
, "Get", "(ss)", "org.example.Foo", "NotReadable");
1698 test_async_case (c
, NULL
, "Set", "(si)", "wrong signature", 5);
1699 test_async_case (c
, NULL
, "Set", "(ssv)", "org.example.WrongInterface", "zzz", g_variant_new_string (""));
1700 test_async_case (c
, NULL
, "Set", "(ssv)", "org.example.Foo", "NoSuchProperty", g_variant_new_string (""));
1701 test_async_case (c
, NULL
, "Set", "(ssv)", "org.example.Foo", "NotWritable", g_variant_new_string (""));
1702 test_async_case (c
, NULL
, "Set", "(ssv)", "org.example.Foo", "PropertyUno", g_variant_new_object_path ("/wrong"));
1704 test_async_case (c
, NULL
, "GetAll", "(si)", "wrong signature", 5);
1705 test_async_case (c
, NULL
, "GetAll", "(s)", "org.example.WrongInterface");
1707 /* Make sure that we get no unexpected async property calls for com.example.Foo2 */
1708 test_async_case (c
, NULL
, "Get", "(ss)", "org.example.Foo2", "zzz");
1709 test_async_case (c
, NULL
, "Set", "(ssv)", "org.example.Foo2", "zzz", g_variant_new_string (""));
1710 test_async_case (c
, "(@a{sv} {},)", "GetAll", "(s)", "org.example.Foo2");
1712 /* Now do the proper things */
1713 test_async_case (c
, "(<'PropertyUno'>,)", "Get", "(ss)", "org.example.Foo", "PropertyUno");
1714 test_async_case (c
, "(<'NotWritable'>,)", "Get", "(ss)", "org.example.Foo", "NotWritable");
1715 test_async_case (c
, "()", "Set", "(ssv)", "org.example.Foo", "PropertyUno", g_variant_new_string (""));
1716 test_async_case (c
, "()", "Set", "(ssv)", "org.example.Foo", "NotReadable", g_variant_new_string (""));
1717 test_async_case (c
, "({'PropertyUno': <'uno'>, 'NotWritable': <'notwrite'>},)", "GetAll", "(s)", "org.example.Foo");
1719 while (outstanding_cases
)
1720 g_main_context_iteration (NULL
, TRUE
);
1722 g_dbus_connection_unregister_object (c
, registration_id
);
1723 g_dbus_connection_unregister_object (c
, registration_id2
);
1727 /* ---------------------------------------------------------------------------------------------------- */
1735 g_test_init (&argc
, &argv
, NULL
);
1737 /* all the tests rely on a shared main loop */
1738 loop
= g_main_loop_new (NULL
, FALSE
);
1740 g_test_add_func ("/gdbus/object-registration", test_object_registration
);
1741 g_test_add_func ("/gdbus/registered-interfaces", test_registered_interfaces
);
1742 g_test_add_func ("/gdbus/async-properties", test_async_properties
);
1744 /* TODO: check that we spit out correct introspection data */
1745 /* TODO: check that registering a whole subtree works */
1747 ret
= session_bus_run ();
1749 g_main_loop_unref (loop
);