2005-01-27 Havoc Pennington <hp@redhat.com>
[platform/upstream/dbus.git] / dbus / dbus-marshal-recursive-util.c
index 2879709..c607b04 100644 (file)
  *
  */
 
+#include <config.h>
+
+#ifdef DBUS_BUILD_TESTS
+
 #include "dbus-marshal-recursive.h"
 #include "dbus-marshal-basic.h"
 #include "dbus-internals.h"
+#include <string.h>
 
-#ifdef DBUS_BUILD_TESTS
-#include "dbus-test.h"
-#include "dbus-list.h"
-#include <stdio.h>
-#include <stdlib.h>
+static void
+basic_value_zero (DBusBasicValue *value)
+{
+
+#ifdef DBUS_HAVE_INT64
+  value->u64 = 0;
+#else
+  value->u64.first32 = 0;
+  value->u64.second32 = 0;
+#endif
+}
+
+static dbus_bool_t
+basic_value_equal (int             type,
+                   DBusBasicValue *lhs,
+                   DBusBasicValue *rhs)
+{
+  if (type == DBUS_TYPE_STRING ||
+      type == DBUS_TYPE_SIGNATURE ||
+      type == DBUS_TYPE_OBJECT_PATH)
+    {
+      return strcmp (lhs->str, rhs->str) == 0;
+    }
+  else
+    {
+#ifdef DBUS_HAVE_INT64
+      return lhs->u64 == rhs->u64;
+#else
+      return lhs->u64.first32 == rhs->u64.first32 &&
+        lhs->u64.second32 == rhs->u64.second32;
+#endif
+    }
+}
 
-static int
-first_type_in_signature (const DBusString *str,
-                         int               pos)
+static dbus_bool_t
+equal_values_helper (DBusTypeReader *lhs,
+                     DBusTypeReader *rhs)
 {
-  unsigned char t;
+  int lhs_type;
+  int rhs_type;
 
-  t = _dbus_string_get_byte (str, pos);
+  lhs_type = _dbus_type_reader_get_current_type (lhs);
+  rhs_type = _dbus_type_reader_get_current_type (rhs);
 
-  if (t == DBUS_STRUCT_BEGIN_CHAR)
-    return DBUS_TYPE_STRUCT;
+  if (lhs_type != rhs_type)
+    return FALSE;
+
+  if (lhs_type == DBUS_TYPE_INVALID)
+    return TRUE;
+
+  if (_dbus_type_is_basic (lhs_type))
+    {
+      DBusBasicValue lhs_value;
+      DBusBasicValue rhs_value;
+
+      basic_value_zero (&lhs_value);
+      basic_value_zero (&rhs_value);
+      
+      _dbus_type_reader_read_basic (lhs, &lhs_value);
+      _dbus_type_reader_read_basic (rhs, &rhs_value);
+
+      return basic_value_equal (lhs_type, &lhs_value, &rhs_value);
+    }
   else
-    return t;
+    {
+      DBusTypeReader lhs_sub;
+      DBusTypeReader rhs_sub;
+
+      _dbus_type_reader_recurse (lhs, &lhs_sub);
+      _dbus_type_reader_recurse (rhs, &rhs_sub);
+
+      return equal_values_helper (&lhs_sub, &rhs_sub);
+    }
+}
+
+/**
+ * See whether the two readers point to identical data blocks.
+ *
+ * @param lhs reader 1
+ * @param rhs reader 2
+ * @returns #TRUE if the data blocks have the same values
+ */
+dbus_bool_t
+_dbus_type_reader_equal_values (const DBusTypeReader *lhs,
+                                const DBusTypeReader *rhs)
+{
+  DBusTypeReader copy_lhs = *lhs;
+  DBusTypeReader copy_rhs = *rhs;
+
+  return equal_values_helper (&copy_lhs, &copy_rhs);
 }
 
+/* TESTS */
+#include "dbus-test.h"
+#include "dbus-list.h"
+#include <stdio.h>
+#include <stdlib.h>
+
 /* Whether to do the OOM stuff (only with other expensive tests) */
 #define TEST_OOM_HANDLING 0
 /* We do start offset 0 through 9, to get various alignment cases. Still this
@@ -313,6 +396,26 @@ struct TestTypeNodeContainerClass
  * and by merging read_value and set_value into one function
  * taking a flag argument.
  */
+static dbus_bool_t int16_write_value       (TestTypeNode   *node,
+                                            DataBlock      *block,
+                                            DBusTypeWriter *writer,
+                                            int             seed);
+static dbus_bool_t int16_read_value        (TestTypeNode   *node,
+                                            DBusTypeReader *reader,
+                                            int             seed);
+static dbus_bool_t int16_set_value         (TestTypeNode   *node,
+                                            DBusTypeReader *reader,
+                                            DBusTypeReader *realign_root,
+                                            int             seed);
+static dbus_bool_t int16_write_multi       (TestTypeNode   *node,
+                                            DataBlock      *block,
+                                            DBusTypeWriter *writer,
+                                            int             seed,
+                                            int             count);
+static dbus_bool_t int16_read_multi        (TestTypeNode   *node,
+                                            DBusTypeReader *reader,
+                                            int             seed,
+                                            int             count);
 static dbus_bool_t int32_write_value       (TestTypeNode   *node,
                                             DataBlock      *block,
                                             DBusTypeWriter *writer,
@@ -450,6 +553,34 @@ static dbus_bool_t variant_set_value       (TestTypeNode   *node,
 static void        container_destroy       (TestTypeNode   *node);
 
 
+static const TestTypeNodeClass int16_class = {
+  DBUS_TYPE_INT16,
+  sizeof (TestTypeNode),
+  0,
+  NULL,
+  NULL,
+  int16_write_value,
+  int16_read_value,
+  int16_set_value,
+  NULL,
+  int16_write_multi,
+  int16_read_multi
+};
+
+static const TestTypeNodeClass uint16_class = {
+  DBUS_TYPE_UINT16,
+  sizeof (TestTypeNode),
+  0,
+  NULL,
+  NULL,
+  int16_write_value, /* recycle from int16 */
+  int16_read_value,  /* recycle from int16 */
+  int16_set_value,   /* recycle from int16 */
+  NULL,
+  int16_write_multi, /* recycle from int16 */
+  int16_read_multi   /* recycle from int16 */
+};
+
 static const TestTypeNodeClass int32_class = {
   DBUS_TYPE_INT32,
   sizeof (TestTypeNode),
@@ -736,6 +867,8 @@ static const TestTypeNodeClass variant_class = {
 
 static const TestTypeNodeClass* const
 basic_nodes[] = {
+  &int16_class,
+  &uint16_class,
   &int32_class,
   &uint32_class,
   &int64_class,
@@ -1439,6 +1572,87 @@ value_generator (int *ip)
 }
 
 static void
+build_body (TestTypeNode **nodes,
+            int            n_nodes,
+            int            byte_order,
+            DBusString    *signature,
+            DBusString    *body)
+{
+  int i;
+  DataBlock block;
+  DBusTypeReader reader;
+  DBusTypeWriter writer;
+
+  i = 0;
+  while (i < n_nodes)
+    {
+      if (! node_build_signature (nodes[i], signature))
+        _dbus_assert_not_reached ("no memory");
+      
+      ++i;
+    }
+
+  if (!data_block_init (&block, byte_order, 0))
+    _dbus_assert_not_reached ("no memory");
+  
+  data_block_init_reader_writer (&block,
+                                 &reader, &writer);
+  
+  /* DBusTypeWriter assumes it's writing into an existing signature,
+   * so doesn't add nul on its own. We have to do that.
+   */
+  if (!_dbus_string_insert_byte (&block.signature,
+                                 0, '\0'))
+    _dbus_assert_not_reached ("no memory");
+
+  i = 0;
+  while (i < n_nodes)
+    {
+      if (!node_write_value (nodes[i], &block, &writer, i))
+        _dbus_assert_not_reached ("no memory");
+
+      ++i;
+    }
+
+  if (!_dbus_string_copy_len (&block.body, 0,
+                              _dbus_string_get_length (&block.body) - N_FENCE_BYTES,
+                              body, 0))
+    _dbus_assert_not_reached ("oom");
+
+  data_block_free (&block);  
+}
+
+dbus_bool_t
+dbus_internal_do_not_use_generate_bodies (int           sequence,
+                                          int           byte_order,
+                                          DBusString   *signature,
+                                          DBusString   *body)
+{
+  TestTypeNode *nodes[1];
+  int i;
+  int n_nodes;
+
+  nodes[0] = value_generator (&sequence);
+
+  if (nodes[0] == NULL)
+    return FALSE;
+
+  n_nodes = 1;
+  
+  build_body (nodes, n_nodes, byte_order, signature, body);
+
+
+  i = 0;
+  while (i < n_nodes)
+    {
+      node_destroy (nodes[i]);
+      ++i;
+    }
+  
+  return TRUE;
+}
+
+static void
 make_and_run_values_inside_container (const TestTypeNodeClass *container_klass,
                                       int                      n_nested)
 {
@@ -1814,6 +2028,142 @@ _dbus_marshal_recursive_test (void)
  */
 #define MAX_MULTI_COUNT 5
 
+#define SAMPLE_INT16           1234
+#define SAMPLE_INT16_ALTERNATE 6785
+static dbus_int16_t
+int16_from_seed (int seed)
+{
+  /* Generate an integer value that's predictable from seed.  We could
+   * just use seed itself, but that would only ever touch one byte of
+   * the int so would miss some kinds of bug.
+   */
+  dbus_int16_t v;
+
+  v = 42; /* just to quiet compiler afaik */
+  switch (seed % 5)
+    {
+    case 0:
+      v = SAMPLE_INT16;
+      break;
+    case 1:
+      v = SAMPLE_INT16_ALTERNATE;
+      break;
+    case 2:
+      v = -1;
+      break;
+    case 3:
+      v = _DBUS_INT16_MAX;
+      break;
+    case 4:
+      v = 1;
+      break;
+    }
+
+  if (seed > 1)
+    v *= seed; /* wraps around eventually, which is fine */
+
+  return v;
+}
+
+static dbus_bool_t
+int16_write_value (TestTypeNode   *node,
+                   DataBlock      *block,
+                   DBusTypeWriter *writer,
+                   int             seed)
+{
+  /* also used for uint16 */
+  dbus_int16_t v;
+
+  v = int16_from_seed (seed);
+
+  return _dbus_type_writer_write_basic (writer,
+                                        node->klass->typecode,
+                                        &v);
+}
+
+static dbus_bool_t
+int16_read_value (TestTypeNode   *node,
+                  DBusTypeReader *reader,
+                  int             seed)
+{
+  /* also used for uint16 */
+  dbus_int16_t v;
+
+  check_expected_type (reader, node->klass->typecode);
+
+  _dbus_type_reader_read_basic (reader,
+                                (dbus_int16_t*) &v);
+
+  _dbus_assert (v == int16_from_seed (seed));
+
+  return TRUE;
+}
+
+static dbus_bool_t
+int16_set_value (TestTypeNode   *node,
+                 DBusTypeReader *reader,
+                 DBusTypeReader *realign_root,
+                 int             seed)
+{
+  /* also used for uint16 */
+  dbus_int16_t v;
+
+  v = int16_from_seed (seed);
+
+  return _dbus_type_reader_set_basic (reader,
+                                      &v,
+                                      realign_root);
+}
+
+static dbus_bool_t
+int16_write_multi (TestTypeNode   *node,
+                   DataBlock      *block,
+                   DBusTypeWriter *writer,
+                   int             seed,
+                   int             count)
+{
+  /* also used for uint16 */
+  dbus_int16_t values[MAX_MULTI_COUNT];
+  dbus_int16_t *v_ARRAY_INT16 = values;
+  int i;
+
+  for (i = 0; i < count; ++i)
+    values[i] = int16_from_seed (seed + i);
+
+  return _dbus_type_writer_write_fixed_multi (writer,
+                                              node->klass->typecode,
+                                              &v_ARRAY_INT16, count);
+}
+
+static dbus_bool_t
+int16_read_multi (TestTypeNode   *node,
+                  DBusTypeReader *reader,
+                  int             seed,
+                  int             count)
+{
+  /* also used for uint16 */
+  dbus_int16_t *values;
+  int n_elements;
+  int i;
+
+  check_expected_type (reader, node->klass->typecode);
+
+  _dbus_type_reader_read_fixed_multi (reader,
+                                      &values,
+                                      &n_elements);
+
+  if (n_elements != count)
+    _dbus_warn ("got %d elements expected %d\n", n_elements, count);
+  _dbus_assert (n_elements == count);
+
+  for (i = 0; i < count; i++)
+    _dbus_assert (((int)_dbus_unpack_uint16 (reader->byte_order,
+                                             (const unsigned char*)values + (i * 2))) ==
+                  int16_from_seed (seed + i));
+
+  return TRUE;
+}
+
 
 #define SAMPLE_INT32           12345678
 #define SAMPLE_INT32_ALTERNATE 53781429
@@ -2319,18 +2669,26 @@ object_path_from_seed (char *buf,
 
   v = (unsigned char) ('A' + seed);
 
-  i = 0;
-  while (i + 1 < len)
+  if (len < 2)
     {
-      if (v < 'A' || v > 'z')
-        v = 'A';
-
-      buf[i] = '/';
-      ++i;
-      buf[i] = v;
-      ++i;
+      buf[0] = '/';
+      i = 1;
+    }
+  else
+    {
+      i = 0;
+      while (i + 1 < len)
+        {
+          if (v < 'A' || v > 'z')
+            v = 'A';
 
-      v += 1;
+          buf[i] = '/';
+          ++i;
+          buf[i] = v;
+          ++i;
+          
+          v += 1;
+        }
     }
 
   buf[i] = '\0';
@@ -2678,7 +3036,7 @@ array_write_value (TestTypeNode   *node,
                              &element_signature))
     goto oom;
 
-  element_type = first_type_in_signature (&element_signature, 0);
+  element_type = _dbus_first_type_in_signature (&element_signature, 0);
 
   if (!_dbus_type_writer_recurse (writer, DBUS_TYPE_ARRAY,
                                   &element_signature, 0,