build: Don't use C99 declarations
[platform/upstream/glib.git] / gio / tests / gdbus-proxy.c
1 /* GLib testing framework examples and tests
2  *
3  * Copyright (C) 2008-2010 Red Hat, Inc.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
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.
14  *
15  * You should have received a copy of the GNU Lesser General
16  * Public License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18  * Boston, MA 02111-1307, USA.
19  *
20  * Author: David Zeuthen <davidz@redhat.com>
21  */
22
23 #include <gio/gio.h>
24 #include <unistd.h>
25 #include <string.h>
26
27 #include "gdbus-tests.h"
28
29 /* all tests rely on a shared mainloop */
30 static GMainLoop *loop = NULL;
31
32 /* ---------------------------------------------------------------------------------------------------- */
33 /* Test that the method aspects of GDBusProxy works */
34 /* ---------------------------------------------------------------------------------------------------- */
35
36 static void
37 test_methods (GDBusProxy *proxy)
38 {
39   GVariant *result;
40   GError *error;
41   const gchar *str;
42   gchar *dbus_error_name;
43
44   /* check that we can invoke a method */
45   error = NULL;
46   result = g_dbus_proxy_call_sync (proxy,
47                                    "HelloWorld",
48                                    g_variant_new ("(s)", "Hey"),
49                                    G_DBUS_CALL_FLAGS_NONE,
50                                    -1,
51                                    NULL,
52                                    &error);
53   g_assert_no_error (error);
54   g_assert (result != NULL);
55   g_assert_cmpstr (g_variant_get_type_string (result), ==, "(s)");
56   g_variant_get (result, "(&s)", &str);
57   g_assert_cmpstr (str, ==, "You greeted me with 'Hey'. Thanks!");
58   g_variant_unref (result);
59
60   /* Check that we can completely recover the returned error */
61   result = g_dbus_proxy_call_sync (proxy,
62                                    "HelloWorld",
63                                    g_variant_new ("(s)", "Yo"),
64                                    G_DBUS_CALL_FLAGS_NONE,
65                                    -1,
66                                    NULL,
67                                    &error);
68   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_DBUS_ERROR);
69   g_assert (g_dbus_error_is_remote_error (error));
70   g_assert (g_dbus_error_is_remote_error (error));
71   g_assert (result == NULL);
72   dbus_error_name = g_dbus_error_get_remote_error (error);
73   g_assert_cmpstr (dbus_error_name, ==, "com.example.TestException");
74   g_free (dbus_error_name);
75   g_assert (g_dbus_error_strip_remote_error (error));
76   g_assert_cmpstr (error->message, ==, "Yo is not a proper greeting");
77   g_clear_error (&error);
78
79   /* Check that we get a timeout if the method handling is taking longer than timeout */
80   error = NULL;
81   result = g_dbus_proxy_call_sync (proxy,
82                                    "Sleep",
83                                    g_variant_new ("(i)", 500 /* msec */),
84                                    G_DBUS_CALL_FLAGS_NONE,
85                                    100 /* msec */,
86                                    NULL,
87                                    &error);
88   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_TIMED_OUT);
89   g_assert (!g_dbus_error_is_remote_error (error));
90   g_assert (result == NULL);
91   g_clear_error (&error);
92
93   /* Check that proxy-default timeouts work. */
94   g_assert_cmpint (g_dbus_proxy_get_default_timeout (proxy), ==, -1);
95
96   /* the default timeout is 25000 msec so this should work */
97   result = g_dbus_proxy_call_sync (proxy,
98                                    "Sleep",
99                                    g_variant_new ("(i)", 500 /* msec */),
100                                    G_DBUS_CALL_FLAGS_NONE,
101                                    -1, /* use proxy default (e.g. -1 -> e.g. 25000 msec) */
102                                    NULL,
103                                    &error);
104   g_assert_no_error (error);
105   g_assert (result != NULL);
106   g_assert_cmpstr (g_variant_get_type_string (result), ==, "()");
107   g_variant_unref (result);
108
109   /* now set the proxy-default timeout to 250 msec and try the 500 msec call - this should FAIL */
110   g_dbus_proxy_set_default_timeout (proxy, 250);
111   g_assert_cmpint (g_dbus_proxy_get_default_timeout (proxy), ==, 250);
112   result = g_dbus_proxy_call_sync (proxy,
113                                    "Sleep",
114                                    g_variant_new ("(i)", 500 /* msec */),
115                                    G_DBUS_CALL_FLAGS_NONE,
116                                    -1, /* use proxy default (e.g. 250 msec) */
117                                    NULL,
118                                    &error);
119   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_TIMED_OUT);
120   g_assert (!g_dbus_error_is_remote_error (error));
121   g_assert (result == NULL);
122   g_clear_error (&error);
123
124   /* clean up after ourselves */
125   g_dbus_proxy_set_default_timeout (proxy, -1);
126 }
127
128 static gboolean
129 strv_equal (gchar **strv, ...)
130 {
131   gint count;
132   va_list list;
133   const gchar *str;
134   gboolean res;
135
136   res = TRUE;
137   count = 0;
138   va_start (list, strv);
139   while (1)
140     {
141       str = va_arg (list, const gchar *);
142       if (str == NULL)
143         break;
144       if (g_strcmp0 (str, strv[count]) != 0)
145         {
146           res = FALSE;
147           break;
148         }
149       count++;
150     }
151   va_end (list);
152
153   if (res)
154     res = g_strv_length (strv) == count;
155
156   return res;
157 }
158
159 /* ---------------------------------------------------------------------------------------------------- */
160 /* Test that the property aspects of GDBusProxy works */
161 /* ---------------------------------------------------------------------------------------------------- */
162
163 static void
164 test_properties (GDBusProxy *proxy)
165 {
166   GError *error;
167   GVariant *variant;
168   GVariant *variant2;
169   GVariant *result;
170   gchar **names;
171   gchar *name_owner;
172   GDBusProxy *proxy2;
173
174   error = NULL;
175
176   if (g_dbus_proxy_get_flags (proxy) & G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES)
177     {
178        g_assert (g_dbus_proxy_get_cached_property_names (proxy) == NULL);
179        return;
180     }
181
182   /*
183    * Check that we can list all cached properties.
184    */
185   names = g_dbus_proxy_get_cached_property_names (proxy);
186
187   g_assert (strv_equal (names,
188                         "PropertyThatWillBeInvalidated",
189                         "ab",
190                         "ad",
191                         "ai",
192                         "an",
193                         "ao",
194                         "aq",
195                         "as",
196                         "at",
197                         "au",
198                         "ax",
199                         "ay",
200                         "b",
201                         "d",
202                         "foo",
203                         "i",
204                         "n",
205                         "o",
206                         "q",
207                         "s",
208                         "t",
209                         "u",
210                         "x",
211                         "y",
212                         NULL));
213
214   g_strfreev (names);
215
216   /*
217    * Check that we can read cached properties.
218    *
219    * No need to test all properties - GVariant has already been tested
220    */
221   variant = g_dbus_proxy_get_cached_property (proxy, "y");
222   g_assert (variant != NULL);
223   g_assert_cmpint (g_variant_get_byte (variant), ==, 1);
224   g_variant_unref (variant);
225   variant = g_dbus_proxy_get_cached_property (proxy, "o");
226   g_assert (variant != NULL);
227   g_assert_cmpstr (g_variant_get_string (variant, NULL), ==, "/some/path");
228   g_variant_unref (variant);
229
230   /*
231    * Now ask the service to change a property and check that #GDBusProxy::g-property-changed
232    * is received. Also check that the cache is updated.
233    */
234   variant2 = g_variant_new_byte (42);
235   result = g_dbus_proxy_call_sync (proxy,
236                                    "FrobSetProperty",
237                                    g_variant_new ("(sv)",
238                                                   "y",
239                                                   variant2),
240                                    G_DBUS_CALL_FLAGS_NONE,
241                                    -1,
242                                    NULL,
243                                    &error);
244   g_assert_no_error (error);
245   g_assert (result != NULL);
246   g_assert_cmpstr (g_variant_get_type_string (result), ==, "()");
247   g_variant_unref (result);
248   _g_assert_signal_received (proxy, "g-properties-changed");
249   variant = g_dbus_proxy_get_cached_property (proxy, "y");
250   g_assert (variant != NULL);
251   g_assert_cmpint (g_variant_get_byte (variant), ==, 42);
252   g_variant_unref (variant);
253
254   g_dbus_proxy_set_cached_property (proxy, "y", g_variant_new_byte (142));
255   variant = g_dbus_proxy_get_cached_property (proxy, "y");
256   g_assert (variant != NULL);
257   g_assert_cmpint (g_variant_get_byte (variant), ==, 142);
258   g_variant_unref (variant);
259
260   g_dbus_proxy_set_cached_property (proxy, "y", NULL);
261   variant = g_dbus_proxy_get_cached_property (proxy, "y");
262   g_assert (variant == NULL);
263
264   /* Check that the invalidation feature of the PropertiesChanged()
265    * signal works... First, check that we have a cached value of the
266    * property (from the initial GetAll() call)
267    */
268   variant = g_dbus_proxy_get_cached_property (proxy, "PropertyThatWillBeInvalidated");
269   g_assert (variant != NULL);
270   g_assert_cmpstr (g_variant_get_string (variant, NULL), ==, "InitialValue");
271   g_variant_unref (variant);
272   /* now ask to invalidate the property - this causes a
273    *
274    *   PropertiesChanaged("com.example.Frob",
275    *                      {},
276    *                      ["PropertyThatWillBeInvalidated")
277    *
278    * signal to be emitted. This is received before the method reply
279    * for FrobInvalidateProperty *but* since the proxy was created in
280    * the same thread as we're doing this synchronous call, we'll get
281    * the method reply before...
282    */
283   result = g_dbus_proxy_call_sync (proxy,
284                                    "FrobInvalidateProperty",
285                                    g_variant_new ("(s)", "OMGInvalidated"),
286                                    G_DBUS_CALL_FLAGS_NONE,
287                                    -1,
288                                    NULL,
289                                    &error);
290   g_assert_no_error (error);
291   g_assert (result != NULL);
292   g_assert_cmpstr (g_variant_get_type_string (result), ==, "()");
293   g_variant_unref (result);
294   /* ... hence we wait for the g-properties-changed signal to be delivered */
295   _g_assert_signal_received (proxy, "g-properties-changed");
296   /* ... and now we finally, check that the cached value has been invalidated */
297   variant = g_dbus_proxy_get_cached_property (proxy, "PropertyThatWillBeInvalidated");
298   g_assert (variant == NULL);
299
300   /* Now test that G_DBUS_PROXY_FLAGS_GET_INVALIDATED_PROPERTIES works - we need a new proxy for that */
301   error = NULL;
302   proxy2 = g_dbus_proxy_new_sync (g_dbus_proxy_get_connection (proxy),
303                                   G_DBUS_PROXY_FLAGS_GET_INVALIDATED_PROPERTIES,
304                                   NULL,                      /* GDBusInterfaceInfo */
305                                   "com.example.TestService", /* name */
306                                   "/com/example/TestObject", /* object path */
307                                   "com.example.Frob",        /* interface */
308                                   NULL, /* GCancellable */
309                                   &error);
310   g_assert_no_error (error);
311
312   name_owner = g_dbus_proxy_get_name_owner (proxy2);
313   g_assert (name_owner != NULL);
314   g_free (name_owner);
315
316   variant = g_dbus_proxy_get_cached_property (proxy2, "PropertyThatWillBeInvalidated");
317   g_assert (variant != NULL);
318   g_assert_cmpstr (g_variant_get_string (variant, NULL), ==, "OMGInvalidated"); /* from previous test */
319   g_variant_unref (variant);
320
321   result = g_dbus_proxy_call_sync (proxy2,
322                                    "FrobInvalidateProperty",
323                                    g_variant_new ("(s)", "OMGInvalidated2"),
324                                    G_DBUS_CALL_FLAGS_NONE,
325                                    -1,
326                                    NULL,
327                                    &error);
328   g_assert_no_error (error);
329   g_assert (result != NULL);
330   g_assert_cmpstr (g_variant_get_type_string (result), ==, "()");
331   g_variant_unref (result);
332
333   /* this time we should get the ::g-properties-changed _with_ the value */
334   _g_assert_signal_received (proxy2, "g-properties-changed");
335
336   variant = g_dbus_proxy_get_cached_property (proxy2, "PropertyThatWillBeInvalidated");
337   g_assert (variant != NULL);
338   g_assert_cmpstr (g_variant_get_string (variant, NULL), ==, "OMGInvalidated2");
339   g_variant_unref (variant);
340
341   g_object_unref (proxy2);
342 }
343
344 /* ---------------------------------------------------------------------------------------------------- */
345 /* Test that the signal aspects of GDBusProxy works */
346 /* ---------------------------------------------------------------------------------------------------- */
347
348 static void
349 test_proxy_signals_on_signal (GDBusProxy  *proxy,
350                               const gchar *sender_name,
351                               const gchar *signal_name,
352                               GVariant    *parameters,
353                               gpointer     user_data)
354 {
355   GString *s = user_data;
356
357   g_assert_cmpstr (signal_name, ==, "TestSignal");
358   g_assert_cmpstr (g_variant_get_type_string (parameters), ==, "(sov)");
359
360   g_variant_print_string (parameters, s, TRUE);
361 }
362
363 typedef struct
364 {
365   GMainLoop *internal_loop;
366   GString *s;
367 } TestSignalData;
368
369 static void
370 test_proxy_signals_on_emit_signal_cb (GDBusProxy   *proxy,
371                                       GAsyncResult *res,
372                                       gpointer      user_data)
373 {
374   TestSignalData *data = user_data;
375   GError *error;
376   GVariant *result;
377
378   error = NULL;
379   result = g_dbus_proxy_call_finish (proxy,
380                                      res,
381                                      &error);
382   g_assert_no_error (error);
383   g_assert (result != NULL);
384   g_assert_cmpstr (g_variant_get_type_string (result), ==, "()");
385   g_variant_unref (result);
386
387   /* check that the signal was recieved before we got the method result */
388   g_assert (strlen (data->s->str) > 0);
389
390   /* break out of the loop */
391   g_main_loop_quit (data->internal_loop);
392 }
393
394 static void
395 test_signals (GDBusProxy *proxy)
396 {
397   GError *error;
398   GString *s;
399   gulong signal_handler_id;
400   TestSignalData data;
401   GVariant *result;
402
403   error = NULL;
404
405   /*
406    * Ask the service to emit a signal and check that we receive it.
407    *
408    * Note that blocking calls don't block in the mainloop so wait for the signal (which
409    * is dispatched before the method reply)
410    */
411   s = g_string_new (NULL);
412   signal_handler_id = g_signal_connect (proxy,
413                                         "g-signal",
414                                         G_CALLBACK (test_proxy_signals_on_signal),
415                                         s);
416
417   result = g_dbus_proxy_call_sync (proxy,
418                                    "EmitSignal",
419                                    g_variant_new ("(so)",
420                                                   "Accept the next proposition you hear",
421                                                   "/some/path"),
422                                    G_DBUS_CALL_FLAGS_NONE,
423                                    -1,
424                                    NULL,
425                                    &error);
426   g_assert_no_error (error);
427   g_assert (result != NULL);
428   g_assert_cmpstr (g_variant_get_type_string (result), ==, "()");
429   g_variant_unref (result);
430   /* check that we haven't received the signal just yet */
431   g_assert (strlen (s->str) == 0);
432   /* and now wait for the signal */
433   _g_assert_signal_received (proxy, "g-signal");
434   g_assert_cmpstr (s->str,
435                    ==,
436                    "('Accept the next proposition you hear .. in bed!', objectpath '/some/path/in/bed', <'a variant'>)");
437   g_signal_handler_disconnect (proxy, signal_handler_id);
438   g_string_free (s, TRUE);
439
440   /*
441    * Now do this async to check the signal is received before the method returns.
442    */
443   s = g_string_new (NULL);
444   data.internal_loop = g_main_loop_new (NULL, FALSE);
445   data.s = s;
446   signal_handler_id = g_signal_connect (proxy,
447                                         "g-signal",
448                                         G_CALLBACK (test_proxy_signals_on_signal),
449                                         s);
450   g_dbus_proxy_call (proxy,
451                      "EmitSignal",
452                      g_variant_new ("(so)",
453                                     "You will make a great programmer",
454                                     "/some/other/path"),
455                      G_DBUS_CALL_FLAGS_NONE,
456                      -1,
457                      NULL,
458                      (GAsyncReadyCallback) test_proxy_signals_on_emit_signal_cb,
459                      &data);
460   g_main_loop_run (data.internal_loop);
461   g_main_loop_unref (data.internal_loop);
462   g_assert_cmpstr (s->str,
463                    ==,
464                    "('You will make a great programmer .. in bed!', objectpath '/some/other/path/in/bed', <'a variant'>)");
465   g_signal_handler_disconnect (proxy, signal_handler_id);
466   g_string_free (s, TRUE);
467 }
468
469 /* ---------------------------------------------------------------------------------------------------- */
470
471 static void
472 test_bogus_method_return (GDBusProxy *proxy)
473 {
474   GError *error = NULL;
475   GVariant *result;
476
477   result = g_dbus_proxy_call_sync (proxy,
478                                    "PairReturn",
479                                    NULL,
480                                    G_DBUS_CALL_FLAGS_NONE,
481                                    -1,
482                                    NULL,
483                                    &error);
484   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
485   g_error_free (error);
486   g_assert (result == NULL);
487 }
488
489 #if 0 /* Disabled: see https://bugzilla.gnome.org/show_bug.cgi?id=658999 */
490 static void
491 test_bogus_signal (GDBusProxy *proxy)
492 {
493   GError *error = NULL;
494   GVariant *result;
495   GDBusInterfaceInfo *old_iface_info;
496
497   result = g_dbus_proxy_call_sync (proxy,
498                                    "EmitSignal2",
499                                    NULL,
500                                    G_DBUS_CALL_FLAGS_NONE,
501                                    -1,
502                                    NULL,
503                                    &error);
504   g_assert_no_error (error);
505   g_assert (result != NULL);
506   g_assert_cmpstr (g_variant_get_type_string (result), ==, "()");
507   g_variant_unref (result);
508
509   if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDOUT | G_TEST_TRAP_SILENCE_STDERR))
510     {
511       /* and now wait for the signal that will never arrive */
512       _g_assert_signal_received (proxy, "g-signal");
513     }
514   g_test_trap_assert_stderr ("*Dropping signal TestSignal2 of type (i) since the type from the expected interface is (u)*");
515   g_test_trap_assert_failed();
516
517   /* Our main branch will also do g_warning() when running the mainloop so
518    * temporarily remove the expected interface
519    */
520   old_iface_info = g_dbus_proxy_get_interface_info (proxy);
521   g_dbus_proxy_set_interface_info (proxy, NULL);
522   _g_assert_signal_received (proxy, "g-signal");
523   g_dbus_proxy_set_interface_info (proxy, old_iface_info);
524 }
525
526 static void
527 test_bogus_property (GDBusProxy *proxy)
528 {
529   GError *error = NULL;
530   GVariant *result;
531   GDBusInterfaceInfo *old_iface_info;
532
533   /* Make the service emit a PropertiesChanged signal for property 'i' of type 'i' - since
534    * our introspection data has this as type 'u' we should get a warning on stderr.
535    */
536   result = g_dbus_proxy_call_sync (proxy,
537                                    "FrobSetProperty",
538                                    g_variant_new ("(sv)",
539                                                   "i", g_variant_new_int32 (42)),
540                                    G_DBUS_CALL_FLAGS_NONE,
541                                    -1,
542                                    NULL,
543                                    &error);
544   g_assert_no_error (error);
545   g_assert (result != NULL);
546   g_assert_cmpstr (g_variant_get_type_string (result), ==, "()");
547   g_variant_unref (result);
548
549   if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDOUT | G_TEST_TRAP_SILENCE_STDERR))
550     {
551       /* and now wait for the signal that will never arrive */
552       _g_assert_signal_received (proxy, "g-properties-changed");
553     }
554   g_test_trap_assert_stderr ("*Received property i with type i does not match expected type u in the expected interface*");
555   g_test_trap_assert_failed();
556
557   /* Our main branch will also do g_warning() when running the mainloop so
558    * temporarily remove the expected interface
559    */
560   old_iface_info = g_dbus_proxy_get_interface_info (proxy);
561   g_dbus_proxy_set_interface_info (proxy, NULL);
562   _g_assert_signal_received (proxy, "g-properties-changed");
563   g_dbus_proxy_set_interface_info (proxy, old_iface_info);
564 }
565 #endif /* Disabled: see https://bugzilla.gnome.org/show_bug.cgi?id=658999 */
566
567 /* ---------------------------------------------------------------------------------------------------- */
568
569 static const gchar *frob_dbus_interface_xml =
570   "<node>"
571   "  <interface name='com.example.Frob'>"
572   /* PairReturn() is deliberately different from gdbus-testserver.py's definition */
573   "    <method name='PairReturn'>"
574   "      <arg type='u' name='somenumber' direction='in'/>"
575   "      <arg type='s' name='somestring' direction='out'/>"
576   "    </method>"
577   "    <method name='HelloWorld'>"
578   "      <arg type='s' name='somestring' direction='in'/>"
579   "      <arg type='s' name='somestring' direction='out'/>"
580   "    </method>"
581   "    <method name='Sleep'>"
582   "      <arg type='i' name='timeout' direction='in'/>"
583   "    </method>"
584   /* We deliberately only mention a single property here */
585   "    <property name='y' type='y' access='readwrite'/>"
586   /* The 'i' property is deliberately different from gdbus-testserver.py's definition */
587   "    <property name='i' type='u' access='readwrite'/>"
588   /* ::TestSignal2 is deliberately different from gdbus-testserver.py's definition */
589   "    <signal name='TestSignal2'>"
590   "      <arg type='u' name='somenumber'/>"
591   "    </signal>"
592   "  </interface>"
593   "</node>";
594 static GDBusInterfaceInfo *frob_dbus_interface_info;
595
596 static void
597 test_expected_interface (GDBusProxy *proxy)
598 {
599   GVariant *value;
600   GError *error;
601
602   /* This is obviously wrong but expected interface is not set so we don't fail... */
603   g_dbus_proxy_set_cached_property (proxy, "y", g_variant_new_string ("error_me_out!"));
604   g_dbus_proxy_set_cached_property (proxy, "y", g_variant_new_byte (42));
605   g_dbus_proxy_set_cached_property (proxy, "does-not-exist", g_variant_new_string ("something"));
606   g_dbus_proxy_set_cached_property (proxy, "does-not-exist", NULL);
607
608   /* Now repeat the method tests, with an expected interface set */
609   g_dbus_proxy_set_interface_info (proxy, frob_dbus_interface_info);
610   test_methods (proxy);
611   test_signals (proxy);
612
613   /* And also where we deliberately set the expected interface definition incorrectly */
614   test_bogus_method_return (proxy);
615   /* Disabled: see https://bugzilla.gnome.org/show_bug.cgi?id=658999
616   test_bogus_signal (proxy);
617   test_bogus_property (proxy);
618   */
619
620   if (g_test_undefined ())
621     {
622       /* Also check that we complain if setting a cached property of the wrong type */
623       if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDOUT | G_TEST_TRAP_SILENCE_STDERR))
624         {
625           g_dbus_proxy_set_cached_property (proxy, "y", g_variant_new_string ("error_me_out!"));
626         }
627       g_test_trap_assert_stderr ("*Trying to set property y of type s but according to the expected interface the type is y*");
628       g_test_trap_assert_failed();
629     }
630
631   /* this should work, however (since the type is correct) */
632   g_dbus_proxy_set_cached_property (proxy, "y", g_variant_new_byte (42));
633
634   if (g_test_undefined ())
635     {
636       /* Try to get the value of a property where the type we expect is different from
637        * what we have in our cache (e.g. what the service returned)
638        */
639       if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDOUT | G_TEST_TRAP_SILENCE_STDERR))
640         {
641           value = g_dbus_proxy_get_cached_property (proxy, "i");
642         }
643       g_test_trap_assert_stderr ("*Trying to get property i with type i but according to the expected interface the type is u*");
644       g_test_trap_assert_failed();
645     }
646
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.
651    *
652    * See https://bugzilla.gnome.org/show_bug.cgi?id=660886
653    */
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);
685 }
686
687 static void
688 test_basic (GDBusProxy *proxy)
689 {
690   GDBusConnection *connection;
691   GDBusConnection *conn;
692   GDBusProxyFlags flags;
693   GDBusInterfaceInfo *info;
694   gchar *name;
695   gchar *path;
696   gchar *interface;
697   gint timeout;
698
699   connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
700
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);
708
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);
718
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);
726
727   g_object_unref (conn);
728   g_free (name);
729   g_free (path);
730   g_free (interface);
731
732   g_object_unref (connection);
733 }
734
735 static void
736 kill_test_service (GDBusConnection *connection)
737 {
738   guint pid;
739   GVariant *ret;
740   GError *error = NULL;
741   const gchar *name = "com.example.TestService";
742
743   ret = g_dbus_connection_call_sync (connection,
744                                      "org.freedesktop.DBus",
745                                      "/org/freedesktop/DBus",
746                                      "org.freedesktop.DBus",
747                                      "GetConnectionUnixProcessID",
748                                      g_variant_new ("(s)", name),
749                                      NULL,
750                                      G_DBUS_CALL_FLAGS_NONE,
751                                      -1,
752                                      NULL,
753                                      &error);
754   g_variant_get (ret, "(u)", &pid);
755   g_variant_unref (ret);
756   kill (pid, SIGTERM);
757 }
758
759 static void
760 test_proxy (void)
761 {
762   GDBusProxy *proxy;
763   GDBusConnection *connection;
764   GError *error;
765
766   error = NULL;
767   connection = g_bus_get_sync (G_BUS_TYPE_SESSION,
768                                NULL,
769                                &error);
770   g_assert_no_error (error);
771   error = NULL;
772   proxy = g_dbus_proxy_new_sync (connection,
773                                  G_DBUS_PROXY_FLAGS_NONE,
774                                  NULL,                      /* GDBusInterfaceInfo */
775                                  "com.example.TestService", /* name */
776                                  "/com/example/TestObject", /* object path */
777                                  "com.example.Frob",        /* interface */
778                                  NULL, /* GCancellable */
779                                  &error);
780   g_assert_no_error (error);
781
782   /* this is safe; testserver will exit once the bus goes away */
783   g_assert (g_spawn_command_line_async (SRCDIR "/gdbus-testserver.py", NULL));
784
785   _g_assert_property_notify (proxy, "g-name-owner");
786
787   test_basic (proxy);
788   test_methods (proxy);
789   test_properties (proxy);
790   test_signals (proxy);
791   test_expected_interface (proxy);
792
793   g_object_unref (proxy);
794   kill_test_service (connection);
795   g_object_unref (connection);
796 }
797
798 /* ---------------------------------------------------------------------------------------------------- */
799
800 static void
801 proxy_ready (GObject      *source,
802              GAsyncResult *result,
803              gpointer      user_data)
804 {
805   GDBusProxy *proxy;
806   GError *error;
807
808   error = NULL;
809   proxy = g_dbus_proxy_new_for_bus_finish (result, &error);
810   g_assert_no_error (error);
811
812   _g_assert_property_notify (proxy, "g-name-owner");
813
814   test_basic (proxy);
815   test_methods (proxy);
816   test_properties (proxy);
817   test_signals (proxy);
818   test_expected_interface (proxy);
819
820   kill_test_service (g_dbus_proxy_get_connection (proxy));
821   g_object_unref (proxy);
822   g_main_loop_quit (loop);
823 }
824
825 static gboolean
826 fail_test (gpointer user_data)
827 {
828   g_assert_not_reached ();
829 }
830
831 static void
832 test_async (void)
833 {
834   g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION,
835                             G_DBUS_PROXY_FLAGS_NONE,
836                             NULL,                      /* GDBusInterfaceInfo */
837                             "com.example.TestService", /* name */
838                             "/com/example/TestObject", /* object path */
839                             "com.example.Frob",        /* interface */
840                             NULL, /* GCancellable */
841                             proxy_ready,
842                             NULL);
843
844   /* this is safe; testserver will exit once the bus goes away */
845   g_assert (g_spawn_command_line_async (SRCDIR "/gdbus-testserver.py", NULL));
846
847   g_timeout_add (10000, fail_test, NULL);
848   g_main_loop_run (loop);
849 }
850
851 static void
852 test_no_properties (void)
853 {
854   GDBusProxy *proxy;
855   GError *error;
856
857   error = NULL;
858   proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
859                                          G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
860                                          NULL,                      /* GDBusInterfaceInfo */
861                                          "com.example.TestService", /* name */
862                                          "/com/example/TestObject", /* object path */
863                                          "com.example.Frob",        /* interface */
864                                          NULL, /* GCancellable */
865                                          &error);
866   g_assert_no_error (error);
867
868   test_properties (proxy);
869
870   g_object_unref (proxy);
871 }
872
873 static void
874 check_error (GObject      *source,
875              GAsyncResult *result,
876              gpointer      user_data)
877 {
878   GError *error = NULL;
879   GVariant *reply;
880
881   reply = g_dbus_proxy_call_finish (G_DBUS_PROXY (source), result, &error);
882   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_FAILED);
883   g_assert (reply == NULL);
884   g_error_free (error);
885
886   g_main_loop_quit (loop);
887 }
888
889 static void
890 test_wellknown_noauto (void)
891 {
892   GError *error = NULL;
893   GDBusProxy *proxy;
894
895   proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
896                                          G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
897                                          NULL, "some.name.that.does.not.exist",
898                                          "/", "some.interface", NULL, &error);
899   g_assert_no_error (error);
900   g_assert (proxy != NULL);
901
902   g_dbus_proxy_call (proxy, "method", NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, check_error, NULL);
903   g_timeout_add (10000, fail_test, NULL);
904   g_main_loop_run (loop);
905   g_object_unref (proxy);
906 }
907
908 int
909 main (int   argc,
910       char *argv[])
911 {
912   gint ret;
913   GDBusNodeInfo *introspection_data = NULL;
914
915   g_test_init (&argc, &argv, NULL);
916
917   introspection_data = g_dbus_node_info_new_for_xml (frob_dbus_interface_xml, NULL);
918   g_assert (introspection_data != NULL);
919   frob_dbus_interface_info = introspection_data->interfaces[0];
920
921   /* all the tests rely on a shared main loop */
922   loop = g_main_loop_new (NULL, FALSE);
923
924   session_bus_up ();
925
926   g_test_add_func ("/gdbus/proxy", test_proxy);
927   g_test_add_func ("/gdbus/proxy/no-properties", test_no_properties);
928   g_test_add_func ("/gdbus/proxy/wellknown-noauto", test_wellknown_noauto);
929   g_test_add_func ("/gdbus/proxy/async", test_async);
930
931   ret = g_test_run();
932
933   g_dbus_node_info_unref (introspection_data);
934
935   session_bus_down ();
936   return ret;
937 }