mirror of
https://gitlab.freedesktop.org/dbus/dbus.git
synced 2026-02-03 19:30:42 +01:00
Add a test for marshalling and endian-swapping
Reviewed-by: Will Thompson <will.thompson@collabora.co.uk> Bug: https://bugs.freedesktop.org/show_bug.cgi?id=38120
This commit is contained in:
parent
983fd36264
commit
bf421f5a30
3 changed files with 229 additions and 0 deletions
1
test/.gitignore
vendored
1
test/.gitignore
vendored
|
|
@ -27,3 +27,4 @@ test-names
|
|||
test-loopback
|
||||
test-relay
|
||||
test-dbus-daemon
|
||||
test-marshal
|
||||
|
|
|
|||
|
|
@ -80,6 +80,7 @@ installable_tests = \
|
|||
test-corrupt \
|
||||
test-dbus-daemon \
|
||||
test-loopback \
|
||||
test-marshal \
|
||||
test-relay \
|
||||
$(NULL)
|
||||
|
||||
|
|
@ -120,6 +121,13 @@ test_dbus_daemon_LDADD = $(top_builddir)/dbus/libdbus-1.la \
|
|||
$(GLIB_LIBS) \
|
||||
$(DBUS_GLIB_LIBS)
|
||||
|
||||
test_marshal_SOURCES = marshal.c
|
||||
test_marshal_CPPFLAGS = $(GLIB_CFLAGS) $(DBUS_GLIB_CFLAGS)
|
||||
test_marshal_LDFLAGS = @R_DYNAMIC_LDFLAG@
|
||||
test_marshal_LDADD = $(top_builddir)/dbus/libdbus-1.la \
|
||||
$(GLIB_LIBS) \
|
||||
$(DBUS_GLIB_LIBS)
|
||||
|
||||
if DBUS_ENABLE_MODULAR_TESTS
|
||||
TESTS += $(installable_tests)
|
||||
installcheck_tests += $(installable_tests)
|
||||
|
|
|
|||
220
test/marshal.c
Normal file
220
test/marshal.c
Normal file
|
|
@ -0,0 +1,220 @@
|
|||
/* Simple sanity-check for D-Bus message serialization.
|
||||
*
|
||||
* Author: Simon McVittie <simon.mcvittie@collabora.co.uk>
|
||||
* Copyright © 2010-2011 Nokia Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include <dbus/dbus.h>
|
||||
#include <dbus/dbus-glib-lowlevel.h>
|
||||
|
||||
typedef struct {
|
||||
DBusError e;
|
||||
} Fixture;
|
||||
|
||||
static void
|
||||
assert_no_error (const DBusError *e)
|
||||
{
|
||||
if (G_UNLIKELY (dbus_error_is_set (e)))
|
||||
g_error ("expected success but got error: %s: %s", e->name, e->message);
|
||||
}
|
||||
|
||||
static void
|
||||
setup (Fixture *f,
|
||||
gconstpointer arg G_GNUC_UNUSED)
|
||||
{
|
||||
dbus_error_init (&f->e);
|
||||
}
|
||||
|
||||
/* this is meant to be obviously correct, not efficient! */
|
||||
static guint32
|
||||
get_uint32 (const gchar *blob,
|
||||
gsize offset,
|
||||
char endian)
|
||||
{
|
||||
if (endian == 'l')
|
||||
{
|
||||
return
|
||||
blob[offset] |
|
||||
(blob[offset + 1] << 8) |
|
||||
(blob[offset + 2] << 16) |
|
||||
(blob[offset + 3] << 24);
|
||||
}
|
||||
else if (endian == 'B')
|
||||
{
|
||||
return
|
||||
(blob[offset] << 24) |
|
||||
(blob[offset + 1] << 16) |
|
||||
(blob[offset + 2] << 8) |
|
||||
blob[offset + 3];
|
||||
}
|
||||
else
|
||||
{
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
}
|
||||
|
||||
#define BLOB_LENGTH (sizeof (le_blob) - 1)
|
||||
#define OFFSET_BODY_LENGTH (4)
|
||||
#define OFFSET_SERIAL (8)
|
||||
|
||||
const gchar le_blob[] =
|
||||
/* byte 0 */
|
||||
/* yyyyuu fixed headers */
|
||||
"l" /* little-endian */
|
||||
"\2" /* reply (which is the simplest message) */
|
||||
"\2" /* no auto-starting */
|
||||
"\1" /* D-Bus version = 1 */
|
||||
/* byte 4 */
|
||||
"\4\0\0\0" /* bytes in body = 4 */
|
||||
/* byte 8 */
|
||||
"\x78\x56\x34\x12" /* serial number = 0x12345678 */
|
||||
/* byte 12 */
|
||||
/* a(uv) variable headers start here */
|
||||
"\x0f\0\0\0" /* bytes in array of variable headers = 15 */
|
||||
/* pad to 8-byte boundary = nothing */
|
||||
/* byte 16 */
|
||||
"\5" /* in reply to: */
|
||||
"\1u\0" /* variant signature = u */
|
||||
/* pad to 4-byte boundary = nothing */
|
||||
"\x12\xef\xcd\xab" /* 0xabcdef12 */
|
||||
/* pad to 8-byte boundary = nothing */
|
||||
/* byte 24 */
|
||||
"\x08" /* signature: */
|
||||
"\1g\0" /* variant signature = g */
|
||||
"\1u\0" /* 1 byte, u, NUL (no alignment needed) */
|
||||
"\0" /* pad to 8-byte boundary for body */
|
||||
/* body; byte 32 */
|
||||
"\xef\xbe\xad\xde" /* 0xdeadbeef */
|
||||
;
|
||||
|
||||
const gchar be_blob[] =
|
||||
/* byte 0 */
|
||||
/* yyyyuu fixed headers */
|
||||
"B" /* big-endian */
|
||||
"\2" /* reply (which is the simplest message) */
|
||||
"\2" /* no auto-starting */
|
||||
"\1" /* D-Bus version = 1 */
|
||||
/* byte 4 */
|
||||
"\0\0\0\4" /* bytes in body = 4 */
|
||||
/* byte 8 */
|
||||
"\x12\x34\x56\x78" /* serial number = 0x12345678 */
|
||||
/* byte 12 */
|
||||
/* a(uv) variable headers start here */
|
||||
"\0\0\0\x0f" /* bytes in array of variable headers = 15 */
|
||||
/* pad to 8-byte boundary = nothing */
|
||||
/* byte 16 */
|
||||
"\5" /* in reply to: */
|
||||
"\1u\0" /* variant signature = u */
|
||||
/* pad to 4-byte boundary = nothing */
|
||||
"\xab\xcd\xef\x12" /* 0xabcdef12 */
|
||||
/* pad to 8-byte boundary = nothing */
|
||||
/* byte 24 */
|
||||
"\x08" /* signature: */
|
||||
"\1g\0" /* variant signature = g */
|
||||
"\1u\0" /* 1 byte, u, NUL (no alignment needed) */
|
||||
"\0" /* pad to 8-byte boundary for body */
|
||||
/* body; byte 32 */
|
||||
"\xde\xad\xbe\xef" /* 0xdeadbeef */
|
||||
;
|
||||
|
||||
static void
|
||||
test_endian (Fixture *f,
|
||||
gconstpointer arg)
|
||||
{
|
||||
const gchar *blob = arg;
|
||||
const gchar *native_blob;
|
||||
char *output;
|
||||
DBusMessage *m;
|
||||
int len;
|
||||
dbus_uint32_t u;
|
||||
dbus_bool_t ok;
|
||||
|
||||
g_assert_cmpuint ((guint) sizeof (le_blob), ==, (guint) sizeof (be_blob));
|
||||
|
||||
g_assert_cmpuint (get_uint32 (blob, OFFSET_BODY_LENGTH, blob[0]), ==, 4);
|
||||
g_assert_cmpuint (get_uint32 (blob, OFFSET_SERIAL, blob[0]), ==,
|
||||
0x12345678u);
|
||||
|
||||
len = dbus_message_demarshal_bytes_needed (blob, sizeof (le_blob));
|
||||
/* everything in the string except the implicit "\0" at the end is part of
|
||||
* the message */
|
||||
g_assert_cmpint (len, ==, BLOB_LENGTH);
|
||||
|
||||
m = dbus_message_demarshal (blob, sizeof (le_blob), &f->e);
|
||||
assert_no_error (&f->e);
|
||||
g_assert (m != NULL);
|
||||
|
||||
g_assert_cmpuint (dbus_message_get_serial (m), ==, 0x12345678u);
|
||||
g_assert_cmpuint (dbus_message_get_reply_serial (m), ==, 0xabcdef12u);
|
||||
g_assert_cmpstr (dbus_message_get_signature (m), ==, "u");
|
||||
|
||||
/* Implementation detail: appending to the message results in it being
|
||||
* byteswapped into compiler byte order, which exposed a bug in libdbus,
|
||||
* fd.o #38120. (If that changes, this test might not exercise that
|
||||
* particular bug but will still be valid.) */
|
||||
u = 0xdecafbadu;
|
||||
ok = dbus_message_append_args (m,
|
||||
DBUS_TYPE_UINT32, &u,
|
||||
DBUS_TYPE_INVALID);
|
||||
g_assert (ok);
|
||||
|
||||
dbus_message_marshal (m, &output, &len);
|
||||
|
||||
g_assert (output[0] == 'l' || output[0] == 'B');
|
||||
/* the single-byte fields are unaffected, even if the endianness was
|
||||
* swapped */
|
||||
g_assert_cmpint (output[1], ==, blob[1]);
|
||||
g_assert_cmpint (output[2], ==, blob[2]);
|
||||
g_assert_cmpint (output[3], ==, blob[3]);
|
||||
/* the length and serial are in the new endianness, the length has expanded
|
||||
* to 8, and the serial is correct */
|
||||
g_assert_cmpuint (get_uint32 (output, OFFSET_BODY_LENGTH, output[0]), ==, 8);
|
||||
g_assert_cmpuint (get_uint32 (output, OFFSET_SERIAL, output[0]), ==,
|
||||
0x12345678u);
|
||||
/* the second "u" in the signature replaced a padding byte, so only
|
||||
* the length of the body changed */
|
||||
g_assert_cmpint (len, ==, BLOB_LENGTH + 4);
|
||||
}
|
||||
|
||||
static void
|
||||
teardown (Fixture *f,
|
||||
gconstpointer arg G_GNUC_UNUSED)
|
||||
{
|
||||
dbus_error_free (&f->e);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc,
|
||||
char **argv)
|
||||
{
|
||||
g_test_init (&argc, &argv, NULL);
|
||||
|
||||
g_test_add ("/demarshal/le", Fixture, le_blob, setup, test_endian, teardown);
|
||||
g_test_add ("/demarshal/be", Fixture, be_blob, setup, test_endian, teardown);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue