test: Add infrastructure to parse valid raw message blobs

Signed-off-by: Simon McVittie <smcv@collabora.com>
(cherry picked from commit 7a2c13d21b)
[backport to 1.14.x: discard Meson build system updates]
This commit is contained in:
Simon McVittie 2022-09-30 14:00:08 +01:00
parent 3fb065b075
commit 7a8f3c2af9
6 changed files with 192 additions and 0 deletions

View file

@ -215,6 +215,7 @@ set(TESTDIRS
data/valid-config-files/session.d
data/valid-config-files-system
data/valid-config-files-system/system.d
data/valid-messages
data/valid-service-files
data/valid-service-files-system
data/invalid-config-files

View file

@ -725,6 +725,8 @@ static_data = \
data/valid-config-files/standard-session-dirs.conf \
data/valid-config-files-system/many-rules.conf \
data/valid-config-files-system/system.d/test.conf \
data/valid-messages/minimal.message-raw \
data/valid-messages/minimal.message-raw.hex \
$(NULL)
EXTRA_DIST += $(static_data)

Binary file not shown.

View file

@ -0,0 +1,25 @@
# Copyright 2022 Collabora Ltd.
# SPDX-License-Identifier: MIT
#
# To output as binary:
# sed -e 's/#.*//' test/data/valid-messages/minimal.message-raw.hex |
# xxd -p -r - test/data/valid-messages/minimal.message-raw
#
# This is a minimal valid message.
# Offset % 0x10:
# 0001 0203 0405 0607 0809 0a0b 0c0d 0e0f
6c # little-endian
02 # method call reply
00 # no flags
01 # major protocol version 1
0000 0000 # message body is 0 bytes
0200 0000 # serial number 2
0800 0000 # header is an array of 8 bytes of struct (yv)
05 # in reply to
01 # signature is 1 byte
7500 # "u" \0
0100 0000 # in reply to serial number 1
#sha1 06942854add9c4346a8b1c76a2b02e2e73abe72a

View file

@ -589,6 +589,10 @@ foreach_message_file (const char *test_data_dir,
_dbus_string_init_const (&test_directory, test_data_dir);
if (!process_test_subdir (&test_directory, "valid-messages",
DBUS_VALID, func, user_data))
goto failed;
if (!process_test_subdir (&test_directory, "invalid-messages",
DBUS_INVALID_FOR_UNKNOWN_REASON, func, user_data))
goto failed;

View file

@ -28,6 +28,7 @@
#include <string.h>
#include <glib.h>
#include <glib/gstdio.h>
#include <dbus/dbus.h>
#include "dbus/dbus-internals.h"
@ -179,6 +180,152 @@ out:
return !g_test_failed ();
}
static void iterate_fully (DBusMessageIter *iter,
int n_elements);
/* Iterate over @iter. If n_elements >= 0, then @iter is
* expected to yield exactly @n_elements elements. */
static void
iterate_fully (DBusMessageIter *iter,
int n_elements)
{
int i = 0;
while (TRUE)
{
int arg_type = dbus_message_iter_get_arg_type (iter);
dbus_bool_t should_have_next;
dbus_bool_t had_next;
if (arg_type == DBUS_TYPE_INVALID)
return; /* end of iteration */
if (dbus_type_is_container (arg_type))
{
DBusMessageIter sub = DBUS_MESSAGE_ITER_INIT_CLOSED;
int n_contained = -1;
switch (arg_type)
{
case DBUS_TYPE_ARRAY:
/* This is only allowed for arrays */
n_contained = dbus_message_iter_get_element_count (iter);
g_assert_cmpint (n_contained, >=, 0);
break;
case DBUS_TYPE_VARIANT:
n_contained = 1;
break;
case DBUS_TYPE_STRUCT:
break;
case DBUS_TYPE_DICT_ENTRY:
n_contained = 2;
break;
default:
g_assert_not_reached ();
}
dbus_message_iter_recurse (iter, &sub);
iterate_fully (&sub, n_contained);
}
else
{
DBusBasicValue value;
dbus_message_iter_get_basic (iter, &value);
if (arg_type == DBUS_TYPE_UNIX_FD && value.fd >= 0)
{
GError *error = NULL;
g_close (value.fd, &error);
g_assert_no_error (error);
}
}
should_have_next = dbus_message_iter_has_next (iter);
had_next = dbus_message_iter_next (iter);
g_assert_cmpint (had_next, ==, should_have_next);
g_assert_cmpint (had_next, ==,
(dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_INVALID));
i += 1;
}
if (n_elements >= 0)
g_assert_cmpuint (n_elements, ==, i);
}
/* Return TRUE if the right thing happens, but the right thing might include
* OOM. */
static dbus_bool_t
test_valid_message_blobs (void *message_name,
dbus_bool_t have_memory)
{
gchar *path = NULL;
gchar *contents = NULL;
gsize len = 0;
DBusMessage *m = NULL;
DBusMessageIter iter = DBUS_MESSAGE_ITER_INIT_CLOSED;
GError *error = NULL;
DBusError e = DBUS_ERROR_INIT;
dbus_bool_t ok = TRUE;
gchar *filename = NULL;
filename = g_strdup_printf ("%s.message-raw", (const char *) message_name);
path = g_test_build_filename (G_TEST_DIST, "data", "valid-messages",
filename, NULL);
g_file_get_contents (path, &contents, &len, &error);
g_assert_no_error (error);
g_assert_cmpuint (len, <, (gsize) INT_MAX);
m = dbus_message_demarshal (contents, (int) len, &e);
if (m == NULL)
{
if (dbus_error_has_name (&e, DBUS_ERROR_NO_MEMORY) && !have_memory)
{
g_test_message ("Out of memory (not a problem)");
goto out;
}
/* TODO: Validity checking sometimes returns InvalidArgs for OOM */
if (dbus_error_has_name (&e, DBUS_ERROR_INVALID_ARGS) &&
!have_memory &&
strstr (e.message, "Out of memory") != NULL)
{
g_test_message ("Out of memory (not a problem)");
goto out;
}
g_test_message ("Parsing %s reported unexpected error %s: %s",
path, e.name, e.message);
g_test_fail ();
ok = FALSE;
goto out;
}
g_test_message ("Successfully parsed %s", path);
test_assert_no_error (&e);
if (dbus_message_iter_init (m, &iter))
g_assert_cmpint (dbus_message_iter_get_arg_type (&iter), !=, DBUS_TYPE_INVALID);
else
g_assert_cmpint (dbus_message_iter_get_arg_type (&iter), ==, DBUS_TYPE_INVALID);
iterate_fully (&iter, -1);
out:
dbus_clear_message (&m);
dbus_error_free (&e);
g_free (path);
g_free (contents);
g_free (filename);
return ok;
}
/* Return TRUE if the right thing happens, but the right thing might include
* OOM. */
static dbus_bool_t
@ -365,6 +512,11 @@ add_oom_test (const gchar *name,
g_queue_push_tail (test_cases_to_free, test_case);
}
static const char *valid_messages[] =
{
"minimal",
};
static const char *invalid_messages[] =
{
"boolean-has-no-value",
@ -391,6 +543,14 @@ main (int argc,
add_oom_test ("/message/fd", test_fd, NULL);
add_oom_test ("/message/zero-iter", test_zero_iter, NULL);
for (i = 0; i < G_N_ELEMENTS (valid_messages); i++)
{
gchar *path = g_strdup_printf ("/message/valid/%s", valid_messages[i]);
add_oom_test (path, test_valid_message_blobs, valid_messages[i]);
g_free (path);
}
for (i = 0; i < G_N_ELEMENTS (invalid_messages); i++)
{
gchar *path = g_strdup_printf ("/message/invalid/%s", invalid_messages[i]);