1 /* Simple sanity-check for D-Bus message serialization.
3 * Author: Simon McVittie <simon.mcvittie@collabora.co.uk>
4 * Copyright © 2010-2011 Nokia Corporation
6 * Permission is hereby granted, free of charge, to any person
7 * obtaining a copy of this software and associated documentation files
8 * (the "Software"), to deal in the Software without restriction,
9 * including without limitation the rights to use, copy, modify, merge,
10 * publish, distribute, sublicense, and/or sell copies of the Software,
11 * and to permit persons to whom the Software is furnished to do so,
12 * subject to the following conditions:
14 * The above copyright notice and this permission notice shall be
15 * included in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
21 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
22 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32 #include <dbus/dbus.h>
34 #include "test-utils-glib.h"
41 assert_no_error (const DBusError *e)
43 if (G_UNLIKELY (dbus_error_is_set (e)))
44 g_error ("expected success but got error: %s: %s", e->name, e->message);
49 gconstpointer arg G_GNUC_UNUSED)
51 dbus_error_init (&f->e);
54 /* this is meant to be obviously correct, not efficient! */
56 get_uint32 (const gchar *blob,
64 (blob[offset + 1] << 8) |
65 (blob[offset + 2] << 16) |
66 (blob[offset + 3] << 24);
68 else if (endian == 'B')
71 (blob[offset] << 24) |
72 (blob[offset + 1] << 16) |
73 (blob[offset + 2] << 8) |
78 g_assert_not_reached ();
82 #define BLOB_LENGTH (sizeof (le_blob) - 1)
83 #define OFFSET_BODY_LENGTH (4)
84 #define OFFSET_SERIAL (8)
86 const gchar le_blob[] =
88 /* yyyyuu fixed headers */
89 "l" /* little-endian */
90 "\2" /* reply (which is the simplest message) */
91 "\2" /* no auto-starting */
92 "\1" /* D-Bus version = 1 */
94 "\4\0\0\0" /* bytes in body = 4 */
96 "\x78\x56\x34\x12" /* serial number = 0x12345678 */
98 /* a(uv) variable headers start here */
99 "\x0f\0\0\0" /* bytes in array of variable headers = 15 */
100 /* pad to 8-byte boundary = nothing */
102 "\5" /* in reply to: */
103 "\1u\0" /* variant signature = u */
104 /* pad to 4-byte boundary = nothing */
105 "\x12\xef\xcd\xab" /* 0xabcdef12 */
106 /* pad to 8-byte boundary = nothing */
108 "\x08" /* signature: */
109 "\1g\0" /* variant signature = g */
110 "\1u\0" /* 1 byte, u, NUL (no alignment needed) */
111 "\0" /* pad to 8-byte boundary for body */
113 "\xef\xbe\xad\xde" /* 0xdeadbeef */
116 const gchar be_blob[] =
118 /* yyyyuu fixed headers */
120 "\2" /* reply (which is the simplest message) */
121 "\2" /* no auto-starting */
122 "\1" /* D-Bus version = 1 */
124 "\0\0\0\4" /* bytes in body = 4 */
126 "\x12\x34\x56\x78" /* serial number = 0x12345678 */
128 /* a(uv) variable headers start here */
129 "\0\0\0\x0f" /* bytes in array of variable headers = 15 */
130 /* pad to 8-byte boundary = nothing */
132 "\5" /* in reply to: */
133 "\1u\0" /* variant signature = u */
134 /* pad to 4-byte boundary = nothing */
135 "\xab\xcd\xef\x12" /* 0xabcdef12 */
136 /* pad to 8-byte boundary = nothing */
138 "\x08" /* signature: */
139 "\1g\0" /* variant signature = g */
140 "\1u\0" /* 1 byte, u, NUL (no alignment needed) */
141 "\0" /* pad to 8-byte boundary for body */
143 "\xde\xad\xbe\xef" /* 0xdeadbeef */
147 test_endian (Fixture *f,
150 const gchar *blob = arg;
157 g_assert_cmpuint ((guint) sizeof (le_blob), ==, (guint) sizeof (be_blob));
159 g_assert_cmpuint (get_uint32 (blob, OFFSET_BODY_LENGTH, blob[0]), ==, 4);
160 g_assert_cmpuint (get_uint32 (blob, OFFSET_SERIAL, blob[0]), ==,
163 len = dbus_message_demarshal_bytes_needed (blob, sizeof (le_blob));
164 /* everything in the string except the implicit "\0" at the end is part of
166 g_assert_cmpint (len, ==, BLOB_LENGTH);
168 m = dbus_message_demarshal (blob, sizeof (le_blob), &f->e);
169 assert_no_error (&f->e);
170 g_assert (m != NULL);
172 g_assert_cmpuint (dbus_message_get_serial (m), ==, 0x12345678u);
173 g_assert_cmpuint (dbus_message_get_reply_serial (m), ==, 0xabcdef12u);
174 g_assert_cmpstr (dbus_message_get_signature (m), ==, "u");
176 /* Implementation detail: appending to the message results in it being
177 * byteswapped into compiler byte order, which exposed a bug in libdbus,
178 * fd.o #38120. (If that changes, this test might not exercise that
179 * particular bug but will still be valid.) */
181 ok = dbus_message_append_args (m,
182 DBUS_TYPE_UINT32, &u,
186 dbus_message_marshal (m, &output, &len);
188 g_assert (output[0] == 'l' || output[0] == 'B');
189 /* the single-byte fields are unaffected, even if the endianness was
191 g_assert_cmpint (output[1], ==, blob[1]);
192 g_assert_cmpint (output[2], ==, blob[2]);
193 g_assert_cmpint (output[3], ==, blob[3]);
194 /* the length and serial are in the new endianness, the length has expanded
195 * to 8, and the serial is correct */
196 g_assert_cmpuint (get_uint32 (output, OFFSET_BODY_LENGTH, output[0]), ==, 8);
197 g_assert_cmpuint (get_uint32 (output, OFFSET_SERIAL, output[0]), ==,
199 /* the second "u" in the signature replaced a padding byte, so only
200 * the length of the body changed */
201 g_assert_cmpint (len, ==, BLOB_LENGTH + 4);
205 test_needed (Fixture *f,
208 const gchar *blob = arg;
210 /* We need at least 16 bytes to know how long the message is - that's just
211 * a fact of the D-Bus protocol. */
213 dbus_message_demarshal_bytes_needed (blob, 0), ==, 0);
215 dbus_message_demarshal_bytes_needed (blob, 15), ==, 0);
216 /* This is enough that we should be able to tell how much we need. */
218 dbus_message_demarshal_bytes_needed (blob, 16), ==, BLOB_LENGTH);
219 /* The header is 32 bytes long (here), so that's another interesting
222 dbus_message_demarshal_bytes_needed (blob, 31), ==, BLOB_LENGTH);
224 dbus_message_demarshal_bytes_needed (blob, 32), ==, BLOB_LENGTH);
226 dbus_message_demarshal_bytes_needed (blob, 33), ==, BLOB_LENGTH);
228 dbus_message_demarshal_bytes_needed (blob, BLOB_LENGTH - 1), ==,
231 dbus_message_demarshal_bytes_needed (blob, BLOB_LENGTH), ==,
234 dbus_message_demarshal_bytes_needed (blob, sizeof (be_blob)), ==,
239 teardown (Fixture *f,
240 gconstpointer arg G_GNUC_UNUSED)
242 dbus_error_free (&f->e);
250 char *aligned_le_blob;
251 char *aligned_be_blob;
253 test_init (&argc, &argv);
255 /* We have to pass in a buffer that's at least "default aligned",
256 * i.e. on GNU systems to 8 or 16. The linker may have only given
257 * us byte-alignment for the char[] static variables.
259 aligned_le_blob = g_malloc (sizeof (le_blob));
260 memcpy (aligned_le_blob, le_blob, sizeof (le_blob));
261 aligned_be_blob = g_malloc (sizeof (be_blob));
262 memcpy (aligned_be_blob, be_blob, sizeof (be_blob));
264 g_test_add ("/demarshal/le", Fixture, aligned_le_blob, setup, test_endian, teardown);
265 g_test_add ("/demarshal/be", Fixture, aligned_be_blob, setup, test_endian, teardown);
266 g_test_add ("/demarshal/needed/le", Fixture, aligned_le_blob, setup, test_needed,
268 g_test_add ("/demarshal/needed/be", Fixture, aligned_be_blob, setup, test_needed,
272 g_free (aligned_le_blob);
273 g_free (aligned_be_blob);