1 /* GLib testing framework examples and tests
3 * Copyright (C) 2008-2011 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>
26 #include "gdbus-tests.h"
28 #include "gdbus-test-codegen-generated.h"
30 /* ---------------------------------------------------------------------------------------------------- */
33 count_annotations (GDBusAnnotationInfo
**annotations
)
37 while (annotations
!= NULL
&& annotations
[ret
] != NULL
)
44 * - non-internal annotations are written out correctly; and
45 * - injection via --annotation --key --value works
48 test_annotations (void)
50 GDBusInterfaceInfo
*iface
;
51 GDBusMethodInfo
*method
;
52 GDBusSignalInfo
*signal
;
53 GDBusPropertyInfo
*property
;
55 iface
= foo_igen_bar_interface_info ();
56 g_assert (iface
!= NULL
);
58 /* see Makefile.am for where these annotations are injected */
59 g_assert_cmpint (count_annotations (iface
->annotations
), ==, 1);
60 g_assert_cmpstr (g_dbus_annotation_info_lookup (iface
->annotations
, "Key1"), ==, "Value1");
62 method
= g_dbus_interface_info_lookup_method (iface
, "HelloWorld");
63 g_assert (method
!= NULL
);
64 g_assert_cmpint (count_annotations (method
->annotations
), ==, 2);
65 g_assert_cmpstr (g_dbus_annotation_info_lookup (method
->annotations
, "ExistingAnnotation"), ==, "blah");
66 g_assert_cmpstr (g_dbus_annotation_info_lookup (method
->annotations
, "Key3"), ==, "Value3");
68 signal
= g_dbus_interface_info_lookup_signal (iface
, "TestSignal");
69 g_assert (signal
!= NULL
);
70 g_assert_cmpint (count_annotations (signal
->annotations
), ==, 1);
71 g_assert_cmpstr (g_dbus_annotation_info_lookup (signal
->annotations
, "Key4"), ==, "Value4");
72 g_assert_cmpstr (g_dbus_annotation_info_lookup (signal
->args
[1]->annotations
, "Key8"), ==, "Value8");
74 property
= g_dbus_interface_info_lookup_property (iface
, "ay");
75 g_assert (property
!= NULL
);
76 g_assert_cmpint (count_annotations (property
->annotations
), ==, 1);
77 g_assert_cmpstr (g_dbus_annotation_info_lookup (property
->annotations
, "Key5"), ==, "Value5");
79 method
= g_dbus_interface_info_lookup_method (iface
, "TestPrimitiveTypes");
80 g_assert (method
!= NULL
);
81 g_assert_cmpstr (g_dbus_annotation_info_lookup (method
->in_args
[4]->annotations
, "Key6"), ==, "Value6");
82 g_assert_cmpstr (g_dbus_annotation_info_lookup (method
->out_args
[5]->annotations
, "Key7"), ==, "Value7");
85 /* ---------------------------------------------------------------------------------------------------- */
88 on_handle_hello_world (FooiGenBar
*object
,
89 GDBusMethodInvocation
*invocation
,
90 const gchar
*greeting
,
94 response
= g_strdup_printf ("Word! You said '%s'. I'm Skeleton, btw!", greeting
);
95 foo_igen_bar_complete_hello_world (object
, invocation
, response
);
101 on_handle_test_primitive_types (FooiGenBar
*object
,
102 GDBusMethodInvocation
*invocation
,
104 gboolean val_boolean
,
112 const gchar
*val_string
,
113 const gchar
*val_objpath
,
114 const gchar
*val_signature
,
115 const gchar
*val_bytestring
,
121 s1
= g_strdup_printf ("Word! You said '%s'. Rock'n'roll!", val_string
);
122 s2
= g_strdup_printf ("/modified%s", val_objpath
);
123 s3
= g_strdup_printf ("assgit%s", val_signature
);
124 foo_igen_bar_complete_test_primitive_types (object
,
133 10000000 + val_uint64
,
146 on_handle_test_non_primitive_types (FooiGenBar
*object
,
147 GDBusMethodInvocation
*invocation
,
148 GVariant
*dict_s_to_s
,
149 GVariant
*dict_s_to_pairs
,
151 const gchar
* const *array_of_strings
,
152 const gchar
* const *array_of_objpaths
,
153 GVariant
*array_of_signatures
,
154 const gchar
* const *array_of_bytestrings
,
159 str
= g_string_new (NULL
);
160 s
= g_variant_print (dict_s_to_s
, TRUE
); g_string_append (str
, s
); g_free (s
);
161 s
= g_variant_print (dict_s_to_pairs
, TRUE
); g_string_append (str
, s
); g_free (s
);
162 s
= g_variant_print (a_struct
, TRUE
); g_string_append (str
, s
); g_free (s
);
163 s
= g_strjoinv (", ", (gchar
**) array_of_strings
);
164 g_string_append_printf (str
, "array_of_strings: [%s] ", s
);
166 s
= g_strjoinv (", ", (gchar
**) array_of_objpaths
);
167 g_string_append_printf (str
, "array_of_objpaths: [%s] ", s
);
169 s
= g_variant_print (array_of_signatures
, TRUE
);
170 g_string_append_printf (str
, "array_of_signatures: %s ", s
);
172 s
= g_strjoinv (", ", (gchar
**) array_of_bytestrings
);
173 g_string_append_printf (str
, "array_of_bytestrings: [%s] ", s
);
175 foo_igen_bar_complete_test_non_primitive_types (object
, invocation
,
179 array_of_bytestrings
,
181 g_string_free (str
, TRUE
);
186 on_handle_request_signal_emission (FooiGenBar
*object
,
187 GDBusMethodInvocation
*invocation
,
193 const gchar
*a_strv
[] = {"foo", "bar", NULL
};
194 const gchar
*a_bytestring_array
[] = {"foo\xff", "bar\xff", NULL
};
195 GVariant
*a_variant
= g_variant_new_parsed ("{'first': (42, 42), 'second': (43, 43)}");
196 foo_igen_bar_emit_test_signal (object
, 43, a_strv
, a_bytestring_array
, a_variant
); /* consumes a_variant */
197 foo_igen_bar_complete_request_signal_emission (object
, invocation
);
203 on_handle_request_multi_property_mods (FooiGenBar
*object
,
204 GDBusMethodInvocation
*invocation
,
207 foo_igen_bar_set_y (object
, foo_igen_bar_get_y (object
) + 1);
208 foo_igen_bar_set_i (object
, foo_igen_bar_get_i (object
) + 1);
209 foo_igen_bar_set_y (object
, foo_igen_bar_get_y (object
) + 1);
210 foo_igen_bar_set_i (object
, foo_igen_bar_get_i (object
) + 1);
211 g_dbus_interface_skeleton_flush (G_DBUS_INTERFACE_SKELETON (object
));
212 foo_igen_bar_set_y (object
, foo_igen_bar_get_y (object
) + 1);
213 foo_igen_bar_set_i (object
, foo_igen_bar_get_i (object
) + 1);
214 foo_igen_bar_complete_request_multi_property_mods (object
, invocation
);
219 on_handle_property_cancellation (FooiGenBar
*object
,
220 GDBusMethodInvocation
*invocation
,
224 n
= foo_igen_bar_get_n (object
);
225 /* This queues up a PropertiesChange event */
226 foo_igen_bar_set_n (object
, n
+ 1);
227 /* this modifies the queued up event */
228 foo_igen_bar_set_n (object
, n
);
229 /* this flushes all PropertiesChanges event (sends the D-Bus message right
230 * away, if any - there should not be any)
232 g_dbus_interface_skeleton_flush (G_DBUS_INTERFACE_SKELETON (object
));
233 /* this makes us return the reply D-Bus method */
234 foo_igen_bar_complete_property_cancellation (object
, invocation
);
238 /* ---------------------------------------------------------------------------------------------------- */
241 on_handle_force_method (FooiGenBat
*object
,
242 GDBusMethodInvocation
*invocation
,
243 GVariant
*force_in_i
,
244 GVariant
*force_in_s
,
245 GVariant
*force_in_ay
,
246 GVariant
*force_in_struct
,
252 GVariant
*ret_struct
;
256 ret_i
= g_variant_new_int32 (g_variant_get_int32 (force_in_i
) + 10);
257 s
= g_strdup_printf ("%s_foo", g_variant_get_string (force_in_s
, NULL
));
258 ret_s
= g_variant_new_string (s
);
260 s
= g_strdup_printf ("%s_foo\xff", g_variant_get_bytestring (force_in_ay
));
261 ret_ay
= g_variant_new_bytestring (s
);
264 g_variant_get (force_in_struct
, "(i)", &val
);
265 ret_struct
= g_variant_new ("(i)", val
+ 10);
267 g_variant_ref_sink (ret_i
);
268 g_variant_ref_sink (ret_s
);
269 g_variant_ref_sink (ret_ay
);
270 g_variant_ref_sink (ret_struct
);
272 foo_igen_bat_emit_force_signal (object
,
278 foo_igen_bat_complete_force_method (object
,
285 g_variant_unref (ret_i
);
286 g_variant_unref (ret_s
);
287 g_variant_unref (ret_ay
);
288 g_variant_unref (ret_struct
);
294 /* ---------------------------------------------------------------------------------------------------- */
297 my_g_authorize_method_handler (GDBusInterfaceSkeleton
*interface
,
298 GDBusMethodInvocation
*invocation
,
301 const gchar
*method_name
;
306 method_name
= g_dbus_method_invocation_get_method_name (invocation
);
307 if (g_strcmp0 (method_name
, "CheckNotAuthorized") == 0)
311 else if (g_strcmp0 (method_name
, "CheckAuthorized") == 0)
315 else if (g_strcmp0 (method_name
, "CheckNotAuthorizedFromObject") == 0)
321 g_assert_not_reached ();
326 g_dbus_method_invocation_return_error (invocation
,
328 G_IO_ERROR_PERMISSION_DENIED
,
329 "not authorized...");
335 my_object_authorize_method_handler (GDBusObjectSkeleton
*object
,
336 GDBusInterfaceSkeleton
*interface
,
337 GDBusMethodInvocation
*invocation
,
340 const gchar
*method_name
;
345 method_name
= g_dbus_method_invocation_get_method_name (invocation
);
346 if (g_strcmp0 (method_name
, "CheckNotAuthorized") == 0)
350 else if (g_strcmp0 (method_name
, "CheckAuthorized") == 0)
354 else if (g_strcmp0 (method_name
, "CheckNotAuthorizedFromObject") == 0)
360 g_assert_not_reached ();
365 g_dbus_method_invocation_return_error (invocation
,
368 "not authorized (from object)...");
374 on_handle_check_not_authorized (FooiGenAuthorize
*object
,
375 GDBusMethodInvocation
*invocation
,
378 foo_igen_authorize_complete_check_not_authorized (object
, invocation
);
383 on_handle_check_authorized (FooiGenAuthorize
*object
,
384 GDBusMethodInvocation
*invocation
,
387 foo_igen_authorize_complete_check_authorized (object
, invocation
);
392 on_handle_check_not_authorized_from_object (FooiGenAuthorize
*object
,
393 GDBusMethodInvocation
*invocation
,
396 foo_igen_authorize_complete_check_not_authorized_from_object (object
, invocation
);
400 /* ---------------------------------------------------------------------------------------------------- */
403 on_handle_get_self (FooiGenMethodThreads
*object
,
404 GDBusMethodInvocation
*invocation
,
408 s
= g_strdup_printf ("%p", (void *)g_thread_self ());
409 foo_igen_method_threads_complete_get_self (object
, invocation
, s
);
414 /* ---------------------------------------------------------------------------------------------------- */
416 static GThread
*method_handler_thread
= NULL
;
418 static FooiGenBar
*exported_bar_object
= NULL
;
419 static FooiGenBat
*exported_bat_object
= NULL
;
420 static FooiGenAuthorize
*exported_authorize_object
= NULL
;
421 static GDBusObjectSkeleton
*authorize_enclosing_object
= NULL
;
422 static FooiGenMethodThreads
*exported_thread_object_1
= NULL
;
423 static FooiGenMethodThreads
*exported_thread_object_2
= NULL
;
426 unexport_objects (void)
428 g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (exported_bar_object
));
429 g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (exported_bat_object
));
430 g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (exported_authorize_object
));
431 g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (exported_thread_object_1
));
432 g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (exported_thread_object_2
));
436 on_bus_acquired (GDBusConnection
*connection
,
442 /* Test that we can export an object using the generated
443 * FooiGenBarSkeleton subclass. Notes:
445 * 1. We handle methods by simply connecting to the appropriate
448 * 2. Property storage is taken care of by the class; we can
449 * use g_object_get()/g_object_set() (and the generated
450 * C bindings at will)
453 exported_bar_object
= foo_igen_bar_skeleton_new ();
454 foo_igen_bar_set_ay (exported_bar_object
, "ABCabc");
455 foo_igen_bar_set_y (exported_bar_object
, 42);
456 foo_igen_bar_set_d (exported_bar_object
, 43.0);
457 foo_igen_bar_set_finally_normal_name (exported_bar_object
, "There aint no place like home");
458 foo_igen_bar_set_writeonly_property (exported_bar_object
, "Mr. Burns");
460 /* The following works because it's on the Skeleton object - it will
461 * fail (at run-time) on a Proxy (see on_proxy_appeared() below)
463 foo_igen_bar_set_readonly_property (exported_bar_object
, "blah");
464 g_assert_cmpstr (foo_igen_bar_get_writeonly_property (exported_bar_object
), ==, "Mr. Burns");
466 g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (exported_bar_object
),
470 g_assert_no_error (error
);
471 g_signal_connect (exported_bar_object
,
472 "handle-hello-world",
473 G_CALLBACK (on_handle_hello_world
),
475 g_signal_connect (exported_bar_object
,
476 "handle-test-primitive-types",
477 G_CALLBACK (on_handle_test_primitive_types
),
479 g_signal_connect (exported_bar_object
,
480 "handle-test-non-primitive-types",
481 G_CALLBACK (on_handle_test_non_primitive_types
),
483 g_signal_connect (exported_bar_object
,
484 "handle-request-signal-emission",
485 G_CALLBACK (on_handle_request_signal_emission
),
487 g_signal_connect (exported_bar_object
,
488 "handle-request-multi-property-mods",
489 G_CALLBACK (on_handle_request_multi_property_mods
),
491 g_signal_connect (exported_bar_object
,
492 "handle-property-cancellation",
493 G_CALLBACK (on_handle_property_cancellation
),
496 exported_bat_object
= foo_igen_bat_skeleton_new ();
497 g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (exported_bat_object
),
501 g_assert_no_error (error
);
502 g_signal_connect (exported_bat_object
,
503 "handle-force-method",
504 G_CALLBACK (on_handle_force_method
),
506 g_object_set (exported_bat_object
,
507 "force-i", g_variant_new_int32 (43),
508 "force-s", g_variant_new_string ("prop string"),
509 "force-ay", g_variant_new_bytestring ("prop bytestring\xff"),
510 "force-struct", g_variant_new ("(i)", 4300),
513 authorize_enclosing_object
= g_dbus_object_skeleton_new ("/authorize");
514 g_signal_connect (authorize_enclosing_object
,
516 G_CALLBACK (my_object_authorize_method_handler
),
518 exported_authorize_object
= foo_igen_authorize_skeleton_new ();
519 g_dbus_object_skeleton_add_interface (authorize_enclosing_object
,
520 G_DBUS_INTERFACE_SKELETON (exported_authorize_object
));
521 g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (exported_authorize_object
),
525 g_assert_no_error (error
);
526 g_signal_connect (exported_authorize_object
,
527 "g-authorize-method",
528 G_CALLBACK (my_g_authorize_method_handler
),
530 g_signal_connect (exported_authorize_object
,
531 "handle-check-not-authorized",
532 G_CALLBACK (on_handle_check_not_authorized
),
534 g_signal_connect (exported_authorize_object
,
535 "handle-check-authorized",
536 G_CALLBACK (on_handle_check_authorized
),
538 g_signal_connect (exported_authorize_object
,
539 "handle-check-not-authorized-from-object",
540 G_CALLBACK (on_handle_check_not_authorized_from_object
),
544 /* only object 1 has the G_DBUS_INTERFACE_SKELETON_FLAGS_HANDLE_METHOD_INVOCATIONS_IN_THREAD flag set */
545 exported_thread_object_1
= foo_igen_method_threads_skeleton_new ();
546 g_dbus_interface_skeleton_set_flags (G_DBUS_INTERFACE_SKELETON (exported_thread_object_1
),
547 G_DBUS_INTERFACE_SKELETON_FLAGS_HANDLE_METHOD_INVOCATIONS_IN_THREAD
);
549 g_assert (!g_dbus_interface_skeleton_has_connection (G_DBUS_INTERFACE_SKELETON (exported_thread_object_1
), connection
));
550 g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (exported_thread_object_1
),
554 g_assert_no_error (error
);
555 g_signal_connect (exported_thread_object_1
,
557 G_CALLBACK (on_handle_get_self
),
559 g_assert_cmpint (g_dbus_interface_skeleton_get_flags (G_DBUS_INTERFACE_SKELETON (exported_thread_object_1
)), ==, G_DBUS_INTERFACE_SKELETON_FLAGS_HANDLE_METHOD_INVOCATIONS_IN_THREAD
);
561 exported_thread_object_2
= foo_igen_method_threads_skeleton_new ();
562 g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (exported_thread_object_2
),
566 g_assert_no_error (error
);
567 g_signal_connect (exported_thread_object_2
,
569 G_CALLBACK (on_handle_get_self
),
572 g_assert_cmpint (g_dbus_interface_skeleton_get_flags (G_DBUS_INTERFACE_SKELETON (exported_thread_object_2
)), ==, G_DBUS_INTERFACE_SKELETON_FLAGS_NONE
);
574 method_handler_thread
= g_thread_self ();
577 static gpointer
check_proxies_in_thread (gpointer user_data
);
580 on_name_acquired (GDBusConnection
*connection
,
584 GMainLoop
*loop
= user_data
;
586 g_thread_new ("check-proxies",
587 check_proxies_in_thread
,
592 on_name_lost (GDBusConnection
*connection
,
596 g_assert_not_reached ();
599 /* ---------------------------------------------------------------------------------------------------- */
603 GMainLoop
*thread_loop
;
606 guint num_g_properties_changed
;
607 gboolean received_test_signal
;
613 on_notify_u (GObject
*object
,
617 ClientData
*data
= user_data
;
618 g_assert_cmpstr (pspec
->name
, ==, "u");
619 data
->num_notify_u
+= 1;
623 on_notify_n (GObject
*object
,
627 ClientData
*data
= user_data
;
628 g_assert_cmpstr (pspec
->name
, ==, "n");
629 data
->num_notify_n
+= 1;
633 on_g_properties_changed (GDBusProxy
*_proxy
,
634 GVariant
*changed_properties
,
635 const gchar
* const *invalidated_properties
,
638 ClientData
*data
= user_data
;
639 FooiGenBar
*proxy
= FOO_IGEN_BAR (_proxy
);
641 g_assert_cmpint (g_variant_n_children (changed_properties
), ==, 2);
643 if (data
->num_g_properties_changed
== 0)
645 g_assert_cmpint (data
->initial_y
, ==, foo_igen_bar_get_y (proxy
) - 2);
646 g_assert_cmpint (data
->initial_i
, ==, foo_igen_bar_get_i (proxy
) - 2);
648 else if (data
->num_g_properties_changed
== 1)
650 g_assert_cmpint (data
->initial_y
, ==, foo_igen_bar_get_y (proxy
) - 3);
651 g_assert_cmpint (data
->initial_i
, ==, foo_igen_bar_get_i (proxy
) - 3);
654 g_assert_not_reached ();
656 data
->num_g_properties_changed
++;
658 if (data
->num_g_properties_changed
== 2)
659 g_main_loop_quit (data
->thread_loop
);
663 on_test_signal (FooiGenBar
*proxy
,
665 const gchar
* const *array_of_strings
,
666 const gchar
* const *array_of_bytestrings
,
667 GVariant
*dict_s_to_pairs
,
670 ClientData
*data
= user_data
;
672 g_assert_cmpint (val_int32
, ==, 43);
673 g_assert_cmpstr (array_of_strings
[0], ==, "foo");
674 g_assert_cmpstr (array_of_strings
[1], ==, "bar");
675 g_assert (array_of_strings
[2] == NULL
);
676 g_assert_cmpstr (array_of_bytestrings
[0], ==, "foo\xff");
677 g_assert_cmpstr (array_of_bytestrings
[1], ==, "bar\xff");
678 g_assert (array_of_bytestrings
[2] == NULL
);
680 data
->received_test_signal
= TRUE
;
681 g_main_loop_quit (data
->thread_loop
);
685 on_property_cancellation_cb (FooiGenBar
*proxy
,
689 ClientData
*data
= user_data
;
691 GError
*error
= NULL
;
694 ret
= foo_igen_bar_call_property_cancellation_finish (proxy
, res
, &error
);
695 g_assert_no_error (error
);
698 g_main_loop_quit (data
->thread_loop
);
702 check_bar_proxy (FooiGenBar
*proxy
,
703 GMainLoop
*thread_loop
)
705 const gchar
*array_of_strings
[3] = {"one", "two", NULL
};
706 const gchar
*array_of_strings_2
[3] = {"one2", "two2", NULL
};
707 const gchar
*array_of_objpaths
[3] = {"/one", "/one/two", NULL
};
708 GVariant
*array_of_signatures
= NULL
;
709 const gchar
*array_of_bytestrings
[3] = {"one\xff", "two\xff", NULL
};
710 gchar
**ret_array_of_strings
= NULL
;
711 gchar
**ret_array_of_objpaths
= NULL
;
712 GVariant
*ret_array_of_signatures
= NULL
;
713 gchar
**ret_array_of_bytestrings
= NULL
;
715 gboolean ret_val_boolean
;
716 gint16 ret_val_int16
;
717 guint16 ret_val_uint16
;
719 guint ret_val_uint32
;
720 gint64 ret_val_int64
;
721 guint64 ret_val_uint64
;
722 gdouble ret_val_double
;
723 gchar
*ret_val_string
;
724 gchar
*ret_val_objpath
;
725 gchar
*ret_val_signature
;
726 gchar
*ret_val_bytestring
;
752 gchar
**val_unset_as
;
753 gchar
**val_unset_ao
;
754 GVariant
*val_unset_ag
;
755 GVariant
*val_unset_struct
;
756 gchar
*val_finally_normal_name
;
759 const gchar
*const *read_as
;
760 const gchar
*const *read_as2
;
761 const gchar
*const *read_as3
;
763 data
= g_new0 (ClientData
, 1);
764 data
->thread_loop
= thread_loop
;
766 v
= g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy
), "y");
767 g_assert (v
!= NULL
);
770 /* set empty values to non-empty */
780 val_unset_struct
= NULL
;
781 /* check properties */
799 "unset_i", &val_unset_i
,
800 "unset_d", &val_unset_d
,
801 "unset_s", &val_unset_s
,
802 "unset_o", &val_unset_o
,
803 "unset_g", &val_unset_g
,
804 "unset_ay", &val_unset_ay
,
805 "unset_as", &val_unset_as
,
806 "unset_ao", &val_unset_ao
,
807 "unset_ag", &val_unset_ag
,
808 "unset_struct", &val_unset_struct
,
809 "finally-normal-name", &val_finally_normal_name
,
811 g_assert_cmpint (val_y
, ==, 42);
812 g_assert_cmpstr (val_finally_normal_name
, ==, "There aint no place like home");
816 g_assert_cmpstr (val_ay
, ==, "ABCabc");
820 g_variant_unref (val_ag
);
821 g_free (val_finally_normal_name
);
822 /* check empty values */
823 g_assert_cmpint (val_unset_i
, ==, 0);
824 g_assert_cmpfloat (val_unset_d
, ==, 0.0);
825 g_assert_cmpstr (val_unset_s
, ==, "");
826 g_assert_cmpstr (val_unset_o
, ==, "/");
827 g_assert_cmpstr (val_unset_g
, ==, "");
828 g_free (val_unset_s
);
829 g_free (val_unset_o
);
830 g_free (val_unset_g
);
831 g_assert_cmpstr (val_unset_ay
, ==, "");
832 g_assert (val_unset_as
[0] == NULL
);
833 g_assert (val_unset_ao
[0] == NULL
);
834 g_assert (g_variant_is_of_type (val_unset_ag
, G_VARIANT_TYPE ("ag")));
835 g_assert (g_variant_is_of_type (val_unset_struct
, G_VARIANT_TYPE ("(idsogayasaoag)")));
836 s
= g_variant_print (val_unset_struct
, TRUE
);
837 g_assert_cmpstr (s
, ==, "(0, 0.0, '', objectpath '/', signature '', @ay [], @as [], @ao [], @ag [])");
839 g_free (val_unset_ay
);
840 g_strfreev (val_unset_as
);
841 g_strfreev (val_unset_ao
);
842 g_variant_unref (val_unset_ag
);
843 g_variant_unref (val_unset_struct
);
845 /* Try setting a property. This causes the generated glue to invoke
846 * the org.fd.DBus.Properties.Set() method asynchronously. So we
847 * have to wait for properties-changed...
849 foo_igen_bar_set_finally_normal_name (proxy
, "foo!");
850 _g_assert_property_notify (proxy
, "finally-normal-name");
851 g_assert_cmpstr (foo_igen_bar_get_finally_normal_name (proxy
), ==, "foo!");
853 /* Try setting properties that requires memory management. This
854 * is to exercise the paths that frees the references.
861 "ay", g_variant_new_parsed ("[byte 0x65, 0x67]"),
862 "as", array_of_strings
,
863 "ao", array_of_objpaths
,
864 "ag", g_variant_new_parsed ("[@g 'ass', 'git']"),
868 ret
= foo_igen_bar_call_test_primitive_types_sync (proxy
,
895 NULL
, /* GCancellable */
897 g_assert_no_error (error
);
900 g_clear_pointer (&ret_val_string
, g_free
);
901 g_clear_pointer (&ret_val_objpath
, g_free
);
902 g_clear_pointer (&ret_val_signature
, g_free
);
903 g_clear_pointer (&ret_val_bytestring
, g_free
);
906 array_of_signatures
= g_variant_ref_sink (g_variant_new_parsed ("[@g 'ass', 'git']"));
907 ret
= foo_igen_bar_call_test_non_primitive_types_sync (proxy
,
908 g_variant_new_parsed ("{'one': 'red',"
910 g_variant_new_parsed ("{'first': (42, 42), "
911 "'second': (43, 43)}"),
912 g_variant_new_parsed ("(42, 'foo', 'bar')"),
916 array_of_bytestrings
,
917 &ret_array_of_strings
,
918 &ret_array_of_objpaths
,
919 &ret_array_of_signatures
,
920 &ret_array_of_bytestrings
,
922 NULL
, /* GCancellable */
925 g_assert_no_error (error
);
928 g_assert_nonnull (ret_array_of_strings
);
929 g_assert_cmpuint (g_strv_length ((gchar
**) ret_array_of_strings
), ==,
930 g_strv_length ((gchar
**) array_of_strings
));
931 g_assert_nonnull (ret_array_of_objpaths
);
932 g_assert_cmpuint (g_strv_length ((gchar
**) ret_array_of_objpaths
), ==,
933 g_strv_length ((gchar
**) array_of_objpaths
));
934 g_assert_nonnull (ret_array_of_signatures
);
935 g_assert_true (g_variant_equal (ret_array_of_signatures
, array_of_signatures
));
936 g_assert_nonnull (ret_array_of_bytestrings
);
937 g_assert_cmpuint (g_strv_length ((gchar
**) ret_array_of_bytestrings
), ==,
938 g_strv_length ((gchar
**) array_of_bytestrings
));
940 g_clear_pointer (&ret_array_of_strings
, g_strfreev
);
941 g_clear_pointer (&ret_array_of_objpaths
, g_strfreev
);
942 g_clear_pointer (&ret_array_of_signatures
, g_variant_unref
);
943 g_clear_pointer (&ret_array_of_bytestrings
, g_strfreev
);
944 g_clear_pointer (&s
, g_free
);
946 /* Check that org.freedesktop.DBus.Error.UnknownMethod is returned on
947 * unimplemented methods.
950 ret
= foo_igen_bar_call_unimplemented_method_sync (proxy
, NULL
/* GCancellable */, &error
);
951 g_assert_error (error
, G_DBUS_ERROR
, G_DBUS_ERROR_UNKNOWN_METHOD
);
952 g_error_free (error
);
956 g_signal_connect (proxy
,
958 G_CALLBACK (on_test_signal
),
961 ret
= foo_igen_bar_call_request_signal_emission_sync (proxy
, 0, NULL
, &error
);
962 g_assert_no_error (error
);
965 g_assert (!data
->received_test_signal
);
966 g_main_loop_run (thread_loop
);
967 g_assert (data
->received_test_signal
);
969 /* Try setting a property. This causes the generated glue to invoke
970 * the org.fd.DBus.Properties.Set() method asynchronously. So we
971 * have to wait for properties-changed...
973 foo_igen_bar_set_finally_normal_name (proxy
, "hey back!");
974 _g_assert_property_notify (proxy
, "finally-normal-name");
975 g_assert_cmpstr (foo_igen_bar_get_finally_normal_name (proxy
), ==, "hey back!");
977 /* Check that multiple calls to a strv getter works... and that
978 * updates on them works as well (See comment for "property vfuncs"
979 * in gio/gdbus-codegen/codegen.py for details)
981 read_as
= foo_igen_bar_get_as (proxy
);
982 read_as2
= foo_igen_bar_get_as (proxy
);
983 g_assert_cmpint (g_strv_length ((gchar
**) read_as
), ==, 2);
984 g_assert_cmpstr (read_as
[0], ==, "one");
985 g_assert_cmpstr (read_as
[1], ==, "two");
986 g_assert (read_as
== read_as2
); /* this is more testing an implementation detail */
988 "as", array_of_strings_2
,
990 _g_assert_property_notify (proxy
, "as");
991 read_as3
= foo_igen_bar_get_as (proxy
);
992 g_assert_cmpint (g_strv_length ((gchar
**) read_as3
), ==, 2);
993 g_assert_cmpstr (read_as3
[0], ==, "one2");
994 g_assert_cmpstr (read_as3
[1], ==, "two2");
996 /* Check that grouping changes in idle works.
998 * See on_handle_request_multi_property_mods(). The server should
999 * emit exactly two PropertiesChanged signals each containing two
1002 * On the first reception, y and i should both be increased by
1003 * two. On the second reception, only by one. The signal handler
1006 * This also checks that _drain_notify() works.
1008 data
->initial_y
= foo_igen_bar_get_y (proxy
);
1009 data
->initial_i
= foo_igen_bar_get_i (proxy
);
1010 g_signal_connect (proxy
,
1011 "g-properties-changed",
1012 G_CALLBACK (on_g_properties_changed
),
1015 ret
= foo_igen_bar_call_request_multi_property_mods_sync (proxy
, NULL
, &error
);
1016 g_assert_no_error (error
);
1018 g_main_loop_run (thread_loop
);
1019 g_assert_cmpint (data
->num_g_properties_changed
, ==, 2);
1020 g_signal_handlers_disconnect_by_func (proxy
,
1021 G_CALLBACK (on_g_properties_changed
),
1024 /* Check that we don't emit PropertiesChanged() if the property
1025 * didn't change... we actually get two notifies.. one for the
1026 * local set (without a value change) and one when receiving
1027 * the PropertiesChanged() signal generated from the remote end.
1029 g_assert_cmpint (data
->num_notify_u
, ==, 0);
1030 g_signal_connect (proxy
,
1032 G_CALLBACK (on_notify_u
),
1034 foo_igen_bar_set_u (proxy
, 1042);
1035 g_assert_cmpint (data
->num_notify_u
, ==, 1);
1036 g_assert_cmpint (foo_igen_bar_get_u (proxy
), ==, 0);
1037 _g_assert_property_notify (proxy
, "u");
1038 g_assert_cmpint (foo_igen_bar_get_u (proxy
), ==, 1042);
1039 g_assert_cmpint (data
->num_notify_u
, ==, 2);
1041 /* Now change u again to the same value.. this will cause a
1042 * local notify:: notify and the usual Properties.Set() call
1044 * (Btw, why also the Set() call if the value in the cache is
1045 * the same? Because someone else might have changed it
1046 * in the mean time and we're just waiting to receive the
1047 * PropertiesChanged() signal...)
1049 * More tricky - how do we check for the *absence* of the
1050 * notification that u changed? Simple: we change another
1051 * property and wait for that PropertiesChanged() message
1054 foo_igen_bar_set_u (proxy
, 1042);
1055 g_assert_cmpint (data
->num_notify_u
, ==, 3);
1057 g_assert_cmpint (data
->num_notify_n
, ==, 0);
1058 g_signal_connect (proxy
,
1060 G_CALLBACK (on_notify_n
),
1062 foo_igen_bar_set_n (proxy
, 10042);
1063 g_assert_cmpint (data
->num_notify_n
, ==, 1);
1064 g_assert_cmpint (foo_igen_bar_get_n (proxy
), ==, 0);
1065 _g_assert_property_notify (proxy
, "n");
1066 g_assert_cmpint (foo_igen_bar_get_n (proxy
), ==, 10042);
1067 g_assert_cmpint (data
->num_notify_n
, ==, 2);
1068 /* Checks that u didn't change at all */
1069 g_assert_cmpint (data
->num_notify_u
, ==, 3);
1071 /* Now we check that if the service does
1073 * guint n = foo_igen_bar_get_n (foo);
1074 * foo_igen_bar_set_n (foo, n + 1);
1075 * foo_igen_bar_set_n (foo, n);
1077 * then no PropertiesChanged() signal is emitted!
1080 foo_igen_bar_call_property_cancellation (proxy
,
1081 NULL
, /* GCancellable */
1082 (GAsyncReadyCallback
) on_property_cancellation_cb
,
1084 g_main_loop_run (thread_loop
);
1085 /* Checks that n didn't change at all */
1086 g_assert_cmpint (data
->num_notify_n
, ==, 2);
1090 g_variant_unref (array_of_signatures
);
1093 /* ---------------------------------------------------------------------------------------------------- */
1096 on_force_signal (FooiGenBat
*proxy
,
1100 GVariant
*force_struct
,
1103 gboolean
*signal_received
= user_data
;
1106 g_assert (!(*signal_received
));
1108 g_assert_cmpint (g_variant_get_int32 (force_i
), ==, 42 + 10);
1109 g_assert_cmpstr (g_variant_get_string (force_s
, NULL
), ==, "a string_foo");
1110 g_assert_cmpstr (g_variant_get_bytestring (force_ay
), ==, "a bytestring\xff_foo\xff");
1111 g_variant_get (force_struct
, "(i)", &val
);
1112 g_assert_cmpint (val
, ==, 4200 + 10);
1114 *signal_received
= TRUE
;
1118 check_bat_proxy (FooiGenBat
*proxy
,
1119 GMainLoop
*thread_loop
)
1125 GVariant
*ret_struct
;
1127 gboolean force_signal_received
;
1129 /* --------------------------------------------------- */
1130 /* Check type-mapping where we force use of a GVariant */
1131 /* --------------------------------------------------- */
1133 /* check properties */
1134 g_object_get (proxy
,
1137 "force-ay", &ret_ay
,
1138 "force-struct", &ret_struct
,
1140 g_assert_cmpint (g_variant_get_int32 (ret_i
), ==, 43);
1141 g_assert_cmpstr (g_variant_get_string (ret_s
, NULL
), ==, "prop string");
1142 g_assert_cmpstr (g_variant_get_bytestring (ret_ay
), ==, "prop bytestring\xff");
1143 g_variant_get (ret_struct
, "(i)", &val
);
1144 g_assert_cmpint (val
, ==, 4300);
1145 g_variant_unref (ret_i
);
1146 g_variant_unref (ret_s
);
1147 g_variant_unref (ret_ay
);
1148 g_variant_unref (ret_struct
);
1150 /* check method and signal */
1151 force_signal_received
= FALSE
;
1152 g_signal_connect (proxy
,
1154 G_CALLBACK (on_force_signal
),
1155 &force_signal_received
);
1158 foo_igen_bat_call_force_method_sync (proxy
,
1159 g_variant_new_int32 (42),
1160 g_variant_new_string ("a string"),
1161 g_variant_new_bytestring ("a bytestring\xff"),
1162 g_variant_new ("(i)", 4200),
1167 NULL
, /* GCancellable* */
1169 g_assert_no_error (error
);
1170 g_assert_cmpint (g_variant_get_int32 (ret_i
), ==, 42 + 10);
1171 g_assert_cmpstr (g_variant_get_string (ret_s
, NULL
), ==, "a string_foo");
1172 g_assert_cmpstr (g_variant_get_bytestring (ret_ay
), ==, "a bytestring\xff_foo\xff");
1173 g_variant_get (ret_struct
, "(i)", &val
);
1174 g_assert_cmpint (val
, ==, 4200 + 10);
1175 g_variant_unref (ret_i
);
1176 g_variant_unref (ret_s
);
1177 g_variant_unref (ret_ay
);
1178 g_variant_unref (ret_struct
);
1179 _g_assert_signal_received (proxy
, "force-signal");
1180 g_assert (force_signal_received
);
1183 /* ---------------------------------------------------------------------------------------------------- */
1186 check_authorize_proxy (FooiGenAuthorize
*proxy
,
1187 GMainLoop
*thread_loop
)
1192 /* Check that g-authorize-method works as intended */
1195 ret
= foo_igen_authorize_call_check_not_authorized_sync (proxy
, NULL
, &error
);
1196 g_assert_error (error
, G_IO_ERROR
, G_IO_ERROR_PERMISSION_DENIED
);
1197 g_error_free (error
);
1201 ret
= foo_igen_authorize_call_check_authorized_sync (proxy
, NULL
, &error
);
1202 g_assert_no_error (error
);
1206 ret
= foo_igen_authorize_call_check_not_authorized_from_object_sync (proxy
, NULL
, &error
);
1207 g_assert_error (error
, G_IO_ERROR
, G_IO_ERROR_PENDING
);
1208 g_error_free (error
);
1212 /* ---------------------------------------------------------------------------------------------------- */
1215 get_self_via_proxy (FooiGenMethodThreads
*proxy_1
)
1223 ret
= foo_igen_method_threads_call_get_self_sync (proxy_1
, &self_str
, NULL
, &error
);
1224 g_assert_no_error (error
);
1227 g_assert_cmpint (sscanf (self_str
, "%p", &self
), ==, 1);
1235 check_thread_proxies (FooiGenMethodThreads
*proxy_1
,
1236 FooiGenMethodThreads
*proxy_2
,
1237 GMainLoop
*thread_loop
)
1239 /* proxy_1 is indeed using threads so should never get the handler thread */
1240 g_assert (get_self_via_proxy (proxy_1
) != method_handler_thread
);
1242 /* proxy_2 is not using threads so should get the handler thread */
1243 g_assert (get_self_via_proxy (proxy_2
) == method_handler_thread
);
1246 /* ---------------------------------------------------------------------------------------------------- */
1249 check_proxies_in_thread (gpointer user_data
)
1251 GMainLoop
*loop
= user_data
;
1252 GMainContext
*thread_context
;
1253 GMainLoop
*thread_loop
;
1255 FooiGenBar
*bar_proxy
;
1256 FooiGenBat
*bat_proxy
;
1257 FooiGenAuthorize
*authorize_proxy
;
1258 FooiGenMethodThreads
*thread_proxy_1
;
1259 FooiGenMethodThreads
*thread_proxy_2
;
1261 thread_context
= g_main_context_new ();
1262 thread_loop
= g_main_loop_new (thread_context
, FALSE
);
1263 g_main_context_push_thread_default (thread_context
);
1265 /* Check the object */
1267 bar_proxy
= foo_igen_bar_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION
,
1268 G_DBUS_PROXY_FLAGS_NONE
,
1269 "org.gtk.GDBus.BindingsTool.Test",
1271 NULL
, /* GCancellable* */
1273 check_bar_proxy (bar_proxy
, thread_loop
);
1274 g_assert_no_error (error
);
1275 g_object_unref (bar_proxy
);
1278 bat_proxy
= foo_igen_bat_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION
,
1279 G_DBUS_PROXY_FLAGS_NONE
,
1280 "org.gtk.GDBus.BindingsTool.Test",
1282 NULL
, /* GCancellable* */
1284 check_bat_proxy (bat_proxy
, thread_loop
);
1285 g_assert_no_error (error
);
1286 g_object_unref (bat_proxy
);
1289 authorize_proxy
= foo_igen_authorize_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION
,
1290 G_DBUS_PROXY_FLAGS_NONE
,
1291 "org.gtk.GDBus.BindingsTool.Test",
1293 NULL
, /* GCancellable* */
1295 check_authorize_proxy (authorize_proxy
, thread_loop
);
1296 g_assert_no_error (error
);
1297 g_object_unref (authorize_proxy
);
1300 thread_proxy_1
= foo_igen_method_threads_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION
,
1301 G_DBUS_PROXY_FLAGS_NONE
,
1302 "org.gtk.GDBus.BindingsTool.Test",
1303 "/method_threads_1",
1304 NULL
, /* GCancellable* */
1306 g_assert_no_error (error
);
1307 thread_proxy_2
= foo_igen_method_threads_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION
,
1308 G_DBUS_PROXY_FLAGS_NONE
,
1309 "org.gtk.GDBus.BindingsTool.Test",
1310 "/method_threads_2",
1311 NULL
, /* GCancellable* */
1313 g_assert_no_error (error
);
1314 check_thread_proxies (thread_proxy_1
, thread_proxy_2
, thread_loop
);
1315 g_object_unref (thread_proxy_1
);
1316 g_object_unref (thread_proxy_2
);
1318 g_main_loop_unref (thread_loop
);
1319 g_main_context_unref (thread_context
);
1321 /* this breaks out of the loop in main() (below) */
1322 g_main_loop_quit (loop
);
1326 /* ---------------------------------------------------------------------------------------------------- */
1335 introspect_cb (GDBusConnection
*connection
,
1339 IntrospectData
*data
= user_data
;
1344 result
= g_dbus_connection_call_finish (connection
,
1347 g_assert_no_error (error
);
1348 g_assert (result
!= NULL
);
1349 g_variant_get (result
, "(s)", &data
->xml
);
1350 g_variant_unref (result
);
1352 g_main_loop_quit (data
->loop
);
1355 static GDBusNodeInfo
*
1356 introspect (GDBusConnection
*connection
,
1358 const gchar
*object_path
,
1362 GDBusNodeInfo
*node_info
;
1363 IntrospectData
*data
;
1365 data
= g_new0 (IntrospectData
, 1);
1369 /* do this async to avoid deadlocks */
1370 g_dbus_connection_call (connection
,
1373 "org.freedesktop.DBus.Introspectable",
1376 G_VARIANT_TYPE ("(s)"),
1377 G_DBUS_CALL_FLAGS_NONE
,
1380 (GAsyncReadyCallback
) introspect_cb
,
1382 g_main_loop_run (loop
);
1383 g_assert (data
->xml
!= NULL
);
1386 node_info
= g_dbus_node_info_new_for_xml (data
->xml
, &error
);
1387 g_assert_no_error (error
);
1388 g_assert (node_info
!= NULL
);
1396 count_interfaces (GDBusNodeInfo
*info
)
1399 for (n
= 0; info
->interfaces
!= NULL
&& info
->interfaces
[n
] != NULL
; n
++)
1405 count_nodes (GDBusNodeInfo
*info
)
1408 for (n
= 0; info
->nodes
!= NULL
&& info
->nodes
[n
] != NULL
; n
++)
1414 has_interface (GDBusNodeInfo
*info
,
1418 for (n
= 0; info
->interfaces
!= NULL
&& info
->interfaces
[n
] != NULL
; n
++)
1420 if (g_strcmp0 (info
->interfaces
[n
]->name
, name
) == 0)
1426 /* ---------------------------------------------------------------------------------------------------- */
1431 } OMGetManagedObjectsData
;
1434 om_get_all_cb (GDBusConnection
*connection
,
1438 OMGetManagedObjectsData
*data
= user_data
;
1442 data
->result
= g_dbus_connection_call_finish (connection
,
1445 g_assert_no_error (error
);
1446 g_assert (data
->result
!= NULL
);
1447 g_main_loop_quit (data
->loop
);
1451 om_check_get_all (GDBusConnection
*c
,
1455 OMGetManagedObjectsData data
;
1461 /* do this async to avoid deadlocks */
1462 g_dbus_connection_call (c
,
1463 g_dbus_connection_get_unique_name (c
),
1465 "org.freedesktop.DBus.ObjectManager",
1466 "GetManagedObjects",
1468 G_VARIANT_TYPE ("(a{oa{sa{sv}}})"),
1469 G_DBUS_CALL_FLAGS_NONE
,
1472 (GAsyncReadyCallback
) om_get_all_cb
,
1474 g_main_loop_run (loop
);
1475 g_assert (data
.result
!= NULL
);
1476 s
= g_variant_print (data
.result
, TRUE
);
1477 g_assert_cmpstr (s
, ==, str
);
1479 g_variant_unref (data
.result
);
1487 guint num_object_proxy_added_signals
;
1488 guint num_object_proxy_removed_signals
;
1489 guint num_interface_added_signals
;
1490 guint num_interface_removed_signals
;
1494 my_pstrcmp (const gchar
**a
, const gchar
**b
)
1496 return g_strcmp0 (*a
, *b
);
1500 om_check_interfaces_added (const gchar
*signal_name
,
1501 GVariant
*parameters
,
1502 const gchar
*object_path
,
1503 const gchar
*first_interface_name
,
1509 GPtrArray
*interfaces
;
1510 GPtrArray
*interfaces_in_message
;
1514 interfaces
= g_ptr_array_new ();
1515 g_ptr_array_add (interfaces
, (gpointer
) first_interface_name
);
1516 va_start (var_args
, first_interface_name
);
1519 str
= va_arg (var_args
, const gchar
*);
1522 g_ptr_array_add (interfaces
, (gpointer
) str
);
1527 g_variant_get (parameters
, "(&o*)", &path
, &array
);
1528 g_assert_cmpstr (signal_name
, ==, "InterfacesAdded");
1529 g_assert_cmpstr (path
, ==, object_path
);
1530 g_assert_cmpint (g_variant_n_children (array
), ==, interfaces
->len
);
1531 interfaces_in_message
= g_ptr_array_new ();
1532 for (n
= 0; n
< interfaces
->len
; n
++)
1534 const gchar
*iface_name
;
1535 g_variant_get_child (array
, n
, "{&sa{sv}}", &iface_name
, NULL
);
1536 g_ptr_array_add (interfaces_in_message
, (gpointer
) iface_name
);
1538 g_assert_cmpint (interfaces_in_message
->len
, ==, interfaces
->len
);
1539 g_ptr_array_sort (interfaces
, (GCompareFunc
) my_pstrcmp
);
1540 g_ptr_array_sort (interfaces_in_message
, (GCompareFunc
) my_pstrcmp
);
1541 for (n
= 0; n
< interfaces
->len
; n
++)
1542 g_assert_cmpstr (interfaces
->pdata
[n
], ==, interfaces_in_message
->pdata
[n
]);
1543 g_ptr_array_unref (interfaces_in_message
);
1544 g_ptr_array_unref (interfaces
);
1545 g_variant_unref (array
);
1549 om_check_interfaces_removed (const gchar
*signal_name
,
1550 GVariant
*parameters
,
1551 const gchar
*object_path
,
1552 const gchar
*first_interface_name
,
1558 GPtrArray
*interfaces
;
1559 GPtrArray
*interfaces_in_message
;
1563 interfaces
= g_ptr_array_new ();
1564 g_ptr_array_add (interfaces
, (gpointer
) first_interface_name
);
1565 va_start (var_args
, first_interface_name
);
1568 str
= va_arg (var_args
, const gchar
*);
1571 g_ptr_array_add (interfaces
, (gpointer
) str
);
1576 g_variant_get (parameters
, "(&o*)", &path
, &array
);
1577 g_assert_cmpstr (signal_name
, ==, "InterfacesRemoved");
1578 g_assert_cmpstr (path
, ==, object_path
);
1579 g_assert_cmpint (g_variant_n_children (array
), ==, interfaces
->len
);
1580 interfaces_in_message
= g_ptr_array_new ();
1581 for (n
= 0; n
< interfaces
->len
; n
++)
1583 const gchar
*iface_name
;
1584 g_variant_get_child (array
, n
, "&s", &iface_name
, NULL
);
1585 g_ptr_array_add (interfaces_in_message
, (gpointer
) iface_name
);
1587 g_assert_cmpint (interfaces_in_message
->len
, ==, interfaces
->len
);
1588 g_ptr_array_sort (interfaces
, (GCompareFunc
) my_pstrcmp
);
1589 g_ptr_array_sort (interfaces_in_message
, (GCompareFunc
) my_pstrcmp
);
1590 for (n
= 0; n
< interfaces
->len
; n
++)
1591 g_assert_cmpstr (interfaces
->pdata
[n
], ==, interfaces_in_message
->pdata
[n
]);
1592 g_ptr_array_unref (interfaces_in_message
);
1593 g_ptr_array_unref (interfaces
);
1594 g_variant_unref (array
);
1598 om_on_signal (GDBusConnection
*connection
,
1599 const gchar
*sender_name
,
1600 const gchar
*object_path
,
1601 const gchar
*interface_name
,
1602 const gchar
*signal_name
,
1603 GVariant
*parameters
,
1606 OMData
*om_data
= user_data
;
1608 //g_debug ("foo: %s", g_variant_print (parameters, TRUE));
1610 switch (om_data
->state
)
1614 g_printerr ("failing and om_data->state=%d on signal %s, params=%s\n",
1617 g_variant_print (parameters
, TRUE
));
1618 g_assert_not_reached ();
1622 om_check_interfaces_added (signal_name
, parameters
, "/managed/first",
1623 "org.project.Bar", NULL
);
1625 g_main_loop_quit (om_data
->loop
);
1629 om_check_interfaces_removed (signal_name
, parameters
, "/managed/first",
1630 "org.project.Bar", NULL
);
1632 /* keep running the loop */
1636 om_check_interfaces_added (signal_name
, parameters
, "/managed/first",
1637 "org.project.Bar", NULL
);
1639 g_main_loop_quit (om_data
->loop
);
1643 om_check_interfaces_removed (signal_name
, parameters
, "/managed/first",
1644 "org.project.Bar", NULL
);
1646 /* keep running the loop */
1650 om_check_interfaces_added (signal_name
, parameters
, "/managed/first",
1651 "org.project.Bar", NULL
);
1652 om_data
->state
= 10;
1653 g_main_loop_quit (om_data
->loop
);
1657 om_check_interfaces_added (signal_name
, parameters
, "/managed/first",
1658 "org.project.Bat", NULL
);
1659 om_data
->state
= 12;
1660 g_main_loop_quit (om_data
->loop
);
1664 om_check_interfaces_removed (signal_name
, parameters
, "/managed/first",
1665 "org.project.Bar", NULL
);
1666 om_data
->state
= 14;
1667 g_main_loop_quit (om_data
->loop
);
1671 om_check_interfaces_removed (signal_name
, parameters
, "/managed/first",
1672 "org.project.Bat", NULL
);
1673 om_data
->state
= 16;
1674 g_main_loop_quit (om_data
->loop
);
1678 om_check_interfaces_added (signal_name
, parameters
, "/managed/first",
1679 "com.acme.Coyote", NULL
);
1680 om_data
->state
= 18;
1681 g_main_loop_quit (om_data
->loop
);
1685 om_check_interfaces_added (signal_name
, parameters
, "/managed/second",
1686 "org.project.Bat", "org.project.Bar", NULL
);
1687 om_data
->state
= 102;
1688 g_main_loop_quit (om_data
->loop
);
1692 om_check_interfaces_removed (signal_name
, parameters
, "/managed/second",
1693 "org.project.Bat", "org.project.Bar", NULL
);
1694 om_data
->state
= 104;
1695 g_main_loop_quit (om_data
->loop
);
1699 om_check_interfaces_added (signal_name
, parameters
, "/managed/first_1",
1700 "com.acme.Coyote", NULL
);
1701 om_data
->state
= 201;
1702 g_main_loop_quit (om_data
->loop
);
1707 static GAsyncResult
*om_res
= NULL
;
1710 om_pm_start_cb (FooiGenObjectManagerClient
*manager
,
1714 GMainLoop
*loop
= user_data
;
1715 om_res
= g_object_ref (res
);
1716 g_main_loop_quit (loop
);
1720 on_interface_added (GDBusObject
*object
,
1721 GDBusInterface
*interface
,
1724 OMData
*om_data
= user_data
;
1725 om_data
->num_interface_added_signals
+= 1;
1729 on_interface_removed (GDBusObject
*object
,
1730 GDBusInterface
*interface
,
1733 OMData
*om_data
= user_data
;
1734 om_data
->num_interface_removed_signals
+= 1;
1738 on_object_proxy_added (GDBusObjectManagerClient
*manager
,
1739 GDBusObjectProxy
*object_proxy
,
1742 OMData
*om_data
= user_data
;
1743 om_data
->num_object_proxy_added_signals
+= 1;
1744 g_signal_connect (object_proxy
,
1746 G_CALLBACK (on_interface_added
),
1748 g_signal_connect (object_proxy
,
1749 "interface-removed",
1750 G_CALLBACK (on_interface_removed
),
1755 on_object_proxy_removed (GDBusObjectManagerClient
*manager
,
1756 GDBusObjectProxy
*object_proxy
,
1759 OMData
*om_data
= user_data
;
1760 om_data
->num_object_proxy_removed_signals
+= 1;
1761 g_assert_cmpint (g_signal_handlers_disconnect_by_func (object_proxy
,
1762 G_CALLBACK (on_interface_added
),
1764 g_assert_cmpint (g_signal_handlers_disconnect_by_func (object_proxy
,
1765 G_CALLBACK (on_interface_removed
),
1770 property_d_changed (GObject
*object
,
1774 gboolean
*changed
= user_data
;
1780 om_check_property_and_signal_emission (GMainLoop
*loop
,
1781 FooiGenBar
*skeleton
,
1784 gboolean d_changed
= FALSE
;
1787 /* First PropertiesChanged */
1788 g_assert_cmpint (foo_igen_bar_get_i (skeleton
), ==, 0);
1789 g_assert_cmpint (foo_igen_bar_get_i (proxy
), ==, 0);
1790 foo_igen_bar_set_i (skeleton
, 1);
1791 _g_assert_property_notify (proxy
, "i");
1792 g_assert_cmpint (foo_igen_bar_get_i (skeleton
), ==, 1);
1793 g_assert_cmpint (foo_igen_bar_get_i (proxy
), ==, 1);
1795 /* Double-check the gdouble case */
1796 g_assert_cmpfloat (foo_igen_bar_get_d (skeleton
), ==, 0.0);
1797 g_assert_cmpfloat (foo_igen_bar_get_d (proxy
), ==, 0.0);
1798 foo_igen_bar_set_d (skeleton
, 1.0);
1799 _g_assert_property_notify (proxy
, "d");
1801 /* Verify that re-setting it to the same value doesn't cause a
1802 * notify on the proxy, by taking advantage of the fact that
1803 * notifications are serialized.
1805 handler
= g_signal_connect (proxy
, "notify::d",
1806 G_CALLBACK (property_d_changed
), &d_changed
);
1807 foo_igen_bar_set_d (skeleton
, 1.0);
1808 foo_igen_bar_set_i (skeleton
, 2);
1809 _g_assert_property_notify (proxy
, "i");
1810 g_assert (d_changed
== FALSE
);
1811 g_signal_handler_disconnect (proxy
, handler
);
1813 /* Then just a regular signal */
1814 foo_igen_bar_emit_another_signal (skeleton
, "word");
1815 _g_assert_signal_received (proxy
, "another-signal");
1819 check_object_manager (void)
1821 FooiGenObjectSkeleton
*o
= NULL
;
1822 FooiGenObjectSkeleton
*o2
= NULL
;
1823 FooiGenObjectSkeleton
*o3
= NULL
;
1824 GDBusInterfaceSkeleton
*i
;
1826 GDBusObjectManagerServer
*manager
= NULL
;
1827 GDBusNodeInfo
*info
;
1830 OMData
*om_data
= NULL
;
1831 guint om_signal_id
= -1;
1832 GDBusObjectManager
*pm
= NULL
;
1833 GList
*object_proxies
;
1837 FooiGenBar
*bar_skeleton
;
1838 GDBusInterface
*iface
;
1839 gchar
*path
, *name
, *name_owner
;
1840 GDBusConnection
*c2
;
1841 GDBusObjectManagerClientFlags flags
;
1843 loop
= g_main_loop_new (NULL
, FALSE
);
1845 om_data
= g_new0 (OMData
, 1);
1846 om_data
->loop
= loop
;
1850 c
= g_bus_get_sync (G_BUS_TYPE_SESSION
, NULL
, &error
);
1851 g_assert_no_error (error
);
1852 g_assert (c
!= NULL
);
1854 om_signal_id
= g_dbus_connection_signal_subscribe (c
,
1856 "org.freedesktop.DBus.ObjectManager",
1858 NULL
, /* object_path */
1860 G_DBUS_SIGNAL_FLAGS_NONE
,
1863 NULL
); /* user_data_free_func */
1865 /* Our GDBusObjectManagerClient tests are simple - we basically just count the
1866 * number of times the various signals have been emitted (we don't check
1867 * that the right objects/interfaces are passed though - that's checked
1868 * in the lower-level tests in om_on_signal()...)
1870 * Note that these tests rely on the D-Bus signal handlers used by
1871 * GDBusObjectManagerClient firing before om_on_signal().
1874 pm
= foo_igen_object_manager_client_new_sync (c
,
1875 G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE
,
1876 g_dbus_connection_get_unique_name (c
),
1878 NULL
, /* GCancellable */
1880 g_assert_error (error
, G_DBUS_ERROR
, G_DBUS_ERROR_UNKNOWN_METHOD
);
1881 g_error_free (error
);
1882 g_assert (pm
== NULL
);
1884 manager
= g_dbus_object_manager_server_new ("/managed");
1886 g_assert (g_dbus_object_manager_server_get_connection (manager
) == NULL
);
1888 g_dbus_object_manager_server_set_connection (manager
, c
);
1890 g_assert_cmpstr (g_dbus_object_manager_get_object_path (G_DBUS_OBJECT_MANAGER (manager
)), ==, "/managed");
1891 g_object_get (manager
, "object-path", &path
, "connection", &c2
, NULL
);
1892 g_assert_cmpstr (path
, ==, "/managed");
1895 g_clear_object (&c2
);
1897 /* Check that the manager object is visible */
1898 info
= introspect (c
, g_dbus_connection_get_unique_name (c
), "/managed", loop
);
1899 g_assert_cmpint (count_interfaces (info
), ==, 4); /* ObjectManager + Properties,Introspectable,Peer */
1900 g_assert (has_interface (info
, "org.freedesktop.DBus.ObjectManager"));
1901 g_assert_cmpint (count_nodes (info
), ==, 0);
1902 g_dbus_node_info_unref (info
);
1904 /* Check GetManagedObjects() - should be empty since we have no objects */
1905 om_check_get_all (c
, loop
,
1906 "(@a{oa{sa{sv}}} {},)");
1908 /* Now try to create the proxy manager again - this time it should work */
1910 foo_igen_object_manager_client_new (c
,
1911 G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE
,
1912 g_dbus_connection_get_unique_name (c
),
1914 NULL
, /* GCancellable */
1915 (GAsyncReadyCallback
) om_pm_start_cb
,
1917 g_main_loop_run (loop
);
1919 pm
= foo_igen_object_manager_client_new_finish (om_res
, &error
);
1920 g_clear_object (&om_res
);
1921 g_assert_no_error (error
);
1922 g_assert (pm
!= NULL
);
1923 g_signal_connect (pm
,
1925 G_CALLBACK (on_object_proxy_added
),
1927 g_signal_connect (pm
,
1929 G_CALLBACK (on_object_proxy_removed
),
1932 g_assert_cmpstr (g_dbus_object_manager_get_object_path (G_DBUS_OBJECT_MANAGER (pm
)), ==, "/managed");
1934 "object-path", &path
,
1937 "name-owner", &name_owner
,
1940 g_assert_cmpstr (path
, ==, "/managed");
1941 g_assert_cmpstr (name
, ==, g_dbus_connection_get_unique_name (c
));
1942 g_assert_cmpstr (name_owner
, ==, g_dbus_connection_get_unique_name (c
));
1943 g_assert_cmpint (flags
, ==, G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE
);
1946 g_clear_object (&c2
);
1948 g_free (name_owner
);
1950 /* ... check there are no object proxies yet */
1951 object_proxies
= g_dbus_object_manager_get_objects (pm
);
1952 g_assert (object_proxies
== NULL
);
1954 /* First, export an object with a single interface (also check that
1955 * g_dbus_interface_get_object() works and that the object isn't reffed)
1957 o
= foo_igen_object_skeleton_new ("/managed/first");
1958 i
= G_DBUS_INTERFACE_SKELETON (foo_igen_bar_skeleton_new ());
1959 g_assert (g_dbus_interface_get_object (G_DBUS_INTERFACE (i
)) == NULL
);
1960 g_assert_cmpint (G_OBJECT (o
)->ref_count
, ==, 1);
1961 foo_igen_object_skeleton_set_bar (o
, FOO_IGEN_BAR (i
));
1962 g_assert_cmpint (G_OBJECT (o
)->ref_count
, ==, 1);
1963 g_assert (g_dbus_interface_get_object (G_DBUS_INTERFACE (i
)) == G_DBUS_OBJECT (o
));
1964 g_assert_cmpint (G_OBJECT (o
)->ref_count
, ==, 1);
1965 foo_igen_object_skeleton_set_bar (o
, NULL
);
1966 g_assert (g_dbus_interface_get_object (G_DBUS_INTERFACE (i
)) == NULL
);
1967 g_assert_cmpint (G_OBJECT (o
)->ref_count
, ==, 1);
1968 foo_igen_object_skeleton_set_bar (o
, FOO_IGEN_BAR (i
));
1969 g_assert (g_dbus_interface_get_object (G_DBUS_INTERFACE (i
)) == G_DBUS_OBJECT (o
));
1970 g_assert_cmpint (G_OBJECT (o
)->ref_count
, ==, 1);
1972 o2
= FOO_IGEN_OBJECT_SKELETON (g_dbus_interface_dup_object (G_DBUS_INTERFACE (i
)));
1973 g_assert (G_DBUS_OBJECT (o2
) == G_DBUS_OBJECT (o
));
1974 g_assert_cmpint (G_OBJECT (o2
)->ref_count
, ==, 2);
1975 g_clear_object (&o2
);
1977 g_dbus_object_manager_server_export (manager
, G_DBUS_OBJECT_SKELETON (o
));
1979 /* ... check we get the InterfacesAdded signal */
1982 g_main_loop_run (om_data
->loop
);
1984 g_assert_cmpint (om_data
->state
, ==, 2);
1985 g_assert_cmpint (om_data
->num_object_proxy_added_signals
, ==, 1);
1986 g_assert_cmpint (om_data
->num_object_proxy_removed_signals
, ==, 0);
1987 g_assert_cmpint (om_data
->num_interface_added_signals
, ==, 0);
1988 g_assert_cmpint (om_data
->num_interface_removed_signals
, ==, 0);
1989 /* ... check there's one non-standard interfaces */
1990 info
= introspect (c
, g_dbus_connection_get_unique_name (c
), "/managed/first", loop
);
1991 g_assert_cmpint (count_interfaces (info
), ==, 4); /* Bar + Properties,Introspectable,Peer */
1992 g_assert (has_interface (info
, "org.project.Bar"));
1993 g_dbus_node_info_unref (info
);
1995 /* Also check g_dbus_object_manager_get_interface */
1996 iface
= g_dbus_object_manager_get_interface (G_DBUS_OBJECT_MANAGER (manager
), "/managed/first", "org.project.Bar");
1997 g_assert (iface
!= NULL
);
1998 g_clear_object (&iface
);
1999 iface
= g_dbus_object_manager_get_interface (G_DBUS_OBJECT_MANAGER (manager
), "/managed/first", "org.project.Bat");
2000 g_assert (iface
== NULL
);
2001 iface
= g_dbus_object_manager_get_interface (G_DBUS_OBJECT_MANAGER (pm
), "/managed/first", "org.project.Bar");
2002 g_assert (iface
!= NULL
);
2003 g_clear_object (&iface
);
2004 iface
= g_dbus_object_manager_get_interface (G_DBUS_OBJECT_MANAGER (pm
), "/managed/first", "org.project.Bat");
2005 g_assert (iface
== NULL
);
2007 /* Now, check adding the same interface replaces the existing one */
2008 foo_igen_object_skeleton_set_bar (o
, FOO_IGEN_BAR (i
));
2009 /* ... check we get the InterfacesRemoved */
2011 g_main_loop_run (om_data
->loop
);
2012 /* ... and then check we get the InterfacesAdded */
2013 g_assert_cmpint (om_data
->state
, ==, 6);
2014 g_assert_cmpint (om_data
->num_object_proxy_added_signals
, ==, 2);
2015 g_assert_cmpint (om_data
->num_object_proxy_removed_signals
, ==, 1);
2016 g_assert_cmpint (om_data
->num_interface_added_signals
, ==, 0);
2017 g_assert_cmpint (om_data
->num_interface_removed_signals
, ==, 0);
2018 /* ... check introspection data */
2019 info
= introspect (c
, g_dbus_connection_get_unique_name (c
), "/managed/first", loop
);
2020 g_assert_cmpint (count_interfaces (info
), ==, 4); /* Bar + Properties,Introspectable,Peer */
2021 g_assert (has_interface (info
, "org.project.Bar"));
2022 g_dbus_node_info_unref (info
);
2023 g_clear_object (&i
);
2025 /* check adding an interface of same type (but not same object) replaces the existing one */
2026 i
= G_DBUS_INTERFACE_SKELETON (foo_igen_bar_skeleton_new ());
2027 foo_igen_object_skeleton_set_bar (o
, FOO_IGEN_BAR (i
));
2028 /* ... check we get the InterfacesRemoved and then InterfacesAdded */
2030 g_main_loop_run (om_data
->loop
);
2031 g_assert_cmpint (om_data
->state
, ==, 10);
2032 g_assert_cmpint (om_data
->num_object_proxy_added_signals
, ==, 3);
2033 g_assert_cmpint (om_data
->num_object_proxy_removed_signals
, ==, 2);
2034 g_assert_cmpint (om_data
->num_interface_added_signals
, ==, 0);
2035 g_assert_cmpint (om_data
->num_interface_removed_signals
, ==, 0);
2036 /* ... check introspection data */
2037 info
= introspect (c
, g_dbus_connection_get_unique_name (c
), "/managed/first", loop
);
2038 g_assert_cmpint (count_interfaces (info
), ==, 4); /* Bar + Properties,Introspectable,Peer */
2039 g_assert (has_interface (info
, "org.project.Bar"));
2040 g_dbus_node_info_unref (info
);
2041 g_clear_object (&i
);
2043 /* check adding an interface of another type doesn't replace the existing one */
2044 i
= G_DBUS_INTERFACE_SKELETON (foo_igen_bat_skeleton_new ());
2045 foo_igen_object_skeleton_set_bat (o
, FOO_IGEN_BAT (i
));
2046 g_clear_object (&i
);
2047 /* ... check we get the InterfacesAdded */
2048 om_data
->state
= 11;
2049 g_main_loop_run (om_data
->loop
);
2050 g_assert_cmpint (om_data
->state
, ==, 12);
2051 g_assert_cmpint (om_data
->num_object_proxy_added_signals
, ==, 3);
2052 g_assert_cmpint (om_data
->num_object_proxy_removed_signals
, ==, 2);
2053 g_assert_cmpint (om_data
->num_interface_added_signals
, ==, 1);
2054 g_assert_cmpint (om_data
->num_interface_removed_signals
, ==, 0);
2055 /* ... check introspection data */
2056 info
= introspect (c
, g_dbus_connection_get_unique_name (c
), "/managed/first", loop
);
2057 g_assert_cmpint (count_interfaces (info
), ==, 5); /* Bar,Bat + Properties,Introspectable,Peer */
2058 g_assert (has_interface (info
, "org.project.Bar"));
2059 g_assert (has_interface (info
, "org.project.Bat"));
2060 g_dbus_node_info_unref (info
);
2062 /* check we can remove an interface */
2063 foo_igen_object_skeleton_set_bar (o
, NULL
);
2064 /* ... check we get the InterfacesRemoved */
2065 om_data
->state
= 13;
2066 g_main_loop_run (om_data
->loop
);
2067 g_assert_cmpint (om_data
->state
, ==, 14);
2068 g_assert_cmpint (om_data
->num_object_proxy_added_signals
, ==, 3);
2069 g_assert_cmpint (om_data
->num_object_proxy_removed_signals
, ==, 2);
2070 g_assert_cmpint (om_data
->num_interface_added_signals
, ==, 1);
2071 g_assert_cmpint (om_data
->num_interface_removed_signals
, ==, 1);
2072 /* ... check introspection data */
2073 info
= introspect (c
, g_dbus_connection_get_unique_name (c
), "/managed/first", loop
);
2074 g_assert_cmpint (count_interfaces (info
), ==, 4); /* Bat + Properties,Introspectable,Peer */
2075 g_assert (has_interface (info
, "org.project.Bat"));
2076 g_dbus_node_info_unref (info
);
2077 /* also and that the call only has effect if the interface actually exists
2079 * (Note: if a signal was emitted we'd assert in the signal handler
2080 * because we're in state 14)
2082 foo_igen_object_skeleton_set_bar (o
, NULL
);
2083 /* ... check introspection data */
2084 info
= introspect (c
, g_dbus_connection_get_unique_name (c
), "/managed/first", loop
);
2085 g_assert_cmpint (count_interfaces (info
), ==, 4); /* Bat + Properties,Introspectable,Peer */
2086 g_assert (has_interface (info
, "org.project.Bat"));
2087 g_dbus_node_info_unref (info
);
2089 /* remove the last interface */
2090 foo_igen_object_skeleton_set_bat (o
, NULL
);
2091 /* ... check we get the InterfacesRemoved */
2092 om_data
->state
= 15;
2093 g_main_loop_run (om_data
->loop
);
2094 g_assert_cmpint (om_data
->state
, ==, 16);
2095 g_assert_cmpint (om_data
->num_object_proxy_added_signals
, ==, 3);
2096 g_assert_cmpint (om_data
->num_object_proxy_removed_signals
, ==, 3);
2097 g_assert_cmpint (om_data
->num_interface_added_signals
, ==, 1);
2098 g_assert_cmpint (om_data
->num_interface_removed_signals
, ==, 1);
2099 /* ... check introspection data */
2100 info
= introspect (c
, g_dbus_connection_get_unique_name (c
), "/managed/first", loop
);
2101 g_assert_cmpint (count_interfaces (info
), ==, 0); /* nothing */
2102 g_dbus_node_info_unref (info
);
2104 /* and add an interface again */
2105 i
= G_DBUS_INTERFACE_SKELETON (foo_igen_com_acme_coyote_skeleton_new ());
2106 foo_igen_object_skeleton_set_com_acme_coyote (o
, FOO_IGEN_COM_ACME_COYOTE (i
));
2107 g_clear_object (&i
);
2108 /* ... check we get the InterfacesAdded */
2109 om_data
->state
= 17;
2110 g_main_loop_run (om_data
->loop
);
2111 g_assert_cmpint (om_data
->state
, ==, 18);
2112 g_assert_cmpint (om_data
->num_object_proxy_added_signals
, ==, 4);
2113 g_assert_cmpint (om_data
->num_object_proxy_removed_signals
, ==, 3);
2114 g_assert_cmpint (om_data
->num_interface_added_signals
, ==, 1);
2115 g_assert_cmpint (om_data
->num_interface_removed_signals
, ==, 1);
2116 /* ... check introspection data */
2117 info
= introspect (c
, g_dbus_connection_get_unique_name (c
), "/managed/first", loop
);
2118 g_assert_cmpint (count_interfaces (info
), ==, 4); /* com.acme.Coyote + Properties,Introspectable,Peer */
2119 g_assert (has_interface (info
, "com.acme.Coyote"));
2120 g_dbus_node_info_unref (info
);
2122 /* Check GetManagedObjects() - should be just the Coyote */
2123 om_check_get_all (c
, loop
,
2124 "({objectpath '/managed/first': {'com.acme.Coyote': {'Mood': <''>}}},)");
2126 /* -------------------------------------------------- */
2128 /* create a new object with two interfaces */
2129 o2
= foo_igen_object_skeleton_new ("/managed/second");
2130 i
= G_DBUS_INTERFACE_SKELETON (foo_igen_bar_skeleton_new ());
2131 bar_skeleton
= FOO_IGEN_BAR (i
); /* save for later test */
2132 foo_igen_object_skeleton_set_bar (o2
, FOO_IGEN_BAR (i
));
2133 g_clear_object (&i
);
2134 i
= G_DBUS_INTERFACE_SKELETON (foo_igen_bat_skeleton_new ());
2135 foo_igen_object_skeleton_set_bat (o2
, FOO_IGEN_BAT (i
));
2136 g_clear_object (&i
);
2138 g_dbus_object_manager_server_export (manager
, G_DBUS_OBJECT_SKELETON (o2
));
2139 /* ... check we get the InterfacesAdded with _two_ interfaces */
2140 om_data
->state
= 101;
2141 g_main_loop_run (om_data
->loop
);
2142 g_assert_cmpint (om_data
->state
, ==, 102);
2143 g_assert_cmpint (om_data
->num_object_proxy_added_signals
, ==, 5);
2144 g_assert_cmpint (om_data
->num_object_proxy_removed_signals
, ==, 3);
2145 g_assert_cmpint (om_data
->num_interface_added_signals
, ==, 1);
2146 g_assert_cmpint (om_data
->num_interface_removed_signals
, ==, 1);
2148 /* -------------------------------------------------- */
2150 /* Now that we have a couple of objects with interfaces, check
2151 * that ObjectManager.GetManagedObjects() works
2153 om_check_get_all (c
, loop
,
2154 "({objectpath '/managed/first': {'com.acme.Coyote': {'Mood': <''>}}, '/managed/second': {'org.project.Bar': {'y': <byte 0x00>, 'b': <false>, 'n': <int16 0>, 'q': <uint16 0>, 'i': <0>, 'u': <uint32 0>, 'x': <int64 0>, 't': <uint64 0>, 'd': <0.0>, 's': <''>, 'o': <objectpath '/'>, 'g': <signature ''>, 'ay': <b''>, 'as': <@as []>, 'aay': <@aay []>, 'ao': <@ao []>, 'ag': <@ag []>, 'FinallyNormalName': <''>, 'ReadonlyProperty': <''>, 'unset_i': <0>, 'unset_d': <0.0>, 'unset_s': <''>, 'unset_o': <objectpath '/'>, 'unset_g': <signature ''>, 'unset_ay': <b''>, 'unset_as': <@as []>, 'unset_ao': <@ao []>, 'unset_ag': <@ag []>, 'unset_struct': <(0, 0.0, '', objectpath '/', signature '', @ay [], @as [], @ao [], @ag [])>}, 'org.project.Bat': {'force_i': <0>, 'force_s': <''>, 'force_ay': <@ay []>, 'force_struct': <(0,)>}}},)");
2156 /* Set connection to NULL, causing everything to be unexported.. verify this.. and
2157 * then set the connection back.. and then check things still work
2159 g_dbus_object_manager_server_set_connection (manager
, NULL
);
2160 info
= introspect (c
, g_dbus_connection_get_unique_name (c
), "/managed", loop
);
2161 g_assert_cmpint (count_interfaces (info
), ==, 0); /* nothing */
2162 g_dbus_node_info_unref (info
);
2164 g_dbus_object_manager_server_set_connection (manager
, c
);
2165 om_check_get_all (c
, loop
,
2166 "({objectpath '/managed/first': {'com.acme.Coyote': {'Mood': <''>}}, '/managed/second': {'org.project.Bar': {'y': <byte 0x00>, 'b': <false>, 'n': <int16 0>, 'q': <uint16 0>, 'i': <0>, 'u': <uint32 0>, 'x': <int64 0>, 't': <uint64 0>, 'd': <0.0>, 's': <''>, 'o': <objectpath '/'>, 'g': <signature ''>, 'ay': <b''>, 'as': <@as []>, 'aay': <@aay []>, 'ao': <@ao []>, 'ag': <@ag []>, 'FinallyNormalName': <''>, 'ReadonlyProperty': <''>, 'unset_i': <0>, 'unset_d': <0.0>, 'unset_s': <''>, 'unset_o': <objectpath '/'>, 'unset_g': <signature ''>, 'unset_ay': <b''>, 'unset_as': <@as []>, 'unset_ao': <@ao []>, 'unset_ag': <@ag []>, 'unset_struct': <(0, 0.0, '', objectpath '/', signature '', @ay [], @as [], @ao [], @ag [])>}, 'org.project.Bat': {'force_i': <0>, 'force_s': <''>, 'force_ay': <@ay []>, 'force_struct': <(0,)>}}},)");
2168 /* Also check that the ObjectManagerClient returns these objects - and
2169 * that they are of the right GType cf. what was requested via
2170 * the generated ::get-proxy-type signal handler
2172 object_proxies
= g_dbus_object_manager_get_objects (pm
);
2173 g_assert (g_list_length (object_proxies
) == 2);
2174 g_list_free_full (object_proxies
, g_object_unref
);
2175 op
= g_dbus_object_manager_get_object (pm
, "/managed/first");
2176 g_assert (op
!= NULL
);
2177 g_assert (FOO_IGEN_IS_OBJECT_PROXY (op
));
2178 g_assert_cmpstr (g_dbus_object_get_object_path (op
), ==, "/managed/first");
2179 proxies
= g_dbus_object_get_interfaces (op
);
2180 g_assert (g_list_length (proxies
) == 1);
2181 g_list_free_full (proxies
, g_object_unref
);
2182 p
= G_DBUS_PROXY (foo_igen_object_get_com_acme_coyote (FOO_IGEN_OBJECT (op
)));
2183 g_assert (p
!= NULL
);
2184 g_assert_cmpint (G_TYPE_FROM_INSTANCE (p
), ==, FOO_IGEN_TYPE_COM_ACME_COYOTE_PROXY
);
2185 g_assert (g_type_is_a (G_TYPE_FROM_INSTANCE (p
), FOO_IGEN_TYPE_COM_ACME_COYOTE
));
2186 g_clear_object (&p
);
2187 p
= (GDBusProxy
*) g_dbus_object_get_interface (op
, "org.project.NonExisting");
2188 g_assert (p
== NULL
);
2189 g_clear_object (&op
);
2192 op
= g_dbus_object_manager_get_object (pm
, "/managed/second");
2193 g_assert (op
!= NULL
);
2194 g_assert (FOO_IGEN_IS_OBJECT_PROXY (op
));
2195 g_assert_cmpstr (g_dbus_object_get_object_path (op
), ==, "/managed/second");
2196 proxies
= g_dbus_object_get_interfaces (op
);
2197 g_assert (g_list_length (proxies
) == 2);
2198 g_list_free_full (proxies
, g_object_unref
);
2199 p
= G_DBUS_PROXY (foo_igen_object_get_bat (FOO_IGEN_OBJECT (op
)));
2200 g_assert (p
!= NULL
);
2201 g_assert_cmpint (G_TYPE_FROM_INSTANCE (p
), ==, FOO_IGEN_TYPE_BAT_PROXY
);
2202 g_assert (g_type_is_a (G_TYPE_FROM_INSTANCE (p
), FOO_IGEN_TYPE_BAT
));
2203 g_clear_object (&p
);
2204 p
= G_DBUS_PROXY (foo_igen_object_get_bar (FOO_IGEN_OBJECT (op
)));
2205 g_assert (p
!= NULL
);
2206 g_assert_cmpint (G_TYPE_FROM_INSTANCE (p
), ==, FOO_IGEN_TYPE_BAR_PROXY
);
2207 g_assert (g_type_is_a (G_TYPE_FROM_INSTANCE (p
), FOO_IGEN_TYPE_BAR
));
2208 /* ... now that we have a Bar instance around, also check that we get signals
2209 * and property changes...
2211 om_check_property_and_signal_emission (loop
, bar_skeleton
, FOO_IGEN_BAR (p
));
2212 g_clear_object (&p
);
2213 p
= (GDBusProxy
*) g_dbus_object_get_interface (op
, "org.project.NonExisting");
2214 g_assert (p
== NULL
);
2215 g_clear_object (&op
);
2217 /* -------------------------------------------------- */
2219 /* Now remove the second object added above */
2220 g_dbus_object_manager_server_unexport (manager
, "/managed/second");
2221 /* ... check we get InterfacesRemoved with both interfaces */
2222 om_data
->state
= 103;
2223 g_main_loop_run (om_data
->loop
);
2224 g_assert_cmpint (om_data
->state
, ==, 104);
2225 g_assert_cmpint (om_data
->num_object_proxy_added_signals
, ==, 5);
2226 g_assert_cmpint (om_data
->num_object_proxy_removed_signals
, ==, 4);
2227 g_assert_cmpint (om_data
->num_interface_added_signals
, ==, 1);
2228 g_assert_cmpint (om_data
->num_interface_removed_signals
, ==, 1);
2229 /* ... check introspection data (there should be nothing) */
2230 info
= introspect (c
, g_dbus_connection_get_unique_name (c
), "/managed/second", loop
);
2231 g_assert_cmpint (count_nodes (info
), ==, 0);
2232 g_assert_cmpint (count_interfaces (info
), ==, 0);
2233 g_dbus_node_info_unref (info
);
2235 /* Check GetManagedObjects() again */
2236 om_check_get_all (c
, loop
,
2237 "({objectpath '/managed/first': {'com.acme.Coyote': {'Mood': <''>}}},)");
2238 /* -------------------------------------------------- */
2240 /* Check that export_uniquely() works */
2242 o3
= foo_igen_object_skeleton_new ("/managed/first");
2243 i
= G_DBUS_INTERFACE_SKELETON (foo_igen_com_acme_coyote_skeleton_new ());
2244 foo_igen_com_acme_coyote_set_mood (FOO_IGEN_COM_ACME_COYOTE (i
), "indifferent");
2245 foo_igen_object_skeleton_set_com_acme_coyote (o3
, FOO_IGEN_COM_ACME_COYOTE (i
));
2246 g_clear_object (&i
);
2247 g_dbus_object_manager_server_export_uniquely (manager
, G_DBUS_OBJECT_SKELETON (o3
));
2248 /* ... check we get the InterfacesAdded signal */
2249 om_data
->state
= 200;
2250 g_main_loop_run (om_data
->loop
);
2251 g_assert_cmpint (om_data
->state
, ==, 201);
2253 om_check_get_all (c
, loop
,
2254 "({objectpath '/managed/first': {'com.acme.Coyote': {'Mood': <''>}}, '/managed/first_1': {'com.acme.Coyote': {'Mood': <'indifferent'>}}},)");
2256 //g_main_loop_run (loop); /* TODO: tmp */
2258 /* Clean up objects */
2259 g_assert (g_dbus_object_manager_server_unexport (manager
, "/managed/first_1"));
2260 //g_assert (g_dbus_object_manager_server_unexport (manager, "/managed/second"));
2261 g_assert (g_dbus_object_manager_server_unexport (manager
, "/managed/first"));
2262 g_assert_cmpint (g_list_length (g_dbus_object_manager_get_objects (G_DBUS_OBJECT_MANAGER (manager
))), ==, 0);
2265 g_main_loop_unref (loop
);
2267 if (om_signal_id
!= -1)
2268 g_dbus_connection_signal_unsubscribe (c
, om_signal_id
);
2269 g_clear_object (&o3
);
2270 g_clear_object (&o2
);
2271 g_clear_object (&o
);
2272 g_clear_object (&manager
);
2275 g_assert_cmpint (g_signal_handlers_disconnect_by_func (pm
,
2276 G_CALLBACK (on_object_proxy_added
),
2278 g_assert_cmpint (g_signal_handlers_disconnect_by_func (pm
,
2279 G_CALLBACK (on_object_proxy_removed
),
2281 g_clear_object (&pm
);
2283 g_clear_object (&c
);
2288 /* ---------------------------------------------------------------------------------------------------- */
2291 test_object_manager (void)
2296 loop
= g_main_loop_new (NULL
, FALSE
);
2298 id
= g_bus_own_name (G_BUS_TYPE_SESSION
,
2299 "org.gtk.GDBus.BindingsTool.Test",
2300 G_BUS_NAME_OWNER_FLAGS_NONE
,
2307 g_main_loop_run (loop
);
2309 check_object_manager ();
2311 /* uncomment to keep the service around (to e.g. introspect it) */
2312 /* g_main_loop_run (loop); */
2314 unexport_objects ();
2316 g_bus_unown_name (id
);
2317 g_main_loop_unref (loop
);
2320 /* ---------------------------------------------------------------------------------------------------- */
2321 /* This checks that forcing names via org.gtk.GDBus.Name works (see test-codegen.xml) */
2323 extern gpointer name_forcing_1
;
2324 extern gpointer name_forcing_2
;
2325 extern gpointer name_forcing_3
;
2326 extern gpointer name_forcing_4
;
2327 extern gpointer name_forcing_5
;
2328 extern gpointer name_forcing_6
;
2329 extern gpointer name_forcing_7
;
2330 gpointer name_forcing_1
= foo_igen_rocket123_get_type
;
2331 gpointer name_forcing_2
= foo_igen_rocket123_call_ignite_xyz
;
2332 gpointer name_forcing_3
= foo_igen_rocket123_emit_exploded_xyz
;
2333 gpointer name_forcing_4
= foo_igen_rocket123_get_speed_xyz
;
2334 gpointer name_forcing_5
= foo_igen_test_ugly_case_interface_call_get_iscsi_servers
;
2335 gpointer name_forcing_6
= foo_igen_test_ugly_case_interface_emit_servers_updated_now
;
2336 gpointer name_forcing_7
= foo_igen_test_ugly_case_interface_get_ugly_name
;
2338 /* ---------------------------------------------------------------------------------------------------- */
2340 /* See https://bugzilla.gnome.org/show_bug.cgi?id=647577#c5 for details */
2342 #define CHECK_FIELD(name, v1, v2) g_assert_cmpint (G_STRUCT_OFFSET (FooiGenChangingInterface##v1##Iface, name), ==, G_STRUCT_OFFSET (FooiGenChangingInterface##v2##Iface, name));
2345 test_interface_stability (void)
2347 CHECK_FIELD(handle_foo_method
, V1
, V2
);
2348 CHECK_FIELD(handle_bar_method
, V1
, V2
);
2349 CHECK_FIELD(handle_baz_method
, V1
, V2
);
2350 CHECK_FIELD(foo_signal
, V1
, V2
);
2351 CHECK_FIELD(bar_signal
, V1
, V2
);
2352 CHECK_FIELD(baz_signal
, V1
, V2
);
2353 CHECK_FIELD(handle_new_method_in2
, V2
, V10
);
2354 CHECK_FIELD(new_signal_in2
, V2
, V10
);
2359 /* ---------------------------------------------------------------------------------------------------- */
2363 * - check that a property with name "Type" is mapped into g-name "type"
2364 * with C accessors get_type_ (to avoid clashing with the GType accessor)
2365 * and set_type_ (for symmetri)
2366 * (see https://bugzilla.gnome.org/show_bug.cgi?id=679473 for details)
2368 * - (could add more tests here)
2372 test_property_naming (void)
2374 gpointer c_getter_name
= foo_igen_naming_get_type_
;
2375 gpointer c_setter_name
= foo_igen_naming_set_type_
;
2376 FooiGenNaming
*skel
;
2378 (void) c_getter_name
;
2379 (void) c_setter_name
;
2381 skel
= foo_igen_naming_skeleton_new ();
2382 g_assert (g_object_class_find_property (G_OBJECT_GET_CLASS (skel
), "type") != NULL
);
2383 g_object_unref (skel
);
2386 /* ---------------------------------------------------------------------------------------------------- */
2392 g_test_init (&argc
, &argv
, NULL
);
2394 g_test_add_func ("/gdbus/codegen/annotations", test_annotations
);
2395 g_test_add_func ("/gdbus/codegen/interface_stability", test_interface_stability
);
2396 g_test_add_func ("/gdbus/codegen/object-manager", test_object_manager
);
2397 g_test_add_func ("/gdbus/codegen/property-naming", test_property_naming
);
2399 return session_bus_run ();