*
*/
+#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 (©_lhs, ©_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
* 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,
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),
static const TestTypeNodeClass* const
basic_nodes[] = {
+ &int16_class,
+ &uint16_class,
&int32_class,
&uint32_class,
&int64_class,
}
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)
{
*/
#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
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';
&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,