tests: use new g_test_build_filename() API
[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'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's definition */
587   "    <property name='i' type='u' access='readwrite'/>"
588   /* ::TestSignal2 is deliberately different from gdbus-testserver'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       g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING,
624                              "*Trying to set property y of type s but according to the expected interface the type is y*");
625       g_dbus_proxy_set_cached_property (proxy, "y", g_variant_new_string ("error_me_out!"));
626       g_test_assert_expected_messages ();
627     }
628
629   /* this should work, however (since the type is correct) */
630   g_dbus_proxy_set_cached_property (proxy, "y", g_variant_new_byte (42));
631
632   if (g_test_undefined ())
633     {
634       /* Try to get the value of a property where the type we expect is different from
635        * what we have in our cache (e.g. what the service returned)
636        */
637       g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING,
638                              "*Trying to get property i with type i but according to the expected interface the type is u*");
639       value = g_dbus_proxy_get_cached_property (proxy, "i");
640       g_test_assert_expected_messages ();
641     }
642
643   /* Even if a property does not exist in expected_interface, looking it
644    * up, or setting it, should never fail. Because it could be that the
645    * property has been added to the service but the GDBusInterfaceInfo*
646    * passed to g_dbus_proxy_set_interface_info() just haven't been updated.
647    *
648    * See https://bugzilla.gnome.org/show_bug.cgi?id=660886
649    */
650   value = g_dbus_proxy_get_cached_property (proxy, "d");
651   g_assert (value != NULL);
652   g_assert (g_variant_is_of_type (value, G_VARIANT_TYPE_DOUBLE));
653   g_assert_cmpfloat (g_variant_get_double (value), ==, 7.5);
654   g_variant_unref (value);
655   /* update it via the cached property... */
656   g_dbus_proxy_set_cached_property (proxy, "d", g_variant_new_double (75.0));
657   /* ... and finally check that it has changed */
658   value = g_dbus_proxy_get_cached_property (proxy, "d");
659   g_assert (value != NULL);
660   g_assert (g_variant_is_of_type (value, G_VARIANT_TYPE_DOUBLE));
661   g_assert_cmpfloat (g_variant_get_double (value), ==, 75.0);
662   g_variant_unref (value);
663   /* now update it via the D-Bus interface... */
664   error = NULL;
665   value = g_dbus_proxy_call_sync (proxy, "FrobSetProperty",
666                                   g_variant_new ("(sv)", "d", g_variant_new_double (85.0)),
667                                   G_DBUS_CALL_FLAGS_NONE,
668                                   -1, NULL, &error);
669   g_assert_no_error (error);
670   g_assert (value != NULL);
671   g_assert_cmpstr (g_variant_get_type_string (value), ==, "()");
672   g_variant_unref (value);
673   /* ...ensure we receive the ::PropertiesChanged signal... */
674   _g_assert_signal_received (proxy, "g-properties-changed");
675   /* ... and finally check that it has changed */
676   value = g_dbus_proxy_get_cached_property (proxy, "d");
677   g_assert (value != NULL);
678   g_assert (g_variant_is_of_type (value, G_VARIANT_TYPE_DOUBLE));
679   g_assert_cmpfloat (g_variant_get_double (value), ==, 85.0);
680   g_variant_unref (value);
681 }
682
683 static void
684 test_basic (GDBusProxy *proxy)
685 {
686   GDBusConnection *connection;
687   GDBusConnection *conn;
688   GDBusProxyFlags flags;
689   GDBusInterfaceInfo *info;
690   gchar *name;
691   gchar *path;
692   gchar *interface;
693   gint timeout;
694
695   connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
696
697   g_assert (g_dbus_proxy_get_connection (proxy) == connection);
698   g_assert (g_dbus_proxy_get_flags (proxy) == G_DBUS_PROXY_FLAGS_NONE);
699   g_assert (g_dbus_proxy_get_interface_info (proxy) == NULL);
700   g_assert_cmpstr (g_dbus_proxy_get_name (proxy), ==, "com.example.TestService");
701   g_assert_cmpstr (g_dbus_proxy_get_object_path (proxy), ==, "/com/example/TestObject");
702   g_assert_cmpstr (g_dbus_proxy_get_interface_name (proxy), ==, "com.example.Frob");
703   g_assert_cmpint (g_dbus_proxy_get_default_timeout (proxy), ==, -1);
704
705   g_object_get (proxy,
706                 "g-connection", &conn,
707                 "g-interface-info", &info,
708                 "g-flags", &flags,
709                 "g-name", &name,
710                 "g-object-path", &path,
711                 "g-interface-name", &interface,
712                 "g-default-timeout", &timeout,
713                 NULL);
714
715   g_assert (conn == connection);
716   g_assert (info == NULL);
717   g_assert_cmpint (flags, ==, G_DBUS_PROXY_FLAGS_NONE);
718   g_assert_cmpstr (name, ==, "com.example.TestService");
719   g_assert_cmpstr (path, ==, "/com/example/TestObject");
720   g_assert_cmpstr (interface, ==, "com.example.Frob");
721   g_assert_cmpint (timeout, ==, -1);
722
723   g_object_unref (conn);
724   g_free (name);
725   g_free (path);
726   g_free (interface);
727
728   g_object_unref (connection);
729 }
730
731 static void
732 kill_test_service (GDBusConnection *connection)
733 {
734 #ifdef G_OS_UNIX
735   guint pid;
736   GVariant *ret;
737   GError *error = NULL;
738   const gchar *name = "com.example.TestService";
739
740   ret = g_dbus_connection_call_sync (connection,
741                                      "org.freedesktop.DBus",
742                                      "/org/freedesktop/DBus",
743                                      "org.freedesktop.DBus",
744                                      "GetConnectionUnixProcessID",
745                                      g_variant_new ("(s)", name),
746                                      NULL,
747                                      G_DBUS_CALL_FLAGS_NONE,
748                                      -1,
749                                      NULL,
750                                      &error);
751   g_variant_get (ret, "(u)", &pid);
752   g_variant_unref (ret);
753   kill (pid, SIGTERM);
754 #else
755   g_warning ("Can't kill com.example.TestService");
756 #endif
757 }
758
759 static void
760 test_proxy (void)
761 {
762   GDBusProxy *proxy;
763   GDBusConnection *connection;
764   GError *error;
765   gchar *path;
766
767   error = NULL;
768   connection = g_bus_get_sync (G_BUS_TYPE_SESSION,
769                                NULL,
770                                &error);
771   g_assert_no_error (error);
772   error = NULL;
773   proxy = g_dbus_proxy_new_sync (connection,
774                                  G_DBUS_PROXY_FLAGS_NONE,
775                                  NULL,                      /* GDBusInterfaceInfo */
776                                  "com.example.TestService", /* name */
777                                  "/com/example/TestObject", /* object path */
778                                  "com.example.Frob",        /* interface */
779                                  NULL, /* GCancellable */
780                                  &error);
781   g_assert_no_error (error);
782
783   /* this is safe; testserver will exit once the bus goes away */
784   path = g_test_build_filename (G_TEST_BUILT, "gdbus-testserver", NULL);
785   g_assert (g_spawn_command_line_async (path, NULL));
786   g_free (path);
787
788   _g_assert_property_notify (proxy, "g-name-owner");
789
790   test_basic (proxy);
791   test_methods (proxy);
792   test_properties (proxy);
793   test_signals (proxy);
794   test_expected_interface (proxy);
795
796   g_object_unref (proxy);
797   kill_test_service (connection);
798   g_object_unref (connection);
799 }
800
801 /* ---------------------------------------------------------------------------------------------------- */
802
803 static void
804 proxy_ready (GObject      *source,
805              GAsyncResult *result,
806              gpointer      user_data)
807 {
808   GDBusProxy *proxy;
809   GError *error;
810
811   error = NULL;
812   proxy = g_dbus_proxy_new_for_bus_finish (result, &error);
813   g_assert_no_error (error);
814
815   _g_assert_property_notify (proxy, "g-name-owner");
816
817   test_basic (proxy);
818   test_methods (proxy);
819   test_properties (proxy);
820   test_signals (proxy);
821   test_expected_interface (proxy);
822
823   kill_test_service (g_dbus_proxy_get_connection (proxy));
824   g_object_unref (proxy);
825   g_main_loop_quit (loop);
826 }
827
828 static gboolean
829 fail_test (gpointer user_data)
830 {
831   g_assert_not_reached ();
832 }
833
834 static void
835 test_async (void)
836 {
837   gchar *path;
838
839   g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION,
840                             G_DBUS_PROXY_FLAGS_NONE,
841                             NULL,                      /* GDBusInterfaceInfo */
842                             "com.example.TestService", /* name */
843                             "/com/example/TestObject", /* object path */
844                             "com.example.Frob",        /* interface */
845                             NULL, /* GCancellable */
846                             proxy_ready,
847                             NULL);
848
849   /* this is safe; testserver will exit once the bus goes away */
850   path = g_test_build_filename (G_TEST_BUILT, "gdbus-testserver", NULL);
851   g_assert (g_spawn_command_line_async (path, NULL));
852   g_free (path);
853
854   g_timeout_add (10000, fail_test, NULL);
855   g_main_loop_run (loop);
856 }
857
858 static void
859 test_no_properties (void)
860 {
861   GDBusProxy *proxy;
862   GError *error;
863
864   error = NULL;
865   proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
866                                          G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
867                                          NULL,                      /* GDBusInterfaceInfo */
868                                          "com.example.TestService", /* name */
869                                          "/com/example/TestObject", /* object path */
870                                          "com.example.Frob",        /* interface */
871                                          NULL, /* GCancellable */
872                                          &error);
873   g_assert_no_error (error);
874
875   test_properties (proxy);
876
877   g_object_unref (proxy);
878 }
879
880 static void
881 check_error (GObject      *source,
882              GAsyncResult *result,
883              gpointer      user_data)
884 {
885   GError *error = NULL;
886   GVariant *reply;
887
888   reply = g_dbus_proxy_call_finish (G_DBUS_PROXY (source), result, &error);
889   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_FAILED);
890   g_assert (reply == NULL);
891   g_error_free (error);
892
893   g_main_loop_quit (loop);
894 }
895
896 static void
897 test_wellknown_noauto (void)
898 {
899   GError *error = NULL;
900   GDBusProxy *proxy;
901
902   proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
903                                          G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
904                                          NULL, "some.name.that.does.not.exist",
905                                          "/", "some.interface", NULL, &error);
906   g_assert_no_error (error);
907   g_assert (proxy != NULL);
908
909   g_dbus_proxy_call (proxy, "method", NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, check_error, NULL);
910   g_timeout_add (10000, fail_test, NULL);
911   g_main_loop_run (loop);
912   g_object_unref (proxy);
913 }
914
915 int
916 main (int   argc,
917       char *argv[])
918 {
919   gint ret;
920   GDBusNodeInfo *introspection_data = NULL;
921
922   g_test_init (&argc, &argv, NULL);
923
924   introspection_data = g_dbus_node_info_new_for_xml (frob_dbus_interface_xml, NULL);
925   g_assert (introspection_data != NULL);
926   frob_dbus_interface_info = introspection_data->interfaces[0];
927
928   /* all the tests rely on a shared main loop */
929   loop = g_main_loop_new (NULL, FALSE);
930
931   session_bus_up ();
932
933   g_test_add_func ("/gdbus/proxy", test_proxy);
934   g_test_add_func ("/gdbus/proxy/no-properties", test_no_properties);
935   g_test_add_func ("/gdbus/proxy/wellknown-noauto", test_wellknown_noauto);
936   g_test_add_func ("/gdbus/proxy/async", test_async);
937
938   ret = g_test_run();
939
940   g_dbus_node_info_unref (introspection_data);
941
942   session_bus_down ();
943   return ret;
944 }