Merge branch '976-disable-assert-checks' into 'master'
[glib.git] / gio / tests / gdbus-proxy.c
blob8a2c324a2cdaa8762c6d2d16b537814436548604
1 /* GLib testing framework examples and tests
3 * Copyright (C) 2008-2010 Red Hat, Inc.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General
16 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 * Author: David Zeuthen <davidz@redhat.com>
21 #include <gio/gio.h>
22 #include <unistd.h>
23 #include <string.h>
25 #include "gdbus-tests.h"
27 /* all tests rely on a shared mainloop */
28 static GMainLoop *loop = NULL;
30 /* ---------------------------------------------------------------------------------------------------- */
31 /* Test that the method aspects of GDBusProxy works */
32 /* ---------------------------------------------------------------------------------------------------- */
34 static void
35 test_methods (GDBusProxy *proxy)
37 GVariant *result;
38 GError *error;
39 const gchar *str;
40 gchar *dbus_error_name;
42 /* check that we can invoke a method */
43 error = NULL;
44 result = g_dbus_proxy_call_sync (proxy,
45 "HelloWorld",
46 g_variant_new ("(s)", "Hey"),
47 G_DBUS_CALL_FLAGS_NONE,
48 -1,
49 NULL,
50 &error);
51 g_assert_no_error (error);
52 g_assert (result != NULL);
53 g_assert_cmpstr (g_variant_get_type_string (result), ==, "(s)");
54 g_variant_get (result, "(&s)", &str);
55 g_assert_cmpstr (str, ==, "You greeted me with 'Hey'. Thanks!");
56 g_variant_unref (result);
58 /* Check that we can completely recover the returned error */
59 result = g_dbus_proxy_call_sync (proxy,
60 "HelloWorld",
61 g_variant_new ("(s)", "Yo"),
62 G_DBUS_CALL_FLAGS_NONE,
63 -1,
64 NULL,
65 &error);
66 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_DBUS_ERROR);
67 g_assert (g_dbus_error_is_remote_error (error));
68 g_assert (g_dbus_error_is_remote_error (error));
69 g_assert (result == NULL);
70 dbus_error_name = g_dbus_error_get_remote_error (error);
71 g_assert_cmpstr (dbus_error_name, ==, "com.example.TestException");
72 g_free (dbus_error_name);
73 g_assert (g_dbus_error_strip_remote_error (error));
74 g_assert_cmpstr (error->message, ==, "Yo is not a proper greeting");
75 g_clear_error (&error);
77 /* Check that we get a timeout if the method handling is taking longer than
78 * timeout. We use such a long sleep because on slow machines, if the
79 * sleep isn't much longer than the timeout and we're doing a parallel
80 * build, there's no guarantee we'll be scheduled in the window between
81 * the timeout being hit and the sleep finishing. */
82 error = NULL;
83 result = g_dbus_proxy_call_sync (proxy,
84 "Sleep",
85 g_variant_new ("(i)", 10000 /* msec */),
86 G_DBUS_CALL_FLAGS_NONE,
87 100 /* msec */,
88 NULL,
89 &error);
90 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_TIMED_OUT);
91 g_assert (!g_dbus_error_is_remote_error (error));
92 g_assert (result == NULL);
93 g_clear_error (&error);
95 /* Check that proxy-default timeouts work. */
96 g_assert_cmpint (g_dbus_proxy_get_default_timeout (proxy), ==, -1);
98 /* the default timeout is 25000 msec so this should work */
99 result = g_dbus_proxy_call_sync (proxy,
100 "Sleep",
101 g_variant_new ("(i)", 500 /* msec */),
102 G_DBUS_CALL_FLAGS_NONE,
103 -1, /* use proxy default (e.g. -1 -> e.g. 25000 msec) */
104 NULL,
105 &error);
106 g_assert_no_error (error);
107 g_assert (result != NULL);
108 g_assert_cmpstr (g_variant_get_type_string (result), ==, "()");
109 g_variant_unref (result);
111 /* Now set the proxy-default timeout to 250 msec and try the 10000 msec
112 * call - this should FAIL. Again, we use such a long sleep because on slow
113 * machines there's no guarantee we'll be scheduled when we want to be. */
114 g_dbus_proxy_set_default_timeout (proxy, 250);
115 g_assert_cmpint (g_dbus_proxy_get_default_timeout (proxy), ==, 250);
116 result = g_dbus_proxy_call_sync (proxy,
117 "Sleep",
118 g_variant_new ("(i)", 10000 /* msec */),
119 G_DBUS_CALL_FLAGS_NONE,
120 -1, /* use proxy default (e.g. 250 msec) */
121 NULL,
122 &error);
123 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_TIMED_OUT);
124 g_assert (!g_dbus_error_is_remote_error (error));
125 g_assert (result == NULL);
126 g_clear_error (&error);
128 /* clean up after ourselves */
129 g_dbus_proxy_set_default_timeout (proxy, -1);
132 static gboolean
133 strv_equal (gchar **strv, ...)
135 gint count;
136 va_list list;
137 const gchar *str;
138 gboolean res;
140 res = TRUE;
141 count = 0;
142 va_start (list, strv);
143 while (1)
145 str = va_arg (list, const gchar *);
146 if (str == NULL)
147 break;
148 if (g_strcmp0 (str, strv[count]) != 0)
150 res = FALSE;
151 break;
153 count++;
155 va_end (list);
157 if (res)
158 res = g_strv_length (strv) == count;
160 return res;
163 /* ---------------------------------------------------------------------------------------------------- */
164 /* Test that the property aspects of GDBusProxy works */
165 /* ---------------------------------------------------------------------------------------------------- */
167 static void
168 test_properties (GDBusProxy *proxy)
170 GError *error;
171 GVariant *variant;
172 GVariant *variant2;
173 GVariant *result;
174 gchar **names;
175 gchar *name_owner;
176 GDBusProxy *proxy2;
178 error = NULL;
180 if (g_dbus_proxy_get_flags (proxy) & G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES)
182 g_assert (g_dbus_proxy_get_cached_property_names (proxy) == NULL);
183 return;
187 * Check that we can list all cached properties.
189 names = g_dbus_proxy_get_cached_property_names (proxy);
191 g_assert (strv_equal (names,
192 "PropertyThatWillBeInvalidated",
193 "ab",
194 "ad",
195 "ai",
196 "an",
197 "ao",
198 "aq",
199 "as",
200 "at",
201 "au",
202 "ax",
203 "ay",
204 "b",
205 "d",
206 "foo",
207 "i",
208 "n",
209 "o",
210 "q",
211 "s",
212 "t",
213 "u",
214 "x",
215 "y",
216 NULL));
218 g_strfreev (names);
221 * Check that we can read cached properties.
223 * No need to test all properties - GVariant has already been tested
225 variant = g_dbus_proxy_get_cached_property (proxy, "y");
226 g_assert (variant != NULL);
227 g_assert_cmpint (g_variant_get_byte (variant), ==, 1);
228 g_variant_unref (variant);
229 variant = g_dbus_proxy_get_cached_property (proxy, "o");
230 g_assert (variant != NULL);
231 g_assert_cmpstr (g_variant_get_string (variant, NULL), ==, "/some/path");
232 g_variant_unref (variant);
235 * Now ask the service to change a property and check that #GDBusProxy::g-property-changed
236 * is received. Also check that the cache is updated.
238 variant2 = g_variant_new_byte (42);
239 result = g_dbus_proxy_call_sync (proxy,
240 "FrobSetProperty",
241 g_variant_new ("(sv)",
242 "y",
243 variant2),
244 G_DBUS_CALL_FLAGS_NONE,
246 NULL,
247 &error);
248 g_assert_no_error (error);
249 g_assert (result != NULL);
250 g_assert_cmpstr (g_variant_get_type_string (result), ==, "()");
251 g_variant_unref (result);
252 _g_assert_signal_received (proxy, "g-properties-changed");
253 variant = g_dbus_proxy_get_cached_property (proxy, "y");
254 g_assert (variant != NULL);
255 g_assert_cmpint (g_variant_get_byte (variant), ==, 42);
256 g_variant_unref (variant);
258 g_dbus_proxy_set_cached_property (proxy, "y", g_variant_new_byte (142));
259 variant = g_dbus_proxy_get_cached_property (proxy, "y");
260 g_assert (variant != NULL);
261 g_assert_cmpint (g_variant_get_byte (variant), ==, 142);
262 g_variant_unref (variant);
264 g_dbus_proxy_set_cached_property (proxy, "y", NULL);
265 variant = g_dbus_proxy_get_cached_property (proxy, "y");
266 g_assert (variant == NULL);
268 /* Check that the invalidation feature of the PropertiesChanged()
269 * signal works... First, check that we have a cached value of the
270 * property (from the initial GetAll() call)
272 variant = g_dbus_proxy_get_cached_property (proxy, "PropertyThatWillBeInvalidated");
273 g_assert (variant != NULL);
274 g_assert_cmpstr (g_variant_get_string (variant, NULL), ==, "InitialValue");
275 g_variant_unref (variant);
276 /* now ask to invalidate the property - this causes a
278 * PropertiesChanaged("com.example.Frob",
279 * {},
280 * ["PropertyThatWillBeInvalidated")
282 * signal to be emitted. This is received before the method reply
283 * for FrobInvalidateProperty *but* since the proxy was created in
284 * the same thread as we're doing this synchronous call, we'll get
285 * the method reply before...
287 result = g_dbus_proxy_call_sync (proxy,
288 "FrobInvalidateProperty",
289 g_variant_new ("(s)", "OMGInvalidated"),
290 G_DBUS_CALL_FLAGS_NONE,
292 NULL,
293 &error);
294 g_assert_no_error (error);
295 g_assert (result != NULL);
296 g_assert_cmpstr (g_variant_get_type_string (result), ==, "()");
297 g_variant_unref (result);
298 /* ... hence we wait for the g-properties-changed signal to be delivered */
299 _g_assert_signal_received (proxy, "g-properties-changed");
300 /* ... and now we finally, check that the cached value has been invalidated */
301 variant = g_dbus_proxy_get_cached_property (proxy, "PropertyThatWillBeInvalidated");
302 g_assert (variant == NULL);
304 /* Now test that G_DBUS_PROXY_FLAGS_GET_INVALIDATED_PROPERTIES works - we need a new proxy for that */
305 error = NULL;
306 proxy2 = g_dbus_proxy_new_sync (g_dbus_proxy_get_connection (proxy),
307 G_DBUS_PROXY_FLAGS_GET_INVALIDATED_PROPERTIES,
308 NULL, /* GDBusInterfaceInfo */
309 "com.example.TestService", /* name */
310 "/com/example/TestObject", /* object path */
311 "com.example.Frob", /* interface */
312 NULL, /* GCancellable */
313 &error);
314 g_assert_no_error (error);
316 name_owner = g_dbus_proxy_get_name_owner (proxy2);
317 g_assert (name_owner != NULL);
318 g_free (name_owner);
320 variant = g_dbus_proxy_get_cached_property (proxy2, "PropertyThatWillBeInvalidated");
321 g_assert (variant != NULL);
322 g_assert_cmpstr (g_variant_get_string (variant, NULL), ==, "OMGInvalidated"); /* from previous test */
323 g_variant_unref (variant);
325 result = g_dbus_proxy_call_sync (proxy2,
326 "FrobInvalidateProperty",
327 g_variant_new ("(s)", "OMGInvalidated2"),
328 G_DBUS_CALL_FLAGS_NONE,
330 NULL,
331 &error);
332 g_assert_no_error (error);
333 g_assert (result != NULL);
334 g_assert_cmpstr (g_variant_get_type_string (result), ==, "()");
335 g_variant_unref (result);
337 /* this time we should get the ::g-properties-changed _with_ the value */
338 _g_assert_signal_received (proxy2, "g-properties-changed");
340 variant = g_dbus_proxy_get_cached_property (proxy2, "PropertyThatWillBeInvalidated");
341 g_assert (variant != NULL);
342 g_assert_cmpstr (g_variant_get_string (variant, NULL), ==, "OMGInvalidated2");
343 g_variant_unref (variant);
345 g_object_unref (proxy2);
348 /* ---------------------------------------------------------------------------------------------------- */
349 /* Test that the signal aspects of GDBusProxy works */
350 /* ---------------------------------------------------------------------------------------------------- */
352 static void
353 test_proxy_signals_on_signal (GDBusProxy *proxy,
354 const gchar *sender_name,
355 const gchar *signal_name,
356 GVariant *parameters,
357 gpointer user_data)
359 GString *s = user_data;
361 g_assert_cmpstr (signal_name, ==, "TestSignal");
362 g_assert_cmpstr (g_variant_get_type_string (parameters), ==, "(sov)");
364 g_variant_print_string (parameters, s, TRUE);
367 typedef struct
369 GMainLoop *internal_loop;
370 GString *s;
371 } TestSignalData;
373 static void
374 test_proxy_signals_on_emit_signal_cb (GDBusProxy *proxy,
375 GAsyncResult *res,
376 gpointer user_data)
378 TestSignalData *data = user_data;
379 GError *error;
380 GVariant *result;
382 error = NULL;
383 result = g_dbus_proxy_call_finish (proxy,
384 res,
385 &error);
386 g_assert_no_error (error);
387 g_assert (result != NULL);
388 g_assert_cmpstr (g_variant_get_type_string (result), ==, "()");
389 g_variant_unref (result);
391 /* check that the signal was recieved before we got the method result */
392 g_assert (strlen (data->s->str) > 0);
394 /* break out of the loop */
395 g_main_loop_quit (data->internal_loop);
398 static void
399 test_signals (GDBusProxy *proxy)
401 GError *error;
402 GString *s;
403 gulong signal_handler_id;
404 TestSignalData data;
405 GVariant *result;
407 error = NULL;
410 * Ask the service to emit a signal and check that we receive it.
412 * Note that blocking calls don't block in the mainloop so wait for the signal (which
413 * is dispatched before the method reply)
415 s = g_string_new (NULL);
416 signal_handler_id = g_signal_connect (proxy,
417 "g-signal",
418 G_CALLBACK (test_proxy_signals_on_signal),
421 result = g_dbus_proxy_call_sync (proxy,
422 "EmitSignal",
423 g_variant_new ("(so)",
424 "Accept the next proposition you hear",
425 "/some/path"),
426 G_DBUS_CALL_FLAGS_NONE,
428 NULL,
429 &error);
430 g_assert_no_error (error);
431 g_assert (result != NULL);
432 g_assert_cmpstr (g_variant_get_type_string (result), ==, "()");
433 g_variant_unref (result);
434 /* check that we haven't received the signal just yet */
435 g_assert (strlen (s->str) == 0);
436 /* and now wait for the signal */
437 _g_assert_signal_received (proxy, "g-signal");
438 g_assert_cmpstr (s->str,
440 "('Accept the next proposition you hear .. in bed!', objectpath '/some/path/in/bed', <'a variant'>)");
441 g_signal_handler_disconnect (proxy, signal_handler_id);
442 g_string_free (s, TRUE);
445 * Now do this async to check the signal is received before the method returns.
447 s = g_string_new (NULL);
448 data.internal_loop = g_main_loop_new (NULL, FALSE);
449 data.s = s;
450 signal_handler_id = g_signal_connect (proxy,
451 "g-signal",
452 G_CALLBACK (test_proxy_signals_on_signal),
454 g_dbus_proxy_call (proxy,
455 "EmitSignal",
456 g_variant_new ("(so)",
457 "You will make a great programmer",
458 "/some/other/path"),
459 G_DBUS_CALL_FLAGS_NONE,
461 NULL,
462 (GAsyncReadyCallback) test_proxy_signals_on_emit_signal_cb,
463 &data);
464 g_main_loop_run (data.internal_loop);
465 g_main_loop_unref (data.internal_loop);
466 g_assert_cmpstr (s->str,
468 "('You will make a great programmer .. in bed!', objectpath '/some/other/path/in/bed', <'a variant'>)");
469 g_signal_handler_disconnect (proxy, signal_handler_id);
470 g_string_free (s, TRUE);
473 /* ---------------------------------------------------------------------------------------------------- */
475 static void
476 test_bogus_method_return (GDBusProxy *proxy)
478 GError *error = NULL;
479 GVariant *result;
481 result = g_dbus_proxy_call_sync (proxy,
482 "PairReturn",
483 NULL,
484 G_DBUS_CALL_FLAGS_NONE,
486 NULL,
487 &error);
488 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
489 g_error_free (error);
490 g_assert (result == NULL);
493 #if 0 /* Disabled: see https://bugzilla.gnome.org/show_bug.cgi?id=658999 */
494 static void
495 test_bogus_signal (GDBusProxy *proxy)
497 GError *error = NULL;
498 GVariant *result;
499 GDBusInterfaceInfo *old_iface_info;
501 result = g_dbus_proxy_call_sync (proxy,
502 "EmitSignal2",
503 NULL,
504 G_DBUS_CALL_FLAGS_NONE,
506 NULL,
507 &error);
508 g_assert_no_error (error);
509 g_assert (result != NULL);
510 g_assert_cmpstr (g_variant_get_type_string (result), ==, "()");
511 g_variant_unref (result);
513 if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDOUT | G_TEST_TRAP_SILENCE_STDERR))
515 /* and now wait for the signal that will never arrive */
516 _g_assert_signal_received (proxy, "g-signal");
518 g_test_trap_assert_stderr ("*Dropping signal TestSignal2 of type (i) since the type from the expected interface is (u)*");
519 g_test_trap_assert_failed();
521 /* Our main branch will also do g_warning() when running the mainloop so
522 * temporarily remove the expected interface
524 old_iface_info = g_dbus_proxy_get_interface_info (proxy);
525 g_dbus_proxy_set_interface_info (proxy, NULL);
526 _g_assert_signal_received (proxy, "g-signal");
527 g_dbus_proxy_set_interface_info (proxy, old_iface_info);
530 static void
531 test_bogus_property (GDBusProxy *proxy)
533 GError *error = NULL;
534 GVariant *result;
535 GDBusInterfaceInfo *old_iface_info;
537 /* Make the service emit a PropertiesChanged signal for property 'i' of type 'i' - since
538 * our introspection data has this as type 'u' we should get a warning on stderr.
540 result = g_dbus_proxy_call_sync (proxy,
541 "FrobSetProperty",
542 g_variant_new ("(sv)",
543 "i", g_variant_new_int32 (42)),
544 G_DBUS_CALL_FLAGS_NONE,
546 NULL,
547 &error);
548 g_assert_no_error (error);
549 g_assert (result != NULL);
550 g_assert_cmpstr (g_variant_get_type_string (result), ==, "()");
551 g_variant_unref (result);
553 if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDOUT | G_TEST_TRAP_SILENCE_STDERR))
555 /* and now wait for the signal that will never arrive */
556 _g_assert_signal_received (proxy, "g-properties-changed");
558 g_test_trap_assert_stderr ("*Received property i with type i does not match expected type u in the expected interface*");
559 g_test_trap_assert_failed();
561 /* Our main branch will also do g_warning() when running the mainloop so
562 * temporarily remove the expected interface
564 old_iface_info = g_dbus_proxy_get_interface_info (proxy);
565 g_dbus_proxy_set_interface_info (proxy, NULL);
566 _g_assert_signal_received (proxy, "g-properties-changed");
567 g_dbus_proxy_set_interface_info (proxy, old_iface_info);
569 #endif /* Disabled: see https://bugzilla.gnome.org/show_bug.cgi?id=658999 */
571 /* ---------------------------------------------------------------------------------------------------- */
573 static const gchar *frob_dbus_interface_xml =
574 "<node>"
575 " <interface name='com.example.Frob'>"
576 /* PairReturn() is deliberately different from gdbus-testserver's definition */
577 " <method name='PairReturn'>"
578 " <arg type='u' name='somenumber' direction='in'/>"
579 " <arg type='s' name='somestring' direction='out'/>"
580 " </method>"
581 " <method name='HelloWorld'>"
582 " <arg type='s' name='somestring' direction='in'/>"
583 " <arg type='s' name='somestring' direction='out'/>"
584 " </method>"
585 " <method name='Sleep'>"
586 " <arg type='i' name='timeout' direction='in'/>"
587 " </method>"
588 /* We deliberately only mention a single property here */
589 " <property name='y' type='y' access='readwrite'/>"
590 /* The 'i' property is deliberately different from gdbus-testserver's definition */
591 " <property name='i' type='u' access='readwrite'/>"
592 /* ::TestSignal2 is deliberately different from gdbus-testserver's definition */
593 " <signal name='TestSignal2'>"
594 " <arg type='u' name='somenumber'/>"
595 " </signal>"
596 " </interface>"
597 "</node>";
598 static GDBusInterfaceInfo *frob_dbus_interface_info;
600 static void
601 test_expected_interface (GDBusProxy *proxy)
603 GVariant *value;
604 GError *error;
606 /* This is obviously wrong but expected interface is not set so we don't fail... */
607 g_dbus_proxy_set_cached_property (proxy, "y", g_variant_new_string ("error_me_out!"));
608 g_dbus_proxy_set_cached_property (proxy, "y", g_variant_new_byte (42));
609 g_dbus_proxy_set_cached_property (proxy, "does-not-exist", g_variant_new_string ("something"));
610 g_dbus_proxy_set_cached_property (proxy, "does-not-exist", NULL);
612 /* Now repeat the method tests, with an expected interface set */
613 g_dbus_proxy_set_interface_info (proxy, frob_dbus_interface_info);
614 test_methods (proxy);
615 test_signals (proxy);
617 /* And also where we deliberately set the expected interface definition incorrectly */
618 test_bogus_method_return (proxy);
619 /* Disabled: see https://bugzilla.gnome.org/show_bug.cgi?id=658999
620 test_bogus_signal (proxy);
621 test_bogus_property (proxy);
624 if (g_test_undefined ())
626 /* Also check that we complain if setting a cached property of the wrong type */
627 g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING,
628 "*Trying to set property y of type s but according to the expected interface the type is y*");
629 g_dbus_proxy_set_cached_property (proxy, "y", g_variant_new_string ("error_me_out!"));
630 g_test_assert_expected_messages ();
633 /* this should work, however (since the type is correct) */
634 g_dbus_proxy_set_cached_property (proxy, "y", g_variant_new_byte (42));
636 if (g_test_undefined ())
638 /* Try to get the value of a property where the type we expect is different from
639 * what we have in our cache (e.g. what the service returned)
641 g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING,
642 "*Trying to get property i with type i but according to the expected interface the type is u*");
643 value = g_dbus_proxy_get_cached_property (proxy, "i");
644 g_test_assert_expected_messages ();
647 /* Even if a property does not exist in expected_interface, looking it
648 * up, or setting it, should never fail. Because it could be that the
649 * property has been added to the service but the GDBusInterfaceInfo*
650 * passed to g_dbus_proxy_set_interface_info() just haven't been updated.
652 * See https://bugzilla.gnome.org/show_bug.cgi?id=660886
654 value = g_dbus_proxy_get_cached_property (proxy, "d");
655 g_assert (value != NULL);
656 g_assert (g_variant_is_of_type (value, G_VARIANT_TYPE_DOUBLE));
657 g_assert_cmpfloat (g_variant_get_double (value), ==, 7.5);
658 g_variant_unref (value);
659 /* update it via the cached property... */
660 g_dbus_proxy_set_cached_property (proxy, "d", g_variant_new_double (75.0));
661 /* ... and finally check that it has changed */
662 value = g_dbus_proxy_get_cached_property (proxy, "d");
663 g_assert (value != NULL);
664 g_assert (g_variant_is_of_type (value, G_VARIANT_TYPE_DOUBLE));
665 g_assert_cmpfloat (g_variant_get_double (value), ==, 75.0);
666 g_variant_unref (value);
667 /* now update it via the D-Bus interface... */
668 error = NULL;
669 value = g_dbus_proxy_call_sync (proxy, "FrobSetProperty",
670 g_variant_new ("(sv)", "d", g_variant_new_double (85.0)),
671 G_DBUS_CALL_FLAGS_NONE,
672 -1, NULL, &error);
673 g_assert_no_error (error);
674 g_assert (value != NULL);
675 g_assert_cmpstr (g_variant_get_type_string (value), ==, "()");
676 g_variant_unref (value);
677 /* ...ensure we receive the ::PropertiesChanged signal... */
678 _g_assert_signal_received (proxy, "g-properties-changed");
679 /* ... and finally check that it has changed */
680 value = g_dbus_proxy_get_cached_property (proxy, "d");
681 g_assert (value != NULL);
682 g_assert (g_variant_is_of_type (value, G_VARIANT_TYPE_DOUBLE));
683 g_assert_cmpfloat (g_variant_get_double (value), ==, 85.0);
684 g_variant_unref (value);
687 static void
688 test_basic (GDBusProxy *proxy)
690 GDBusConnection *connection;
691 GDBusConnection *conn;
692 GDBusProxyFlags flags;
693 GDBusInterfaceInfo *info;
694 gchar *name;
695 gchar *path;
696 gchar *interface;
697 gint timeout;
699 connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
701 g_assert (g_dbus_proxy_get_connection (proxy) == connection);
702 g_assert (g_dbus_proxy_get_flags (proxy) == G_DBUS_PROXY_FLAGS_NONE);
703 g_assert (g_dbus_proxy_get_interface_info (proxy) == NULL);
704 g_assert_cmpstr (g_dbus_proxy_get_name (proxy), ==, "com.example.TestService");
705 g_assert_cmpstr (g_dbus_proxy_get_object_path (proxy), ==, "/com/example/TestObject");
706 g_assert_cmpstr (g_dbus_proxy_get_interface_name (proxy), ==, "com.example.Frob");
707 g_assert_cmpint (g_dbus_proxy_get_default_timeout (proxy), ==, -1);
709 g_object_get (proxy,
710 "g-connection", &conn,
711 "g-interface-info", &info,
712 "g-flags", &flags,
713 "g-name", &name,
714 "g-object-path", &path,
715 "g-interface-name", &interface,
716 "g-default-timeout", &timeout,
717 NULL);
719 g_assert (conn == connection);
720 g_assert (info == NULL);
721 g_assert_cmpint (flags, ==, G_DBUS_PROXY_FLAGS_NONE);
722 g_assert_cmpstr (name, ==, "com.example.TestService");
723 g_assert_cmpstr (path, ==, "/com/example/TestObject");
724 g_assert_cmpstr (interface, ==, "com.example.Frob");
725 g_assert_cmpint (timeout, ==, -1);
727 g_object_unref (conn);
728 g_free (name);
729 g_free (path);
730 g_free (interface);
732 g_object_unref (connection);
735 static void
736 kill_test_service (GDBusConnection *connection)
738 #ifdef G_OS_UNIX
739 guint pid;
740 GVariant *ret;
741 GError *error = NULL;
742 const gchar *name = "com.example.TestService";
744 ret = g_dbus_connection_call_sync (connection,
745 "org.freedesktop.DBus",
746 "/org/freedesktop/DBus",
747 "org.freedesktop.DBus",
748 "GetConnectionUnixProcessID",
749 g_variant_new ("(s)", name),
750 NULL,
751 G_DBUS_CALL_FLAGS_NONE,
753 NULL,
754 &error);
755 g_variant_get (ret, "(u)", &pid);
756 g_variant_unref (ret);
757 kill (pid, SIGTERM);
758 #else
759 g_warning ("Can't kill com.example.TestService");
760 #endif
763 static void
764 test_proxy (void)
766 GDBusProxy *proxy;
767 GDBusConnection *connection;
768 GError *error;
770 error = NULL;
771 connection = g_bus_get_sync (G_BUS_TYPE_SESSION,
772 NULL,
773 &error);
774 g_assert_no_error (error);
775 error = NULL;
776 proxy = g_dbus_proxy_new_sync (connection,
777 G_DBUS_PROXY_FLAGS_NONE,
778 NULL, /* GDBusInterfaceInfo */
779 "com.example.TestService", /* name */
780 "/com/example/TestObject", /* object path */
781 "com.example.Frob", /* interface */
782 NULL, /* GCancellable */
783 &error);
784 g_assert_no_error (error);
786 /* this is safe; testserver will exit once the bus goes away */
787 g_assert (g_spawn_command_line_async (g_test_get_filename (G_TEST_BUILT, "gdbus-testserver", NULL), NULL));
789 _g_assert_property_notify (proxy, "g-name-owner");
791 test_basic (proxy);
792 test_methods (proxy);
793 test_properties (proxy);
794 test_signals (proxy);
795 test_expected_interface (proxy);
797 g_object_unref (proxy);
798 kill_test_service (connection);
799 g_object_unref (connection);
802 /* ---------------------------------------------------------------------------------------------------- */
804 static void
805 proxy_ready (GObject *source,
806 GAsyncResult *result,
807 gpointer user_data)
809 GDBusProxy *proxy;
810 GError *error;
812 error = NULL;
813 proxy = g_dbus_proxy_new_for_bus_finish (result, &error);
814 g_assert_no_error (error);
816 _g_assert_property_notify (proxy, "g-name-owner");
818 test_basic (proxy);
819 test_methods (proxy);
820 test_properties (proxy);
821 test_signals (proxy);
822 test_expected_interface (proxy);
824 kill_test_service (g_dbus_proxy_get_connection (proxy));
825 g_object_unref (proxy);
826 g_main_loop_quit (loop);
829 static gboolean
830 fail_test (gpointer user_data)
832 g_assert_not_reached ();
835 static void
836 test_async (void)
838 guint id;
840 g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION,
841 G_DBUS_PROXY_FLAGS_NONE,
842 NULL, /* GDBusInterfaceInfo */
843 "com.example.TestService", /* name */
844 "/com/example/TestObject", /* object path */
845 "com.example.Frob", /* interface */
846 NULL, /* GCancellable */
847 proxy_ready,
848 NULL);
850 /* this is safe; testserver will exit once the bus goes away */
851 g_assert (g_spawn_command_line_async (g_test_get_filename (G_TEST_BUILT, "gdbus-testserver", NULL), NULL));
853 id = g_timeout_add (10000, fail_test, NULL);
854 g_main_loop_run (loop);
856 g_source_remove (id);
859 static void
860 test_no_properties (void)
862 GDBusProxy *proxy;
863 GError *error;
865 error = NULL;
866 proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
867 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
868 NULL, /* GDBusInterfaceInfo */
869 "com.example.TestService", /* name */
870 "/com/example/TestObject", /* object path */
871 "com.example.Frob", /* interface */
872 NULL, /* GCancellable */
873 &error);
874 g_assert_no_error (error);
876 test_properties (proxy);
878 g_object_unref (proxy);
881 static void
882 check_error (GObject *source,
883 GAsyncResult *result,
884 gpointer user_data)
886 GError *error = NULL;
887 GVariant *reply;
889 reply = g_dbus_proxy_call_finish (G_DBUS_PROXY (source), result, &error);
890 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_FAILED);
891 g_assert (reply == NULL);
892 g_error_free (error);
894 g_main_loop_quit (loop);
897 static void
898 test_wellknown_noauto (void)
900 GError *error = NULL;
901 GDBusProxy *proxy;
902 guint id;
904 proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
905 G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
906 NULL, "some.name.that.does.not.exist",
907 "/", "some.interface", NULL, &error);
908 g_assert_no_error (error);
909 g_assert (proxy != NULL);
911 g_dbus_proxy_call (proxy, "method", NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, check_error, NULL);
912 id = g_timeout_add (10000, fail_test, NULL);
913 g_main_loop_run (loop);
914 g_object_unref (proxy);
915 g_source_remove (id);
919 main (int argc,
920 char *argv[])
922 gint ret;
923 GDBusNodeInfo *introspection_data = NULL;
925 g_test_init (&argc, &argv, NULL);
927 introspection_data = g_dbus_node_info_new_for_xml (frob_dbus_interface_xml, NULL);
928 g_assert (introspection_data != NULL);
929 frob_dbus_interface_info = introspection_data->interfaces[0];
931 /* all the tests rely on a shared main loop */
932 loop = g_main_loop_new (NULL, FALSE);
934 g_test_add_func ("/gdbus/proxy", test_proxy);
935 g_test_add_func ("/gdbus/proxy/no-properties", test_no_properties);
936 g_test_add_func ("/gdbus/proxy/wellknown-noauto", test_wellknown_noauto);
937 g_test_add_func ("/gdbus/proxy/async", test_async);
939 ret = session_bus_run();
941 g_dbus_node_info_unref (introspection_data);
943 return ret;