-/* -*- mode: C; c-file-style: "gnu" -*- */
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/* dbus-marshal-recursive-util.c Would be in dbus-marshal-recursive.c, but only used in bus/tests
*
* Copyright (C) 2004, 2005 Red Hat, Inc.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
+#include <config.h>
+
+#ifdef DBUS_ENABLE_EMBEDDED_TESTS
+
#include "dbus-marshal-recursive.h"
#include "dbus-marshal-basic.h"
+#include "dbus-signature.h"
#include "dbus-internals.h"
+#include <string.h>
+
+static void
+basic_value_zero (DBusBasicValue *value)
+{
+
+#ifdef DBUS_HAVE_INT64
+ value->u64 = 0;
+#else
+ value->eight.first32 = 0;
+ value->eight.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->eight.first32 == rhs->eight.first32 &&
+ lhs->eight.second32 == rhs->eight.second32;
+#endif
+ }
+}
+
+static dbus_bool_t
+equal_values_helper (DBusTypeReader *lhs,
+ DBusTypeReader *rhs)
+{
+ int lhs_type;
+ int rhs_type;
+
+ lhs_type = _dbus_type_reader_get_current_type (lhs);
+ rhs_type = _dbus_type_reader_get_current_type (rhs);
+
+ 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
+ {
+ 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 (©_lhs, ©_rhs);
+}
+
+/* TESTS */
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
-#ifdef DBUS_BUILD_TESTS
#include "dbus-test.h"
#include "dbus-list.h"
#include <stdio.h>
* 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,
int seed);
static dbus_bool_t struct_build_signature (TestTypeNode *node,
DBusString *str);
+static dbus_bool_t dict_write_value (TestTypeNode *node,
+ DataBlock *block,
+ DBusTypeWriter *writer,
+ int seed);
+static dbus_bool_t dict_read_value (TestTypeNode *node,
+ DBusTypeReader *reader,
+ int seed);
+static dbus_bool_t dict_set_value (TestTypeNode *node,
+ DBusTypeReader *reader,
+ DBusTypeReader *realign_root,
+ int seed);
+static dbus_bool_t dict_build_signature (TestTypeNode *node,
+ DBusString *str);
static dbus_bool_t array_write_value (TestTypeNode *node,
DataBlock *block,
DBusTypeWriter *writer,
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),
NULL
};
+static const TestTypeNodeClass dict_1_class = {
+ DBUS_TYPE_ARRAY, /* this is correct, a dict is an array of dict entry */
+ sizeof (TestTypeNodeContainer),
+ 1, /* number of entries */
+ NULL,
+ container_destroy,
+ dict_write_value,
+ dict_read_value,
+ dict_set_value,
+ dict_build_signature,
+ NULL,
+ NULL
+};
+
static dbus_bool_t arrays_write_fixed_in_blocks = FALSE;
static const TestTypeNodeClass array_0_class = {
static const TestTypeNodeClass* const
basic_nodes[] = {
+ &int16_class,
+ &uint16_class,
&int32_class,
&uint32_class,
&int64_class,
&struct_2_class,
&array_0_class,
&array_2_class,
- &variant_class
+ &variant_class,
+ &dict_1_class /* last since we want struct and array before it */
/* array_9_class is omitted on purpose, it's too slow;
* we only use it in one hardcoded test below
*/
if (!(* klass->construct) (node))
{
dbus_free (node);
- return FALSE;
+ return NULL;
}
}
DBusTypeReader *reader,
int seed)
{
- DBusTypeMark mark;
- DBusTypeReader restored;
-
- _dbus_type_reader_save_mark (reader, &mark);
+ /* DBusTypeReader restored; */
if (!(* node->klass->read_value) (node, reader, seed))
return FALSE;
- _dbus_type_reader_init_from_mark (&restored,
- reader->byte_order,
- reader->type_str,
- reader->value_str,
- &mark);
-
- if (!(* node->klass->read_value) (node, &restored, seed))
- return FALSE;
-
return TRUE;
}
DBusTypeReader reader;
DBusTypeWriter writer;
- _dbus_verbose ("%s\n", _DBUS_FUNCTION_NAME);
+ _dbus_verbose ("\n");
src = nid->block;
dbus_bool_t retval;
int sig_len;
- _dbus_verbose ("%s\n", _DBUS_FUNCTION_NAME);
+ _dbus_verbose ("\n");
retval = FALSE;
dbus_bool_t retval;
int i;
- _dbus_verbose ("%s\n", _DBUS_FUNCTION_NAME);
+ _dbus_verbose ("\n");
retval = FALSE;
dbus_bool_t retval;
int t;
- _dbus_verbose ("%s\n", _DBUS_FUNCTION_NAME);
+ _dbus_verbose ("\n");
retval = FALSE;
}
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)
{
node_destroy (node);
}
+ if (_dbus_getenv ("DBUS_TEST_SLOW") == NULL ||
+ atoi (_dbus_getenv ("DBUS_TEST_SLOW")) < 1)
+ {
+ fprintf (stderr, "skipping remaining marshal-recursive tests, "
+ "run with DBUS_TEST_SLOW=1 (or more) to enable\n");
+ goto out;
+ }
+
start_next_test ("Each container of each container of each value %d iterations\n",
N_CONTAINERS * N_CONTAINERS * N_VALUES);
for (i = 0; i < N_CONTAINERS; i++)
node_destroy (outer_container);
}
-#if 0
- /* This one takes a really long time, so comment it out for now */
+ /* This one takes a really long time (10 minutes on a Core2), so only enable
+ * it if you're really sure */
+ if (atoi (_dbus_getenv ("DBUS_TEST_SLOW")) < 2)
+ {
+ fprintf (stderr, "skipping really slow marshal-recursive test, "
+ "run with DBUS_TEST_SLOW=2 (or more) to enable\n");
+ goto out;
+ }
+
start_next_test ("Each value,value,value triplet combination as toplevel, in all orders %d iterations\n",
N_VALUES * N_VALUES * N_VALUES);
{
node_destroy (nodes[0]);
}
}
-#endif /* #if 0 expensive test */
+out:
fprintf (stderr, "%d total iterations of recursive marshaling tests\n",
n_iterations_completed_total);
fprintf (stderr, "each iteration ran at initial offsets 0 through %d in both big and little endian\n",
*/
#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 (((dbus_int16_t)_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
DBusTypeWriter *writer,
int seed)
{
- char buf[MAX_SAMPLE_STRING_LEN];
+ char buf[MAX_SAMPLE_STRING_LEN + 1]="";
const char *v_string = buf;
+
string_from_seed (buf, node->klass->subclass_detail,
seed);
int seed)
{
const char *v;
- char buf[MAX_SAMPLE_STRING_LEN];
+ char buf[MAX_SAMPLE_STRING_LEN + 1];
+ v = buf;
check_expected_type (reader, node->klass->typecode);
DBusTypeReader *realign_root,
int seed)
{
- char buf[MAX_SAMPLE_STRING_LEN];
+ char buf[MAX_SAMPLE_STRING_LEN + 1];
const char *v_string = buf;
string_from_seed (buf, node->klass->subclass_detail,
if (!_DBUS_DOUBLES_BITWISE_EQUAL (v, expected))
{
-#ifdef DBUS_HAVE_INT64
- _dbus_warn ("Expected double %g got %g\n bits = 0x%llx vs.\n bits = 0x%llx)\n",
+#ifdef DBUS_INT64_PRINTF_MODIFIER
+ _dbus_warn ("Expected double %g got %g\n bits = 0x%" DBUS_INT64_PRINTF_MODIFIER "x vs.\n bits = 0x%" DBUS_INT64_PRINTF_MODIFIER "x)\n",
expected, v,
*(dbus_uint64_t*)(char*)&expected,
*(dbus_uint64_t*)(char*)&v);
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';
DBusTypeWriter *writer,
int seed)
{
- char buf[MAX_SAMPLE_OBJECT_PATH_LEN];
+ char buf[MAX_SAMPLE_OBJECT_PATH_LEN + 1];
const char *v_string = buf;
object_path_from_seed (buf, seed);
int seed)
{
const char *v;
- char buf[MAX_SAMPLE_OBJECT_PATH_LEN];
+ char buf[MAX_SAMPLE_OBJECT_PATH_LEN + 1];
check_expected_type (reader, node->klass->typecode);
DBusTypeReader *realign_root,
int seed)
{
- char buf[MAX_SAMPLE_OBJECT_PATH_LEN];
+ char buf[MAX_SAMPLE_OBJECT_PATH_LEN + 1];
const char *v_string = buf;
object_path_from_seed (buf, seed);
signature_from_seed (char *buf,
int seed)
{
- int i;
- const char *s;
/* try to avoid ascending, descending, or alternating length to help find bugs */
const char *sample_signatures[] = {
"asax"
"a(ii)"
};
- s = sample_signatures[seed % _DBUS_N_ELEMENTS(sample_signatures)];
-
- for (i = 0; s[i]; i++)
- {
- buf[i] = s[i];
- }
- buf[i] = '\0';
+ strcpy (buf, sample_signatures[seed % _DBUS_N_ELEMENTS(sample_signatures)]);
}
static dbus_bool_t
DBusTypeWriter *writer,
int seed)
{
- char buf[MAX_SAMPLE_SIGNATURE_LEN];
+ char buf[MAX_SAMPLE_SIGNATURE_LEN + 1];
const char *v_string = buf;
signature_from_seed (buf, seed);
int seed)
{
const char *v;
- char buf[MAX_SAMPLE_SIGNATURE_LEN];
+ char buf[MAX_SAMPLE_SIGNATURE_LEN + 1];
check_expected_type (reader, node->klass->typecode);
DBusTypeReader *realign_root,
int seed)
{
- char buf[MAX_SAMPLE_SIGNATURE_LEN];
+ char buf[MAX_SAMPLE_SIGNATURE_LEN + 1];
const char *v_string = buf;
signature_from_seed (buf, seed);
goto oom;
if (arrays_write_fixed_in_blocks &&
- _dbus_type_is_fixed (element_type) &&
+ dbus_type_is_fixed (element_type) &&
child->klass->write_multi)
{
if (!node_write_multi (child, block, &sub, seed, n_copies))
_dbus_type_reader_recurse (reader, &sub);
if (realign_root == NULL && arrays_write_fixed_in_blocks &&
- _dbus_type_is_fixed (_dbus_type_reader_get_element_type (reader)) &&
+ dbus_type_is_fixed (_dbus_type_reader_get_element_type (reader)) &&
child->klass->read_multi)
{
if (!node_read_multi (child, &sub, seed, n_copies))
return variant_read_or_set_value (node, reader, realign_root, seed);
}
+static dbus_bool_t
+dict_write_value (TestTypeNode *node,
+ DataBlock *block,
+ DBusTypeWriter *writer,
+ int seed)
+{
+ TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
+ DataBlockState saved;
+ DBusTypeWriter sub;
+ DBusString entry_value_signature;
+ DBusString dict_entry_signature;
+ int i;
+ int n_entries;
+ TestTypeNode *child;
+
+ n_entries = node->klass->subclass_detail;
+
+ _dbus_assert (container->children != NULL);
+
+ data_block_save (block, &saved);
+
+ if (!_dbus_string_init (&entry_value_signature))
+ return FALSE;
+
+ if (!_dbus_string_init (&dict_entry_signature))
+ {
+ _dbus_string_free (&entry_value_signature);
+ return FALSE;
+ }
+
+ child = _dbus_list_get_first (&container->children);
+
+ if (!node_build_signature (child,
+ &entry_value_signature))
+ goto oom;
+
+ if (!_dbus_string_append (&dict_entry_signature,
+ DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+ DBUS_TYPE_INT32_AS_STRING))
+ goto oom;
+
+ if (!_dbus_string_copy (&entry_value_signature, 0,
+ &dict_entry_signature,
+ _dbus_string_get_length (&dict_entry_signature)))
+ goto oom;
+
+ if (!_dbus_string_append_byte (&dict_entry_signature,
+ DBUS_DICT_ENTRY_END_CHAR))
+ goto oom;
+
+ if (!_dbus_type_writer_recurse (writer, DBUS_TYPE_ARRAY,
+ &dict_entry_signature, 0,
+ &sub))
+ goto oom;
+
+ i = 0;
+ while (i < n_entries)
+ {
+ DBusTypeWriter entry_sub;
+ dbus_int32_t key;
+
+ if (!_dbus_type_writer_recurse (&sub, DBUS_TYPE_DICT_ENTRY,
+ NULL, 0,
+ &entry_sub))
+ goto oom;
+
+ key = int32_from_seed (seed + i);
+
+ if (!_dbus_type_writer_write_basic (&entry_sub,
+ DBUS_TYPE_INT32,
+ &key))
+ goto oom;
+
+ if (!node_write_value (child, block, &entry_sub, seed + i))
+ goto oom;
+
+ if (!_dbus_type_writer_unrecurse (&sub, &entry_sub))
+ goto oom;
+
+ ++i;
+ }
+
+ if (!_dbus_type_writer_unrecurse (writer, &sub))
+ goto oom;
+
+ _dbus_string_free (&entry_value_signature);
+ _dbus_string_free (&dict_entry_signature);
+ return TRUE;
+
+ oom:
+ data_block_restore (block, &saved);
+ _dbus_string_free (&entry_value_signature);
+ _dbus_string_free (&dict_entry_signature);
+ return FALSE;
+}
+
+static dbus_bool_t
+dict_read_or_set_value (TestTypeNode *node,
+ DBusTypeReader *reader,
+ DBusTypeReader *realign_root,
+ int seed)
+{
+ TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
+ DBusTypeReader sub;
+ int i;
+ int n_entries;
+ TestTypeNode *child;
+
+ n_entries = node->klass->subclass_detail;
+
+ check_expected_type (reader, DBUS_TYPE_ARRAY);
+
+ child = _dbus_list_get_first (&container->children);
+
+ if (n_entries > 0)
+ {
+ _dbus_type_reader_recurse (reader, &sub);
+
+ check_expected_type (&sub, DBUS_TYPE_DICT_ENTRY);
+
+ i = 0;
+ while (i < n_entries)
+ {
+ DBusTypeReader entry_sub;
+
+ check_expected_type (&sub, DBUS_TYPE_DICT_ENTRY);
+
+ _dbus_type_reader_recurse (&sub, &entry_sub);
+
+ if (realign_root == NULL)
+ {
+ dbus_int32_t v;
+
+ check_expected_type (&entry_sub, DBUS_TYPE_INT32);
+
+ _dbus_type_reader_read_basic (&entry_sub,
+ (dbus_int32_t*) &v);
+
+ _dbus_assert (v == int32_from_seed (seed + i));
+
+ NEXT_EXPECTING_TRUE (&entry_sub);
+
+ if (!node_read_value (child, &entry_sub, seed + i))
+ return FALSE;
+
+ NEXT_EXPECTING_FALSE (&entry_sub);
+ }
+ else
+ {
+ dbus_int32_t v;
+
+ v = int32_from_seed (seed + i);
+
+ if (!_dbus_type_reader_set_basic (&entry_sub,
+ &v,
+ realign_root))
+ return FALSE;
+
+ NEXT_EXPECTING_TRUE (&entry_sub);
+
+ if (!node_set_value (child, &entry_sub, realign_root, seed + i))
+ return FALSE;
+
+ NEXT_EXPECTING_FALSE (&entry_sub);
+ }
+
+ if (i == (n_entries - 1))
+ NEXT_EXPECTING_FALSE (&sub);
+ else
+ NEXT_EXPECTING_TRUE (&sub);
+
+ ++i;
+ }
+ }
+
+ return TRUE;
+}
+
+static dbus_bool_t
+dict_read_value (TestTypeNode *node,
+ DBusTypeReader *reader,
+ int seed)
+{
+ return dict_read_or_set_value (node, reader, NULL, seed);
+}
+
+static dbus_bool_t
+dict_set_value (TestTypeNode *node,
+ DBusTypeReader *reader,
+ DBusTypeReader *realign_root,
+ int seed)
+{
+ return dict_read_or_set_value (node, reader, realign_root, seed);
+}
+
+static dbus_bool_t
+dict_build_signature (TestTypeNode *node,
+ DBusString *str)
+{
+ TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
+ int orig_len;
+
+ orig_len = _dbus_string_get_length (str);
+
+ if (!_dbus_string_append_byte (str, DBUS_TYPE_ARRAY))
+ goto oom;
+
+ if (!_dbus_string_append (str, DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING DBUS_TYPE_INT32_AS_STRING))
+ goto oom;
+
+ if (!node_build_signature (_dbus_list_get_first (&container->children),
+ str))
+ goto oom;
+
+ if (!_dbus_string_append_byte (str, DBUS_DICT_ENTRY_END_CHAR))
+ goto oom;
+
+ return TRUE;
+
+ oom:
+ _dbus_string_set_length (str, orig_len);
+ return FALSE;
+}
+
static void
container_destroy (TestTypeNode *node)
{
}
}
-#endif /* DBUS_BUILD_TESTS */
+#endif /* !DOXYGEN_SHOULD_SKIP_THIS */
+
+#endif /* DBUS_ENABLE_EMBEDDED_TESTS */