diff options
author | Simon McVittie <smcv@collabora.com> | 2022-09-30 14:00:08 +0100 |
---|---|---|
committer | Simon McVittie <smcv@collabora.com> | 2022-10-05 10:47:18 +0100 |
commit | 5d2b764d1fcbc1992b9fd5e532cd925bd3d69e6b (patch) | |
tree | 458f73dd1f86615f7a48e542f028d74c0ad3158d | |
parent | 51a5bbf9074855b0f4a353ed309938b196c13525 (diff) |
test: Add infrastructure to parse valid raw message blobs
Signed-off-by: Simon McVittie <smcv@collabora.com>
(cherry picked from commit 7a2c13d21be702c7b5b7288fb82a60adc5bd7378)
[backport to 1.14.x: discard Meson build system updates]
(cherry picked from commit 7a8f3c2af94063e4994a9780d00d700aa0ea8aef)
[backport to 1.12.x: resolve conflicts in build system; adjust signature
of test function for absence of 39ef65d0 in this branch]
-rw-r--r-- | test/Makefile.am | 2 | ||||
-rw-r--r-- | test/data/valid-messages/minimal.message-raw | bin | 0 -> 24 bytes | |||
-rw-r--r-- | test/data/valid-messages/minimal.message-raw.hex | 25 | ||||
-rw-r--r-- | test/message.c | 158 |
4 files changed, 185 insertions, 0 deletions
diff --git a/test/Makefile.am b/test/Makefile.am index 168ffaea..99d6485b 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -552,6 +552,8 @@ static_data = \ data/valid-messages/dict.message \ data/valid-messages/emptiness.message \ data/valid-messages/lots-of-arguments.message \ + data/valid-messages/minimal.message-raw \ + data/valid-messages/minimal.message-raw.hex \ data/valid-messages/no-padding.message \ data/valid-messages/opposite-endian.message \ data/valid-messages/recursive-types.message \ diff --git a/test/data/valid-messages/minimal.message-raw b/test/data/valid-messages/minimal.message-raw Binary files differnew file mode 100644 index 00000000..3b5ee188 --- /dev/null +++ b/test/data/valid-messages/minimal.message-raw diff --git a/test/data/valid-messages/minimal.message-raw.hex b/test/data/valid-messages/minimal.message-raw.hex new file mode 100644 index 00000000..ab0534da --- /dev/null +++ b/test/data/valid-messages/minimal.message-raw.hex @@ -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 diff --git a/test/message.c b/test/message.c index 618528bb..887935dd 100644 --- a/test/message.c +++ b/test/message.c @@ -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,150 @@ 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) +{ + 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)) + { + 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) && + 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 +510,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 +541,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]); |