gresourcefile: simplify path canonicalization
[glib.git] / gio / tests / gdbus-serialization.c
blobda28f1bc1879b99e12ad194646c20b75a1ee3274
1 /* GLib testing framework examples and tests
3 * Copyright (C) 2008-2010 Red Hat, Inc.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General
16 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 * Author: David Zeuthen <davidz@redhat.com>
21 #include <locale.h>
22 #include <gio/gio.h>
24 #include <string.h>
25 #include <unistd.h>
26 #include <dbus/dbus.h>
28 /* ---------------------------------------------------------------------------------------------------- */
30 static void
31 hexdump (const guchar *str, gsize len)
33 const guchar *data = (const guchar *) str;
34 guint n, m;
36 for (n = 0; n < len; n += 16)
38 g_printerr ("%04x: ", n);
40 for (m = n; m < n + 16; m++)
42 if (m > n && (m%4) == 0)
43 g_printerr (" ");
44 if (m < len)
45 g_printerr ("%02x ", data[m]);
46 else
47 g_printerr (" ");
50 g_printerr (" ");
52 for (m = n; m < len && m < n + 16; m++)
53 g_printerr ("%c", g_ascii_isprint (data[m]) ? data[m] : '.');
55 g_printerr ("\n");
59 /* ---------------------------------------------------------------------------------------------------- */
61 static gboolean
62 append_gv_to_dbus_iter (DBusMessageIter *iter,
63 GVariant *value,
64 GError **error)
66 const GVariantType *type;
68 type = g_variant_get_type (value);
69 if (g_variant_type_equal (type, G_VARIANT_TYPE_BOOLEAN))
71 dbus_bool_t v = g_variant_get_boolean (value);
72 dbus_message_iter_append_basic (iter, DBUS_TYPE_BOOLEAN, &v);
74 else if (g_variant_type_equal (type, G_VARIANT_TYPE_BYTE))
76 guint8 v = g_variant_get_byte (value);
77 dbus_message_iter_append_basic (iter, DBUS_TYPE_BYTE, &v);
79 else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT16))
81 gint16 v = g_variant_get_int16 (value);
82 dbus_message_iter_append_basic (iter, DBUS_TYPE_INT16, &v);
84 else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT16))
86 guint16 v = g_variant_get_uint16 (value);
87 dbus_message_iter_append_basic (iter, DBUS_TYPE_UINT16, &v);
89 else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT32))
91 gint32 v = g_variant_get_int32 (value);
92 dbus_message_iter_append_basic (iter, DBUS_TYPE_INT32, &v);
94 else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT32))
96 guint32 v = g_variant_get_uint32 (value);
97 dbus_message_iter_append_basic (iter, DBUS_TYPE_UINT32, &v);
99 else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT64))
101 gint64 v = g_variant_get_int64 (value);
102 dbus_message_iter_append_basic (iter, DBUS_TYPE_INT64, &v);
104 else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT64))
106 guint64 v = g_variant_get_uint64 (value);
107 dbus_message_iter_append_basic (iter, DBUS_TYPE_UINT64, &v);
109 else if (g_variant_type_equal (type, G_VARIANT_TYPE_DOUBLE))
111 gdouble v = g_variant_get_double (value);
112 dbus_message_iter_append_basic (iter, DBUS_TYPE_DOUBLE, &v);
114 else if (g_variant_type_equal (type, G_VARIANT_TYPE_STRING))
116 const gchar *v = g_variant_get_string (value, NULL);
117 dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &v);
119 else if (g_variant_type_equal (type, G_VARIANT_TYPE_OBJECT_PATH))
121 const gchar *v = g_variant_get_string (value, NULL);
122 dbus_message_iter_append_basic (iter, DBUS_TYPE_OBJECT_PATH, &v);
124 else if (g_variant_type_equal (type, G_VARIANT_TYPE_SIGNATURE))
126 const gchar *v = g_variant_get_string (value, NULL);
127 dbus_message_iter_append_basic (iter, DBUS_TYPE_SIGNATURE, &v);
129 else if (g_variant_type_is_variant (type))
131 DBusMessageIter sub;
132 GVariant *child;
134 child = g_variant_get_child_value (value, 0);
135 dbus_message_iter_open_container (iter, DBUS_TYPE_VARIANT,
136 g_variant_get_type_string (child),
137 &sub);
138 if (!append_gv_to_dbus_iter (&sub, child, error))
140 g_variant_unref (child);
141 goto fail;
143 dbus_message_iter_close_container (iter, &sub);
144 g_variant_unref (child);
146 else if (g_variant_type_is_array (type))
148 DBusMessageIter dbus_iter;
149 const gchar *type_string;
150 GVariantIter gv_iter;
151 GVariant *item;
153 type_string = g_variant_get_type_string (value);
154 type_string++; /* skip the 'a' */
156 dbus_message_iter_open_container (iter, DBUS_TYPE_ARRAY,
157 type_string, &dbus_iter);
158 g_variant_iter_init (&gv_iter, value);
160 while ((item = g_variant_iter_next_value (&gv_iter)))
162 if (!append_gv_to_dbus_iter (&dbus_iter, item, error))
164 goto fail;
168 dbus_message_iter_close_container (iter, &dbus_iter);
170 else if (g_variant_type_is_tuple (type))
172 DBusMessageIter dbus_iter;
173 GVariantIter gv_iter;
174 GVariant *item;
176 dbus_message_iter_open_container (iter, DBUS_TYPE_STRUCT,
177 NULL, &dbus_iter);
178 g_variant_iter_init (&gv_iter, value);
180 while ((item = g_variant_iter_next_value (&gv_iter)))
182 if (!append_gv_to_dbus_iter (&dbus_iter, item, error))
183 goto fail;
186 dbus_message_iter_close_container (iter, &dbus_iter);
188 else if (g_variant_type_is_dict_entry (type))
190 DBusMessageIter dbus_iter;
191 GVariant *key, *val;
193 dbus_message_iter_open_container (iter, DBUS_TYPE_DICT_ENTRY,
194 NULL, &dbus_iter);
195 key = g_variant_get_child_value (value, 0);
196 if (!append_gv_to_dbus_iter (&dbus_iter, key, error))
198 g_variant_unref (key);
199 goto fail;
201 g_variant_unref (key);
203 val = g_variant_get_child_value (value, 1);
204 if (!append_gv_to_dbus_iter (&dbus_iter, val, error))
206 g_variant_unref (val);
207 goto fail;
209 g_variant_unref (val);
211 dbus_message_iter_close_container (iter, &dbus_iter);
213 else
215 g_set_error (error,
216 G_IO_ERROR,
217 G_IO_ERROR_INVALID_ARGUMENT,
218 "Error serializing GVariant with type-string '%s' to a D-Bus message",
219 g_variant_get_type_string (value));
220 goto fail;
223 return TRUE;
225 fail:
226 return FALSE;
229 static gboolean
230 append_gv_to_dbus_message (DBusMessage *message,
231 GVariant *value,
232 GError **error)
234 gboolean ret;
235 guint n;
237 ret = FALSE;
239 if (value != NULL)
241 DBusMessageIter iter;
242 GVariantIter gv_iter;
243 GVariant *item;
245 dbus_message_iter_init_append (message, &iter);
247 g_variant_iter_init (&gv_iter, value);
248 n = 0;
249 while ((item = g_variant_iter_next_value (&gv_iter)))
251 if (!append_gv_to_dbus_iter (&iter, item, error))
253 g_prefix_error (error,
254 "Error encoding in-arg %d: ",
256 goto out;
258 n++;
262 ret = TRUE;
264 out:
265 return ret;
268 static void
269 print_gv_dbus_message (GVariant *value)
271 DBusMessage *message;
272 char *blob;
273 int blob_len;
274 GError *error;
276 message = dbus_message_new (DBUS_MESSAGE_TYPE_METHOD_CALL);
277 dbus_message_set_serial (message, 0x41);
278 dbus_message_set_path (message, "/foo/bar");
279 dbus_message_set_member (message, "Member");
281 error = NULL;
282 if (!append_gv_to_dbus_message (message, value, &error))
284 g_printerr ("Error printing GVariant as DBusMessage: %s", error->message);
285 g_error_free (error);
286 goto out;
289 dbus_message_marshal (message, &blob, &blob_len);
290 g_printerr ("\n");
291 hexdump ((guchar *) blob, blob_len);
292 out:
293 dbus_message_unref (message);
296 /* ---------------------------------------------------------------------------------------------------- */
298 static void
299 dbus_1_message_append (GString *s,
300 guint indent,
301 DBusMessageIter *iter)
303 gint arg_type;
304 DBusMessageIter sub;
306 g_string_append_printf (s, "%*s", indent, "");
308 arg_type = dbus_message_iter_get_arg_type (iter);
309 switch (arg_type)
311 case DBUS_TYPE_BOOLEAN:
313 dbus_bool_t value;
314 dbus_message_iter_get_basic (iter, &value);
315 g_string_append_printf (s, "bool: %s\n", value ? "true" : "false");
316 break;
319 case DBUS_TYPE_BYTE:
321 guchar value;
322 dbus_message_iter_get_basic (iter, &value);
323 g_string_append_printf (s, "byte: 0x%02x\n", (guint) value);
324 break;
327 case DBUS_TYPE_INT16:
329 gint16 value;
330 dbus_message_iter_get_basic (iter, &value);
331 g_string_append_printf (s, "int16: %" G_GINT16_FORMAT "\n", value);
332 break;
335 case DBUS_TYPE_UINT16:
337 guint16 value;
338 dbus_message_iter_get_basic (iter, &value);
339 g_string_append_printf (s, "uint16: %" G_GUINT16_FORMAT "\n", value);
340 break;
343 case DBUS_TYPE_INT32:
345 gint32 value;
346 dbus_message_iter_get_basic (iter, &value);
347 g_string_append_printf (s, "int32: %" G_GINT32_FORMAT "\n", value);
348 break;
351 case DBUS_TYPE_UINT32:
353 guint32 value;
354 dbus_message_iter_get_basic (iter, &value);
355 g_string_append_printf (s, "uint32: %" G_GUINT32_FORMAT "\n", value);
356 break;
359 case DBUS_TYPE_INT64:
361 gint64 value;
362 dbus_message_iter_get_basic (iter, &value);
363 g_string_append_printf (s, "int64: %" G_GINT64_FORMAT "\n", value);
364 break;
367 case DBUS_TYPE_UINT64:
369 guint64 value;
370 dbus_message_iter_get_basic (iter, &value);
371 g_string_append_printf (s, "uint64: %" G_GUINT64_FORMAT "\n", value);
372 break;
375 case DBUS_TYPE_DOUBLE:
377 gdouble value;
378 dbus_message_iter_get_basic (iter, &value);
379 g_string_append_printf (s, "double: %f\n", value);
380 break;
383 case DBUS_TYPE_STRING:
385 const gchar *value;
386 dbus_message_iter_get_basic (iter, &value);
387 g_string_append_printf (s, "string: '%s'\n", value);
388 break;
391 case DBUS_TYPE_OBJECT_PATH:
393 const gchar *value;
394 dbus_message_iter_get_basic (iter, &value);
395 g_string_append_printf (s, "object_path: '%s'\n", value);
396 break;
399 case DBUS_TYPE_SIGNATURE:
401 const gchar *value;
402 dbus_message_iter_get_basic (iter, &value);
403 g_string_append_printf (s, "signature: '%s'\n", value);
404 break;
407 #ifdef DBUS_TYPE_UNIX_FD
408 case DBUS_TYPE_UNIX_FD:
410 /* unfortunately there's currently no way to get just the
411 * protocol value, since dbus_message_iter_get_basic() wants
412 * to be 'helpful' and dup the fd for the user...
414 g_string_append (s, "unix-fd: (not extracted)\n");
415 break;
417 #endif
419 case DBUS_TYPE_VARIANT:
420 g_string_append_printf (s, "variant:\n");
421 dbus_message_iter_recurse (iter, &sub);
422 while (dbus_message_iter_get_arg_type (&sub))
424 dbus_1_message_append (s, indent + 2, &sub);
425 dbus_message_iter_next (&sub);
427 break;
429 case DBUS_TYPE_ARRAY:
430 g_string_append_printf (s, "array:\n");
431 dbus_message_iter_recurse (iter, &sub);
432 while (dbus_message_iter_get_arg_type (&sub))
434 dbus_1_message_append (s, indent + 2, &sub);
435 dbus_message_iter_next (&sub);
437 break;
439 case DBUS_TYPE_STRUCT:
440 g_string_append_printf (s, "struct:\n");
441 dbus_message_iter_recurse (iter, &sub);
442 while (dbus_message_iter_get_arg_type (&sub))
444 dbus_1_message_append (s, indent + 2, &sub);
445 dbus_message_iter_next (&sub);
447 break;
449 case DBUS_TYPE_DICT_ENTRY:
450 g_string_append_printf (s, "dict_entry:\n");
451 dbus_message_iter_recurse (iter, &sub);
452 while (dbus_message_iter_get_arg_type (&sub))
454 dbus_1_message_append (s, indent + 2, &sub);
455 dbus_message_iter_next (&sub);
457 break;
459 default:
460 g_printerr ("Error serializing D-Bus message to GVariant. Unsupported arg type '%c' (%d)",
461 arg_type,
462 arg_type);
463 g_assert_not_reached ();
464 break;
468 static gchar *
469 dbus_1_message_print (DBusMessage *message)
471 GString *s;
472 guint n;
473 DBusMessageIter iter;
475 s = g_string_new (NULL);
476 n = 0;
477 dbus_message_iter_init (message, &iter);
478 while (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INVALID)
480 g_string_append_printf (s, "value %d: ", n);
481 dbus_1_message_append (s, 2, &iter);
482 dbus_message_iter_next (&iter);
483 n++;
486 return g_string_free (s, FALSE);
489 /* ---------------------------------------------------------------------------------------------------- */
491 static gchar *
492 get_body_signature (GVariant *value)
494 const gchar *s;
495 gsize len;
496 gchar *ret;
498 if (value == NULL)
500 ret = g_strdup ("");
501 goto out;
504 s = g_variant_get_type_string (value);
505 len = strlen (s);
506 g_assert (len >= 2);
508 ret = g_strndup (s + 1, len - 2);
510 out:
511 return ret;
514 /* If @value is floating, this assumes ownership. */
515 static void
516 check_serialization (GVariant *value,
517 const gchar *expected_dbus_1_output)
519 guchar *blob;
520 gsize blob_size;
521 DBusMessage *dbus_1_message;
522 GDBusMessage *message;
523 GDBusMessage *recovered_message;
524 GError *error;
525 DBusError dbus_error;
526 gchar *s;
527 gchar *s1;
528 guint n;
530 message = g_dbus_message_new ();
531 g_dbus_message_set_body (message, value);
532 g_dbus_message_set_message_type (message, G_DBUS_MESSAGE_TYPE_METHOD_CALL);
533 g_dbus_message_set_serial (message, 0x41);
534 s = get_body_signature (value);
535 g_dbus_message_set_header (message, G_DBUS_MESSAGE_HEADER_FIELD_PATH, g_variant_new_object_path ("/foo/bar"));
536 g_dbus_message_set_header (message, G_DBUS_MESSAGE_HEADER_FIELD_MEMBER, g_variant_new_string ("Member"));
537 g_dbus_message_set_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE, g_variant_new_signature (s));
538 g_free (s);
540 /* First check that the serialization to the D-Bus wire format is correct - do this for both byte orders */
541 for (n = 0; n < 2; n++)
543 GDBusMessageByteOrder byte_order;
544 switch (n)
546 case 0:
547 byte_order = G_DBUS_MESSAGE_BYTE_ORDER_BIG_ENDIAN;
548 break;
549 case 1:
550 byte_order = G_DBUS_MESSAGE_BYTE_ORDER_LITTLE_ENDIAN;
551 break;
552 case 2:
553 g_assert_not_reached ();
554 break;
556 g_dbus_message_set_byte_order (message, byte_order);
558 error = NULL;
559 blob = g_dbus_message_to_blob (message,
560 &blob_size,
561 G_DBUS_CAPABILITY_FLAGS_NONE,
562 &error);
563 g_assert_no_error (error);
564 g_assert (blob != NULL);
566 switch (byte_order)
568 case G_DBUS_MESSAGE_BYTE_ORDER_BIG_ENDIAN:
569 g_assert_cmpint (blob[0], ==, 'B');
570 break;
571 case G_DBUS_MESSAGE_BYTE_ORDER_LITTLE_ENDIAN:
572 g_assert_cmpint (blob[0], ==, 'l');
573 break;
576 dbus_error_init (&dbus_error);
577 dbus_1_message = dbus_message_demarshal ((char *) blob, blob_size, &dbus_error);
578 if (dbus_error_is_set (&dbus_error))
580 g_printerr ("Error calling dbus_message_demarshal() on this blob: %s: %s\n",
581 dbus_error.name,
582 dbus_error.message);
583 hexdump (blob, blob_size);
584 dbus_error_free (&dbus_error);
586 s = g_variant_print (value, TRUE);
587 g_printerr ("\nThe blob was generated from the following GVariant value:\n%s\n\n", s);
588 g_free (s);
590 g_printerr ("If the blob was encoded using DBusMessageIter, the payload would have been:\n");
591 print_gv_dbus_message (value);
593 g_assert_not_reached ();
596 s = dbus_1_message_print (dbus_1_message);
597 dbus_message_unref (dbus_1_message);
599 g_assert_cmpstr (s, ==, expected_dbus_1_output);
600 g_free (s);
602 /* Then serialize back and check that the body is identical */
604 error = NULL;
605 recovered_message = g_dbus_message_new_from_blob (blob,
606 blob_size,
607 G_DBUS_CAPABILITY_FLAGS_NONE,
608 &error);
609 g_assert_no_error (error);
610 g_assert (recovered_message != NULL);
612 if (value == NULL)
614 g_assert (g_dbus_message_get_body (recovered_message) == NULL);
616 else
618 g_assert (g_dbus_message_get_body (recovered_message) != NULL);
619 if (!g_variant_equal (g_dbus_message_get_body (recovered_message), value))
621 s = g_variant_print (g_dbus_message_get_body (recovered_message), TRUE);
622 s1 = g_variant_print (value, TRUE);
623 g_printerr ("Recovered value:\n%s\ndoes not match given value\n%s\n",
625 s1);
626 g_free (s);
627 g_free (s1);
628 g_assert_not_reached ();
631 g_object_unref (recovered_message);
632 g_free (blob);
635 g_object_unref (message);
638 static void
639 message_serialize_basic (void)
641 check_serialization (NULL, "");
643 check_serialization (g_variant_new ("(sogybnqiuxtd)",
644 "this is a string",
645 "/this/is/a/path",
646 "sad",
648 TRUE,
649 -42,
650 60000,
651 -44,
652 100000,
653 -(G_GUINT64_CONSTANT(2)<<34),
654 G_GUINT64_CONSTANT(0xffffffffffffffff),
655 42.5),
656 "value 0: string: 'this is a string'\n"
657 "value 1: object_path: '/this/is/a/path'\n"
658 "value 2: signature: 'sad'\n"
659 "value 3: byte: 0x2a\n"
660 "value 4: bool: true\n"
661 "value 5: int16: -42\n"
662 "value 6: uint16: 60000\n"
663 "value 7: int32: -44\n"
664 "value 8: uint32: 100000\n"
665 "value 9: int64: -34359738368\n"
666 "value 10: uint64: 18446744073709551615\n"
667 "value 11: double: 42.500000\n");
670 /* ---------------------------------------------------------------------------------------------------- */
672 static void
673 message_serialize_complex (void)
675 GError *error;
676 GVariant *value;
678 error = NULL;
680 value = g_variant_parse (G_VARIANT_TYPE ("(aia{ss})"),
681 "([1, 2, 3], {'one': 'white', 'two': 'black'})",
682 NULL, NULL, &error);
683 g_assert_no_error (error);
684 g_assert (value != NULL);
685 check_serialization (value,
686 "value 0: array:\n"
687 " int32: 1\n"
688 " int32: 2\n"
689 " int32: 3\n"
690 "value 1: array:\n"
691 " dict_entry:\n"
692 " string: 'one'\n"
693 " string: 'white'\n"
694 " dict_entry:\n"
695 " string: 'two'\n"
696 " string: 'black'\n");
697 g_variant_unref (value);
699 value = g_variant_parse (G_VARIANT_TYPE ("(sa{sv}as)"),
700 "('01234567890123456', {}, ['Something'])",
701 NULL, NULL, &error);
702 g_assert_no_error (error);
703 g_assert (value != NULL);
704 check_serialization (value,
705 "value 0: string: '01234567890123456'\n"
706 "value 1: array:\n"
707 "value 2: array:\n"
708 " string: 'Something'\n");
709 g_variant_unref (value);
711 /* https://bugzilla.gnome.org/show_bug.cgi?id=621838 */
712 check_serialization (g_variant_new_parsed ("(@aay [], {'cwd': <'/home/davidz/Hacking/glib/gio/tests'>})"),
713 "value 0: array:\n"
714 "value 1: array:\n"
715 " dict_entry:\n"
716 " string: 'cwd'\n"
717 " variant:\n"
718 " string: '/home/davidz/Hacking/glib/gio/tests'\n");
720 #ifdef DBUS_TYPE_UNIX_FD
721 value = g_variant_parse (G_VARIANT_TYPE ("(hah)"),
722 "(42, [43, 44])",
723 NULL, NULL, &error);
724 g_assert_no_error (error);
725 g_assert (value != NULL);
726 /* about (not extracted), see comment in DBUS_TYPE_UNIX_FD case in
727 * dbus_1_message_append() above.
729 check_serialization (value,
730 "value 0: unix-fd: (not extracted)\n"
731 "value 1: array:\n"
732 " unix-fd: (not extracted)\n"
733 " unix-fd: (not extracted)\n");
734 g_variant_unref (value);
735 #endif
739 /* ---------------------------------------------------------------------------------------------------- */
741 static void
742 replace (char *blob,
743 gsize len,
744 const char *before,
745 const char *after)
747 gsize i;
748 gsize slen = strlen (before) + 1;
750 g_assert_cmpuint (strlen (before), ==, strlen (after));
751 g_assert_cmpuint (len, >=, slen);
753 for (i = 0; i < (len - slen + 1); i++)
755 if (memcmp (blob + i, before, slen) == 0)
756 memcpy (blob + i, after, slen);
760 static void
761 message_serialize_invalid (void)
763 guint n;
765 /* Other things we could check (note that GDBus _does_ check for all
766 * these things - we just don't have test-suit coverage for it)
768 * - array exceeding 64 MiB (2^26 bytes) - unfortunately libdbus-1 checks
769 * this, e.g.
771 * process 19620: arguments to dbus_message_iter_append_fixed_array() were incorrect,
772 * assertion "n_elements <= DBUS_MAXIMUM_ARRAY_LENGTH / _dbus_type_get_alignment (element_type)"
773 * failed in file dbus-message.c line 2344.
774 * This is normally a bug in some application using the D-Bus library.
775 * D-Bus not built with -rdynamic so unable to print a backtrace
776 * Aborted (core dumped)
778 * - message exceeding 128 MiB (2^27 bytes)
780 * - endianness, message type, flags, protocol version
783 for (n = 0; n < 3; n++)
785 GDBusMessage *message;
786 GError *error;
787 DBusMessage *dbus_message;
788 char *blob;
789 int blob_len;
790 /* these are in pairs with matching length */
791 const gchar *valid_utf8_str = "this is valid...";
792 const gchar *invalid_utf8_str = "this is invalid\xff";
793 const gchar *valid_signature = "a{sv}a{sv}a{sv}aiai";
794 const gchar *invalid_signature = "not valid signature";
795 const gchar *valid_object_path = "/this/is/a/valid/dbus/object/path";
796 const gchar *invalid_object_path = "/this/is/not a valid object path!";
798 dbus_message = dbus_message_new (DBUS_MESSAGE_TYPE_METHOD_CALL);
799 dbus_message_set_serial (dbus_message, 0x41);
800 dbus_message_set_path (dbus_message, "/foo/bar");
801 dbus_message_set_member (dbus_message, "Member");
802 switch (n)
804 case 0:
805 /* invalid UTF-8 */
806 dbus_message_append_args (dbus_message,
807 DBUS_TYPE_STRING, &valid_utf8_str,
808 DBUS_TYPE_INVALID);
809 break;
811 case 1:
812 /* invalid object path */
813 dbus_message_append_args (dbus_message,
814 DBUS_TYPE_OBJECT_PATH, &valid_object_path,
815 DBUS_TYPE_INVALID);
816 break;
818 case 2:
819 /* invalid signature */
820 dbus_message_append_args (dbus_message,
821 DBUS_TYPE_SIGNATURE, &valid_signature,
822 DBUS_TYPE_INVALID);
823 break;
825 default:
826 g_assert_not_reached ();
827 break;
829 dbus_message_marshal (dbus_message, &blob, &blob_len);
830 /* hack up the message to be invalid by replacing each valid string
831 * with its invalid counterpart */
832 replace (blob, blob_len, valid_utf8_str, invalid_utf8_str);
833 replace (blob, blob_len, valid_object_path, invalid_object_path);
834 replace (blob, blob_len, valid_signature, invalid_signature);
836 error = NULL;
837 message = g_dbus_message_new_from_blob ((guchar *) blob,
838 blob_len,
839 G_DBUS_CAPABILITY_FLAGS_NONE,
840 &error);
841 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
842 g_error_free (error);
843 g_assert (message == NULL);
845 dbus_free (blob);
846 dbus_message_unref (dbus_message);
851 /* ---------------------------------------------------------------------------------------------------- */
853 static void
854 message_serialize_header_checks (void)
856 GDBusMessage *message;
857 GDBusMessage *reply;
858 GError *error;
859 guchar *blob;
860 gsize blob_size;
863 * check we can't serialize messages with INVALID type
865 message = g_dbus_message_new ();
866 error = NULL;
867 blob = g_dbus_message_to_blob (message, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
868 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
869 g_assert_cmpstr (error->message, ==, "Cannot serialize message: type is INVALID");
870 g_error_free (error);
871 g_assert (blob == NULL);
872 g_object_unref (message);
875 * check we can't serialize signal messages with INTERFACE, PATH or MEMBER unset / set to reserved value
877 message = g_dbus_message_new_signal ("/the/path", "The.Interface", "TheMember");
878 /* ----- */
879 /* interface NULL => error */
880 g_dbus_message_set_interface (message, NULL);
881 error = NULL;
882 blob = g_dbus_message_to_blob (message, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
883 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
884 g_assert_cmpstr (error->message, ==, "Cannot serialize message: SIGNAL message: PATH, INTERFACE or MEMBER header field is missing");
885 g_error_free (error);
886 g_assert (blob == NULL);
887 /* interface reserved value => error */
888 g_dbus_message_set_interface (message, "org.freedesktop.DBus.Local");
889 error = NULL;
890 blob = g_dbus_message_to_blob (message, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
891 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
892 g_assert_cmpstr (error->message, ==, "Cannot serialize message: SIGNAL message: The INTERFACE header field is using the reserved value org.freedesktop.DBus.Local");
893 g_error_free (error);
894 g_assert (blob == NULL);
895 /* reset interface */
896 g_dbus_message_set_interface (message, "The.Interface");
897 /* ----- */
898 /* path NULL => error */
899 g_dbus_message_set_path (message, NULL);
900 error = NULL;
901 blob = g_dbus_message_to_blob (message, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
902 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
903 g_assert_cmpstr (error->message, ==, "Cannot serialize message: SIGNAL message: PATH, INTERFACE or MEMBER header field is missing");
904 g_error_free (error);
905 g_assert (blob == NULL);
906 /* path reserved value => error */
907 g_dbus_message_set_path (message, "/org/freedesktop/DBus/Local");
908 error = NULL;
909 blob = g_dbus_message_to_blob (message, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
910 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
911 g_assert_cmpstr (error->message, ==, "Cannot serialize message: SIGNAL message: The PATH header field is using the reserved value /org/freedesktop/DBus/Local");
912 g_error_free (error);
913 g_assert (blob == NULL);
914 /* reset path */
915 g_dbus_message_set_path (message, "/the/path");
916 /* ----- */
917 /* member NULL => error */
918 g_dbus_message_set_member (message, NULL);
919 error = NULL;
920 blob = g_dbus_message_to_blob (message, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
921 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
922 g_assert_cmpstr (error->message, ==, "Cannot serialize message: SIGNAL message: PATH, INTERFACE or MEMBER header field is missing");
923 g_error_free (error);
924 g_assert (blob == NULL);
925 /* reset member */
926 g_dbus_message_set_member (message, "TheMember");
927 /* ----- */
928 /* done */
929 g_object_unref (message);
932 * check that we can't serialize method call messages with PATH or MEMBER unset
934 message = g_dbus_message_new_method_call (NULL, "/the/path", NULL, "TheMember");
935 /* ----- */
936 /* path NULL => error */
937 g_dbus_message_set_path (message, NULL);
938 error = NULL;
939 blob = g_dbus_message_to_blob (message, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
940 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
941 g_assert_cmpstr (error->message, ==, "Cannot serialize message: METHOD_CALL message: PATH or MEMBER header field is missing");
942 g_error_free (error);
943 g_assert (blob == NULL);
944 /* reset path */
945 g_dbus_message_set_path (message, "/the/path");
946 /* ----- */
947 /* member NULL => error */
948 g_dbus_message_set_member (message, NULL);
949 error = NULL;
950 blob = g_dbus_message_to_blob (message, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
951 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
952 g_assert_cmpstr (error->message, ==, "Cannot serialize message: METHOD_CALL message: PATH or MEMBER header field is missing");
953 g_error_free (error);
954 g_assert (blob == NULL);
955 /* reset member */
956 g_dbus_message_set_member (message, "TheMember");
957 /* ----- */
958 /* done */
959 g_object_unref (message);
962 * check that we can't serialize method reply messages with REPLY_SERIAL unset
964 message = g_dbus_message_new_method_call (NULL, "/the/path", NULL, "TheMember");
965 g_dbus_message_set_serial (message, 42);
966 /* method reply */
967 reply = g_dbus_message_new_method_reply (message);
968 g_assert_cmpint (g_dbus_message_get_reply_serial (reply), ==, 42);
969 g_dbus_message_set_header (reply, G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL, NULL);
970 error = NULL;
971 blob = g_dbus_message_to_blob (reply, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
972 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
973 g_assert_cmpstr (error->message, ==, "Cannot serialize message: METHOD_RETURN message: REPLY_SERIAL header field is missing");
974 g_error_free (error);
975 g_assert (blob == NULL);
976 g_object_unref (reply);
977 /* method error - first nuke ERROR_NAME, then REPLY_SERIAL */
978 reply = g_dbus_message_new_method_error (message, "Some.Error.Name", "the message");
979 g_assert_cmpint (g_dbus_message_get_reply_serial (reply), ==, 42);
980 /* nuke ERROR_NAME */
981 g_dbus_message_set_error_name (reply, NULL);
982 error = NULL;
983 blob = g_dbus_message_to_blob (reply, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
984 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
985 g_assert_cmpstr (error->message, ==, "Cannot serialize message: ERROR message: REPLY_SERIAL or ERROR_NAME header field is missing");
986 g_error_free (error);
987 g_assert (blob == NULL);
988 /* reset ERROR_NAME */
989 g_dbus_message_set_error_name (reply, "Some.Error.Name");
990 /* nuke REPLY_SERIAL */
991 g_dbus_message_set_header (reply, G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL, NULL);
992 error = NULL;
993 blob = g_dbus_message_to_blob (reply, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, &error);
994 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
995 g_assert_cmpstr (error->message, ==, "Cannot serialize message: ERROR message: REPLY_SERIAL or ERROR_NAME header field is missing");
996 g_error_free (error);
997 g_assert (blob == NULL);
998 g_object_unref (reply);
999 g_object_unref (message);
1002 /* ---------------------------------------------------------------------------------------------------- */
1004 static void
1005 message_parse_empty_arrays_of_arrays (void)
1007 GVariant *body;
1008 GError *error = NULL;
1010 g_test_bug ("673612");
1011 /* These three-element array of empty arrays were previously read back as a
1012 * two-element array of empty arrays, due to sometimes erroneously skipping
1013 * four bytes to align for the eight-byte-aligned grandchild types (x and
1014 * dict_entry).
1016 body = g_variant_parse (G_VARIANT_TYPE ("(aaax)"),
1017 "([@aax [], [], []],)", NULL, NULL, &error);
1018 g_assert_no_error (error);
1019 check_serialization (body,
1020 "value 0: array:\n"
1021 " array:\n"
1022 " array:\n"
1023 " array:\n");
1024 g_variant_unref (body);
1026 body = g_variant_parse (G_VARIANT_TYPE ("(aaa{uu})"),
1027 "([@aa{uu} [], [], []],)", NULL, NULL, &error);
1028 g_assert_no_error (error);
1029 check_serialization (body,
1030 "value 0: array:\n"
1031 " array:\n"
1032 " array:\n"
1033 " array:\n");
1034 g_variant_unref (body);
1036 /* Due to the same bug, g_dbus_message_new_from_blob() would fail for this
1037 * message because it would try to read past the end of the string. Hence,
1038 * sending this to an application would make it fall off the bus. */
1039 body = g_variant_parse (G_VARIANT_TYPE ("(a(aa{sv}as))"),
1040 "([ ([], []),"
1041 " ([], []),"
1042 " ([], [])],)", NULL, NULL, &error);
1043 g_assert_no_error (error);
1044 check_serialization (body,
1045 "value 0: array:\n"
1046 " struct:\n"
1047 " array:\n"
1048 " array:\n"
1049 " struct:\n"
1050 " array:\n"
1051 " array:\n"
1052 " struct:\n"
1053 " array:\n"
1054 " array:\n");
1055 g_variant_unref (body);
1058 /* ---------------------------------------------------------------------------------------------------- */
1060 static void
1061 test_double_array (void)
1063 GVariantBuilder builder;
1064 GVariant *body;
1066 g_test_bug ("732754");
1068 g_variant_builder_init (&builder, G_VARIANT_TYPE ("ad"));
1069 g_variant_builder_add (&builder, "d", (gdouble)0.0);
1070 g_variant_builder_add (&builder, "d", (gdouble)8.0);
1071 g_variant_builder_add (&builder, "d", (gdouble)22.0);
1072 g_variant_builder_add (&builder, "d", (gdouble)0.0);
1073 body = g_variant_new ("(@ad)", g_variant_builder_end (&builder));
1074 check_serialization (body,
1075 "value 0: array:\n"
1076 " double: 0.000000\n"
1077 " double: 8.000000\n"
1078 " double: 22.000000\n"
1079 " double: 0.000000\n");
1082 /* ---------------------------------------------------------------------------------------------------- */
1085 main (int argc,
1086 char *argv[])
1088 setlocale (LC_ALL, "C");
1090 g_test_init (&argc, &argv, NULL);
1091 g_test_bug_base ("https://bugzilla.gnome.org/show_bug.cgi?id=");
1093 g_test_add_func ("/gdbus/message-serialize-basic", message_serialize_basic);
1094 g_test_add_func ("/gdbus/message-serialize-complex", message_serialize_complex);
1095 g_test_add_func ("/gdbus/message-serialize-invalid", message_serialize_invalid);
1096 g_test_add_func ("/gdbus/message-serialize-header-checks", message_serialize_header_checks);
1098 g_test_add_func ("/gdbus/message-parse-empty-arrays-of-arrays",
1099 message_parse_empty_arrays_of_arrays);
1101 g_test_add_func ("/gdbus/message-serialize/double-array", test_double_array);
1103 return g_test_run();