]> git.ipfire.org Git - thirdparty/dbus.git/commitdiff
test: Add infrastructure to parse valid raw message blobs
authorSimon McVittie <smcv@collabora.com>
Fri, 30 Sep 2022 13:00:08 +0000 (14:00 +0100)
committerSimon McVittie <smcv@collabora.com>
Wed, 5 Oct 2022 09:24:42 +0000 (10:24 +0100)
Signed-off-by: Simon McVittie <smcv@collabora.com>
test/CMakeLists.txt
test/Makefile.am
test/data/meson.build
test/data/valid-messages/minimal.message-raw [new file with mode: 0644]
test/data/valid-messages/minimal.message-raw.hex [new file with mode: 0644]
test/internals/dbus-message-util.c
test/message.c

index cd338a07f9f1f2c4eeb032700b525af3b7ec23dc..5bd7915c29bf8d7a2d374dd787a518cbdaf048ad 100644 (file)
@@ -228,6 +228,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
index 659aead3774caa42aa3ae51041dceb2c70687f9b..54ec36934aa2dbc0b298788603c18d727cbe5e4c 100644 (file)
@@ -762,6 +762,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)
index 7ad99411e2ba485ec6b591ff12fea4b2fbb0e860..45fb6f910837fe585ee54aaffd25b858d707ab59 100644 (file)
@@ -110,6 +110,8 @@ data_to_install = [
     'valid-config-files/many-rules.conf',
     'valid-config-files/minimal.conf',
     'valid-config-files/standard-session-dirs.conf',
+    'valid-messages/minimal.message-raw',
+    'valid-messages/minimal.message-raw.hex',
 ]
 
 data_in_to_install = [
diff --git a/test/data/valid-messages/minimal.message-raw b/test/data/valid-messages/minimal.message-raw
new file mode 100644 (file)
index 0000000..3b5ee18
Binary files /dev/null and b/test/data/valid-messages/minimal.message-raw differ
diff --git a/test/data/valid-messages/minimal.message-raw.hex b/test/data/valid-messages/minimal.message-raw.hex
new file mode 100644 (file)
index 0000000..ab0534d
--- /dev/null
@@ -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
index df2ab8cfed50942219d2e9be234f2931576bfd7d..25237c8507fcbdd84b20900ac643efe772bcd460 100644 (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;
index 699302f46797b482a328dd4cd41fc9663d74e5bb..58966cb870dbd18dcce87e229d57057d4d366a25 100644 (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]);