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