* @addtogroup DBusMarshal
* @{
*/
-#define RECURSIVE_MARSHAL_TRACE 1
+#define RECURSIVE_MARSHAL_TRACE 0
+
+static void
+apply_and_free_fixups (DBusList **fixups,
+ DBusTypeReader *reader)
+{
+ DBusList *link;
+
+#if RECURSIVE_MARSHAL_TRACE
+ if (*fixups)
+ _dbus_verbose (" %d FIXUPS to apply\n",
+ _dbus_list_get_length (fixups));
+#endif
+
+ link = _dbus_list_get_first_link (fixups);
+ while (link != NULL)
+ {
+ DBusList *next;
+
+ next = _dbus_list_get_next_link (fixups, link);
+
+ if (reader)
+ {
+ DBusArrayLenFixup *f;
+
+ f = link->data;
+
+#if RECURSIVE_MARSHAL_TRACE
+ _dbus_verbose (" applying FIXUP to reader %p at pos %d new_len = %d old len %d\n",
+ reader, f->len_pos_in_reader, f->new_len,
+ _dbus_marshal_read_uint32 (reader->value_str,
+ f->len_pos_in_reader,
+ reader->byte_order, NULL));
+#endif
+
+ _dbus_marshal_set_uint32 ((DBusString*) reader->value_str,
+ f->len_pos_in_reader,
+ f->new_len,
+ reader->byte_order);
+ }
+
+ dbus_free (link->data);
+ _dbus_list_free_link (link);
+
+ link = next;
+ }
+
+ *fixups = NULL;
+}
struct DBusTypeReaderClass
{
sub->array_len_offset = 7;
}
+/* array_len_offset is the offset back from start_pos to end of the len */
+#define ARRAY_READER_LEN_POS(reader) \
+ ((reader)->u.array.start_pos - ((int)(reader)->array_len_offset) - 4)
+
static int
array_reader_get_array_len (const DBusTypeReader *reader)
{
dbus_uint32_t array_len;
int len_pos;
- /* array_len_offset is the offset back from start_pos to end of the len */
- len_pos = reader->u.array.start_pos - ((int)reader->array_len_offset) - 4;
+ len_pos = ARRAY_READER_LEN_POS (reader);
_dbus_marshal_read_basic (reader->value_str,
len_pos,
end_pos = reader->u.array.start_pos + array_reader_get_array_len (reader);
+#if RECURSIVE_MARSHAL_TRACE
+ _dbus_verbose (" reader %p array next START start_pos = %d end_pos = %d value_pos = %d current_type = %s\n",
+ reader,
+ reader->u.array.start_pos,
+ end_pos, reader->value_pos,
+ _dbus_type_to_string (current_type));
+#endif
+
_dbus_assert (reader->value_pos < end_pos);
_dbus_assert (reader->value_pos >= reader->u.array.start_pos);
break;
}
+#if RECURSIVE_MARSHAL_TRACE
+ _dbus_verbose (" reader %p array next END start_pos = %d end_pos = %d value_pos = %d current_type = %s\n",
+ reader,
+ reader->u.array.start_pos,
+ end_pos, reader->value_pos,
+ _dbus_type_to_string (current_type));
+#endif
+
_dbus_assert (reader->value_pos <= end_pos);
if (reader->value_pos == end_pos)
}
+
/* In the variable-length case, we have to fix alignment after we insert.
* The strategy is as follows:
*
* - copy the new string back to the original
* string, replacing the relevant part of the
* original string
+ * - now any arrays in the original string that
+ * contained the replaced string may have the
+ * wrong length; so we have to fix that
*/
static dbus_bool_t
reader_set_basic_variable_length (DBusTypeReader *reader,
int padding;
DBusTypeWriter writer;
DBusTypeReader realign_reader;
+ DBusList *fixups;
_dbus_assert (realign_root != NULL);
&replacement,
_dbus_string_get_length (&replacement));
- if (!_dbus_type_writer_write_reader (&writer,
- &realign_reader,
- reader))
+ fixups = NULL;
+ if (!_dbus_type_writer_write_reader_partial (&writer,
+ &realign_reader,
+ reader,
+ padding,
+ _dbus_string_get_length (&replacement) - padding,
+ &fixups))
goto out;
+#if RECURSIVE_MARSHAL_TRACE
+ _dbus_verbose ("REPLACEMENT at padding %d len %d\n", padding,
+ _dbus_string_get_length (&replacement) - padding);
+ _dbus_verbose_bytes_of_string (&replacement, padding,
+ _dbus_string_get_length (&replacement) - padding);
+ _dbus_verbose ("TO BE REPLACED at value_pos = %d (align pad %d) len %d\n",
+ reader->value_pos, (int) (8 - _DBUS_ALIGN_OFFSET (reader->value_pos, 8)),
+ realign_reader.value_pos - reader->value_pos);
+ _dbus_verbose_bytes_of_string (reader->value_str,
+ reader->value_pos,
+ realign_reader.value_pos - reader->value_pos);
+#endif
+
/* Move the replacement into position
* (realign_reader should now be at the end of the block to be replaced)
*/
realign_reader.value_pos - reader->value_pos))
goto out;
+ /* Process our fixups now that we can't have an OOM error */
+ apply_and_free_fixups (&fixups, reader);
+
retval = TRUE;
out:
current_type = _dbus_type_reader_get_current_type (reader);
+#if RECURSIVE_MARSHAL_TRACE
+ _dbus_verbose (" type reader %p set basic type_pos = %d value_pos = %d remaining sig '%s' realign_root = %p with value_pos %d current_type = %s\n",
+ reader, reader->type_pos, reader->value_pos,
+ _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0),
+ realign_root,
+ realign_root ? realign_root->value_pos : -1,
+ _dbus_type_to_string (current_type));
+#endif
+
_dbus_assert (_dbus_type_is_basic (current_type));
if (_dbus_type_length_varies (current_type))
sub->value_pos = aligned;
}
- sub->u.array.start_pos = sub->value_pos;
-
- _dbus_assert (sub->u.array.start_pos == sub->value_pos);
- _dbus_assert (sub->u.array.len_pos < sub->u.array.start_pos);
#if RECURSIVE_MARSHAL_TRACE
_dbus_verbose (" type writer %p recurse array done remaining sig '%s' array start_pos = %d len_pos = %d\n", sub,
sub->u.array.start_pos, sub->u.array.len_pos);
#endif
}
+ else
+ {
+ /* not enabled, so we won't write the len_pos; set it to -1 to so indicate */
+ sub->u.array.len_pos = -1;
+ }
+
+ sub->u.array.start_pos = sub->value_pos;
+ _dbus_assert (sub->u.array.start_pos == sub->value_pos);
+ _dbus_assert (sub->u.array.len_pos < sub->u.array.start_pos);
return TRUE;
}
sub);
}
+static int
+writer_get_array_len (DBusTypeWriter *writer)
+{
+ _dbus_assert (writer->container_type == DBUS_TYPE_ARRAY);
+ return writer->value_pos - writer->u.array.start_pos;
+}
+
dbus_bool_t
_dbus_type_writer_unrecurse (DBusTypeWriter *writer,
DBusTypeWriter *sub)
{
- _dbus_assert (sub->type_pos > 0); /* can't be recursed if this fails */
-
/* type_pos_is_expectation never gets unset once set, or we'd get all hosed */
_dbus_assert (!writer->type_pos_is_expectation ||
(writer->type_pos_is_expectation && sub->type_pos_is_expectation));
}
else if (sub->container_type == DBUS_TYPE_ARRAY)
{
- if (sub->enabled)
+ if (sub->u.array.len_pos >= 0) /* len_pos == -1 if we weren't enabled when we passed it */
{
dbus_uint32_t len;
/* Set the array length */
- len = sub->value_pos - sub->u.array.start_pos;
+ len = writer_get_array_len (sub);
_dbus_marshal_set_uint32 (sub->value_str,
sub->u.array.len_pos,
len,
#if RECURSIVE_MARSHAL_TRACE
_dbus_verbose (" filled in sub array len to %u at len_pos %d\n",
len, sub->u.array.len_pos);
+#endif
+ }
+#if RECURSIVE_MARSHAL_TRACE
+ else
+ {
+ _dbus_verbose (" not filling in sub array len because we were disabled when we passed the len\n");
}
#endif
}
}
-/**
- * Iterate through all values in the given reader, writing a copy of
- * each value to the writer. The reader will be moved forward to its
- * end position.
- *
- * If a reader start_after is provided, it should be a reader for the
- * same data as the reader to be written. Only values occurring after
- * the value pointed to by start_after will be written to the writer.
- *
- * @param writer the writer to copy to
- * @param reader the reader to copy from
- * @param start_after #NULL or a reader showing where to start
- */
-dbus_bool_t
-_dbus_type_writer_write_reader (DBusTypeWriter *writer,
- DBusTypeReader *reader,
- const DBusTypeReader *start_after)
+static void
+enable_if_after (DBusTypeWriter *writer,
+ DBusTypeReader *reader,
+ const DBusTypeReader *start_after)
{
- DBusTypeWriter orig;
- int orig_type_len;
- int orig_value_len;
- int new_bytes;
- int current_type;
- int orig_enabled;
+ if (start_after)
+ {
+ if (!writer->enabled && _dbus_type_reader_greater_than (reader, start_after))
+ {
+ _dbus_type_writer_set_enabled (writer, TRUE);
+#if RECURSIVE_MARSHAL_TRACE
+ _dbus_verbose ("ENABLING writer %p because reader at value_pos %d is after reader at value_pos %d\n",
+ writer, reader->value_pos, start_after->value_pos);
+#endif
+ }
- orig = *writer;
- orig_type_len = _dbus_string_get_length (writer->type_str);
- orig_value_len = _dbus_string_get_length (writer->value_str);
- orig_enabled = writer->enabled;
+ _dbus_assert ((!writer->enabled && !_dbus_type_reader_greater_than (reader, start_after)) ||
+ (writer->enabled && _dbus_type_reader_greater_than (reader, start_after)));
+ }
+}
- if (start_after)
+static dbus_bool_t
+append_fixup (DBusList **fixups,
+ const DBusArrayLenFixup *fixup)
+{
+ DBusArrayLenFixup *f;
+
+ f = dbus_new (DBusArrayLenFixup, 1);
+ if (f == NULL)
+ return FALSE;
+
+ *f = *fixup;
+
+ if (!_dbus_list_append (fixups, f))
{
- _dbus_type_writer_set_enabled (writer,
- _dbus_type_reader_greater_than (reader, start_after));
+ dbus_free (f);
+ return FALSE;
}
+ _dbus_assert (f->len_pos_in_reader == fixup->len_pos_in_reader);
+ _dbus_assert (f->new_len == fixup->new_len);
+
+ return TRUE;
+}
+
+/* This loop is trivial if you ignore all the start_after nonsense,
+ * so if you're trying to figure it out, start by ignoring that
+ */
+static dbus_bool_t
+writer_write_reader_helper (DBusTypeWriter *writer,
+ DBusTypeReader *reader,
+ const DBusTypeReader *start_after,
+ int start_after_new_pos,
+ int start_after_new_len,
+ DBusList **fixups)
+{
+ int current_type;
+
while ((current_type = _dbus_type_reader_get_current_type (reader)) != DBUS_TYPE_INVALID)
{
if (_dbus_type_is_container (current_type))
const DBusString *sig_str;
int sig_start;
int sig_len;
+ dbus_bool_t enabled_at_recurse;
+ dbus_bool_t past_start_after;
+ int reader_array_len_pos;
+ int reader_array_start_pos;
_dbus_type_reader_recurse (reader, &subreader);
+ if (current_type == DBUS_TYPE_ARRAY)
+ {
+ reader_array_len_pos = ARRAY_READER_LEN_POS (&subreader);
+ reader_array_start_pos = subreader.u.array.start_pos;
+ }
+ else
+ {
+ /* quiet gcc */
+ reader_array_len_pos = -1;
+ reader_array_start_pos = -1;
+ }
+
_dbus_type_reader_get_signature (&subreader, &sig_str,
&sig_start, &sig_len);
+ enable_if_after (writer, &subreader, start_after);
+ enabled_at_recurse = writer->enabled;
if (!_dbus_type_writer_recurse_contained_len (writer, current_type,
sig_str, sig_start, sig_len,
&subwriter))
goto oom;
- if (!_dbus_type_writer_write_reader (&subwriter, &subreader, start_after))
+ if (!writer_write_reader_helper (&subwriter, &subreader, start_after,
+ start_after_new_pos, start_after_new_len,
+ fixups))
goto oom;
+ enable_if_after (writer, &subreader, start_after);
+ past_start_after = writer->enabled;
if (!_dbus_type_writer_unrecurse (writer, &subwriter))
goto oom;
+
+ /* If we weren't enabled when we recursed, we didn't
+ * write an array len; if we passed start_after
+ * somewhere inside the array, then we need to generate
+ * a fixup.
+ */
+ if (start_after != NULL &&
+ !enabled_at_recurse && past_start_after &&
+ current_type == DBUS_TYPE_ARRAY &&
+ fixups != NULL)
+ {
+ DBusArrayLenFixup fixup;
+ int bytes_written_after_start_after;
+ int bytes_before_start_after;
+ int old_len;
+
+ /* this is moderately unkosher since we already unrecursed,
+ * but it works as long as unrecurse doesn't break us on purpose
+ */
+ bytes_written_after_start_after = writer_get_array_len (&subwriter);
+
+ bytes_before_start_after =
+ start_after->value_pos - reader_array_start_pos;
+
+ fixup.len_pos_in_reader = reader_array_len_pos;
+ fixup.new_len =
+ bytes_before_start_after +
+ start_after_new_len +
+ bytes_written_after_start_after;
+
+ old_len = _dbus_marshal_read_uint32 (reader->value_str,
+ fixup.len_pos_in_reader,
+ reader->byte_order, NULL);
+
+ if (old_len != fixup.new_len && !append_fixup (fixups, &fixup))
+ goto oom;
+
+#if RECURSIVE_MARSHAL_TRACE
+ _dbus_verbose ("Generated fixup len_pos_in_reader = %d new_len = %d reader_array_start_pos = %d start_after->value_pos = %d bytes_before_start_after = %d start_after_new_len = %d bytes_written_after_start_after = %d\n",
+ fixup.len_pos_in_reader,
+ fixup.new_len,
+ reader_array_start_pos,
+ start_after->value_pos,
+ bytes_before_start_after,
+ start_after_new_len,
+ bytes_written_after_start_after);
+#endif
+ }
}
else
{
_dbus_type_reader_read_basic (reader, &val);
+ enable_if_after (writer, reader, start_after);
if (!_dbus_type_writer_write_basic (writer, current_type, &val))
goto oom;
}
_dbus_type_reader_next (reader);
}
+ return TRUE;
+
+ oom:
+ if (fixups)
+ apply_and_free_fixups (fixups, NULL); /* NULL for reader to apply to */
+
+ return FALSE;
+}
+
+/**
+ * Iterate through all values in the given reader, writing a copy of
+ * each value to the writer. The reader will be moved forward to its
+ * end position.
+ *
+ * If a reader start_after is provided, it should be a reader for the
+ * same data as the reader to be written. Only values occurring after
+ * the value pointed to by start_after will be written to the writer.
+ *
+ * If start_after is provided, then the copy of the reader will be
+ * partial. This means that array lengths will not have been copied.
+ * The assumption is that you wrote a new version of the value at
+ * start_after to the writer. You have to pass in the start position
+ * and length of the new value. (If you are deleting the value
+ * at start_after, pass in 0 for the length.)
+ *
+ * If the fixups parameter is non-#NULL, then any array length that
+ * was read but not written due to start_after will be provided
+ * as a #DBusArrayLenFixup. The fixup contains the position of the
+ * array length in the source data, and the correct array length
+ * assuming you combine the source data before start_after with
+ * the written data at start_after and beyond.
+ *
+ * @param writer the writer to copy to
+ * @param reader the reader to copy from
+ * @param start_after #NULL or a reader showing where to start
+ * @param start_after_new_pos the position of start_after equivalent in the target data
+ * @param start_after_new_len the length of start_after equivalent in the target data
+ * @param fixups list to append #DBusArrayLenFixup if the write was partial
+ * @returns #FALSE if no memory
+ */
+dbus_bool_t
+_dbus_type_writer_write_reader_partial (DBusTypeWriter *writer,
+ DBusTypeReader *reader,
+ const DBusTypeReader *start_after,
+ int start_after_new_pos,
+ int start_after_new_len,
+ DBusList **fixups)
+{
+ DBusTypeWriter orig;
+ int orig_type_len;
+ int orig_value_len;
+ int new_bytes;
+ int orig_enabled;
+
+ orig = *writer;
+ orig_type_len = _dbus_string_get_length (writer->type_str);
+ orig_value_len = _dbus_string_get_length (writer->value_str);
+ orig_enabled = writer->enabled;
+
+ if (start_after)
+ _dbus_type_writer_set_enabled (writer, FALSE);
+
+ if (!writer_write_reader_helper (writer, reader, start_after,
+ start_after_new_pos,
+ start_after_new_len,
+ fixups))
+ goto oom;
+
_dbus_type_writer_set_enabled (writer, orig_enabled);
return TRUE;
}
/**
+ * Iterate through all values in the given reader, writing a copy of
+ * each value to the writer. The reader will be moved forward to its
+ * end position.
+ *
+ * @param writer the writer to copy to
+ * @param reader the reader to copy from
+ * @returns #FALSE if no memory
+ */
+dbus_bool_t
+_dbus_type_writer_write_reader (DBusTypeWriter *writer,
+ DBusTypeReader *reader)
+{
+ return _dbus_type_writer_write_reader_partial (writer, reader, NULL, 0, 0, NULL);
+}
+
+/**
* If disabled, a writer can still be iterated forward and recursed/unrecursed
* but won't write any values. Types will still be written unless the
* writer is a "values only" writer, because the writer needs access to
#include <stdio.h>
#include <stdlib.h>
-/* Whether to do the OOM stuff */
+/* 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
* obviously makes the test suite run 10x as slow.
TestTypeNodeClass base;
};
+/* FIXME this could be chilled out substantially by unifying
+ * the basic types into basic_write_value/basic_read_value
+ * and by merging read_value and set_value into one function
+ * taking a flag argument.
+ */
static dbus_bool_t int32_write_value (TestTypeNode *node,
DataBlock *block,
DBusTypeWriter *writer,
static dbus_bool_t int32_read_value (TestTypeNode *node,
DBusTypeReader *reader,
int seed);
+static dbus_bool_t int32_set_value (TestTypeNode *node,
+ DBusTypeReader *reader,
+ DBusTypeReader *realign_root,
+ int seed);
static dbus_bool_t int64_write_value (TestTypeNode *node,
DataBlock *block,
DBusTypeWriter *writer,
static dbus_bool_t int64_read_value (TestTypeNode *node,
DBusTypeReader *reader,
int seed);
+static dbus_bool_t int64_set_value (TestTypeNode *node,
+ DBusTypeReader *reader,
+ DBusTypeReader *realign_root,
+ int seed);
static dbus_bool_t string_write_value (TestTypeNode *node,
DataBlock *block,
DBusTypeWriter *writer,
static dbus_bool_t string_read_value (TestTypeNode *node,
DBusTypeReader *reader,
int seed);
+static dbus_bool_t string_set_value (TestTypeNode *node,
+ DBusTypeReader *reader,
+ DBusTypeReader *realign_root,
+ int seed);
static dbus_bool_t bool_write_value (TestTypeNode *node,
DataBlock *block,
DBusTypeWriter *writer,
static dbus_bool_t bool_read_value (TestTypeNode *node,
DBusTypeReader *reader,
int seed);
+static dbus_bool_t bool_set_value (TestTypeNode *node,
+ DBusTypeReader *reader,
+ DBusTypeReader *realign_root,
+ int seed);
static dbus_bool_t byte_write_value (TestTypeNode *node,
DataBlock *block,
DBusTypeWriter *writer,
static dbus_bool_t byte_read_value (TestTypeNode *node,
DBusTypeReader *reader,
int seed);
+static dbus_bool_t byte_set_value (TestTypeNode *node,
+ DBusTypeReader *reader,
+ DBusTypeReader *realign_root,
+ int seed);
static dbus_bool_t double_write_value (TestTypeNode *node,
DataBlock *block,
DBusTypeWriter *writer,
static dbus_bool_t double_read_value (TestTypeNode *node,
DBusTypeReader *reader,
int seed);
+static dbus_bool_t double_set_value (TestTypeNode *node,
+ DBusTypeReader *reader,
+ DBusTypeReader *realign_root,
+ int seed);
static dbus_bool_t object_path_write_value (TestTypeNode *node,
DataBlock *block,
DBusTypeWriter *writer,
static dbus_bool_t object_path_read_value (TestTypeNode *node,
DBusTypeReader *reader,
int seed);
+static dbus_bool_t object_path_set_value (TestTypeNode *node,
+ DBusTypeReader *reader,
+ DBusTypeReader *realign_root,
+ int seed);
static dbus_bool_t signature_write_value (TestTypeNode *node,
DataBlock *block,
DBusTypeWriter *writer,
static dbus_bool_t signature_read_value (TestTypeNode *node,
DBusTypeReader *reader,
int seed);
+static dbus_bool_t signature_set_value (TestTypeNode *node,
+ DBusTypeReader *reader,
+ DBusTypeReader *realign_root,
+ int seed);
static dbus_bool_t struct_write_value (TestTypeNode *node,
DataBlock *block,
DBusTypeWriter *writer,
static dbus_bool_t struct_read_value (TestTypeNode *node,
DBusTypeReader *reader,
int seed);
+static dbus_bool_t struct_set_value (TestTypeNode *node,
+ DBusTypeReader *reader,
+ DBusTypeReader *realign_root,
+ int seed);
static dbus_bool_t struct_build_signature (TestTypeNode *node,
DBusString *str);
static dbus_bool_t array_write_value (TestTypeNode *node,
static dbus_bool_t array_read_value (TestTypeNode *node,
DBusTypeReader *reader,
int seed);
+static dbus_bool_t array_set_value (TestTypeNode *node,
+ DBusTypeReader *reader,
+ DBusTypeReader *realign_root,
+ int seed);
static dbus_bool_t array_build_signature (TestTypeNode *node,
DBusString *str);
static dbus_bool_t variant_write_value (TestTypeNode *node,
static dbus_bool_t variant_read_value (TestTypeNode *node,
DBusTypeReader *reader,
int seed);
+static dbus_bool_t variant_set_value (TestTypeNode *node,
+ DBusTypeReader *reader,
+ DBusTypeReader *realign_root,
+ int seed);
static void container_destroy (TestTypeNode *node);
NULL,
int32_write_value,
int32_read_value,
- NULL,
+ int32_set_value,
NULL
};
NULL,
int32_write_value, /* recycle from int32 */
int32_read_value, /* recycle from int32 */
- NULL,
+ int32_set_value, /* recycle from int32 */
NULL
};
NULL,
int64_write_value,
int64_read_value,
- NULL,
+ int64_set_value,
NULL
};
NULL,
int64_write_value, /* recycle from int64 */
int64_read_value, /* recycle from int64 */
- NULL,
+ int64_set_value, /* recycle from int64 */
NULL
};
NULL,
string_write_value,
string_read_value,
- NULL,
+ string_set_value,
NULL
};
NULL,
string_write_value,
string_read_value,
- NULL,
+ string_set_value,
NULL
};
NULL,
string_write_value,
string_read_value,
- NULL,
+ string_set_value,
NULL
};
NULL,
string_write_value,
string_read_value,
- NULL,
+ string_set_value,
NULL
};
NULL,
bool_write_value,
bool_read_value,
- NULL,
+ bool_set_value,
NULL
};
NULL,
byte_write_value,
byte_read_value,
- NULL,
+ byte_set_value,
NULL
};
NULL,
double_write_value,
double_read_value,
- NULL,
+ double_set_value,
NULL
};
NULL,
object_path_write_value,
object_path_read_value,
- NULL,
+ object_path_set_value,
NULL
};
NULL,
signature_write_value,
signature_read_value,
- NULL,
+ signature_set_value,
NULL
};
container_destroy,
struct_write_value,
struct_read_value,
- NULL,
+ struct_set_value,
struct_build_signature
};
container_destroy,
struct_write_value,
struct_read_value,
- NULL,
+ struct_set_value,
struct_build_signature
};
container_destroy,
array_write_value,
array_read_value,
- NULL,
+ array_set_value,
array_build_signature
};
container_destroy,
array_write_value,
array_read_value,
- NULL,
+ array_set_value,
array_build_signature
};
container_destroy,
array_write_value,
array_read_value,
- NULL,
+ array_set_value,
array_build_signature
};
container_destroy,
array_write_value,
array_read_value,
- NULL,
+ array_set_value,
array_build_signature
};
container_destroy,
variant_write_value,
variant_read_value,
- NULL,
+ variant_set_value,
NULL
};
return TRUE;
}
+/* Warning: if this one fails due to OOM, it has side effects (can
+ * modify only some of the sub-values). OK in a test suite, but we
+ * never do this in real code.
+ */
+static dbus_bool_t
+node_set_value (TestTypeNode *node,
+ DBusTypeReader *reader,
+ DBusTypeReader *realign_root,
+ int seed)
+{
+ if (!(* node->klass->set_value) (node, reader, realign_root, seed))
+ return FALSE;
+
+ return TRUE;
+}
+
static dbus_bool_t
node_build_signature (TestTypeNode *node,
DBusString *str)
dest.initial_offset, '\0'))
goto out;
- if (!_dbus_type_writer_write_reader (&writer, &reader, NULL))
+ if (!_dbus_type_writer_write_reader (&writer, &reader))
goto out;
/* Data blocks should now be identical */
return retval;
}
+/* offset the seed for setting, so we set different numbers than
+ * we originally wrote. Don't offset by a huge number since in
+ * some cases it's value = possibilities[seed % n_possibilities]
+ * and we don't want to wrap around. bool_from_seed
+ * is just seed % 2 even.
+ */
+#define SET_SEED 1
+static dbus_bool_t
+run_test_set_values (NodeIterationData *nid)
+{
+ DBusTypeReader reader;
+ DBusTypeReader realign_root;
+ dbus_bool_t retval;
+ int i;
+
+ _dbus_verbose ("%s\n", _DBUS_FUNCTION_NAME);
+
+ retval = FALSE;
+
+ data_block_init_reader_writer (nid->block,
+ &reader, NULL);
+
+ realign_root = reader;
+
+ i = 0;
+ while (i < nid->n_nodes)
+ {
+ if (!node_set_value (nid->nodes[i],
+ &reader, &realign_root,
+ i + SET_SEED))
+ goto out;
+
+ if (i + 1 == nid->n_nodes)
+ NEXT_EXPECTING_FALSE (&reader);
+ else
+ NEXT_EXPECTING_TRUE (&reader);
+
+ ++i;
+ }
+
+ /* Check that the new values were set */
+
+ reader = realign_root;
+
+ i = 0;
+ while (i < nid->n_nodes)
+ {
+ if (!node_read_value (nid->nodes[i], &reader,
+ i + SET_SEED))
+ goto out;
+
+ if (i + 1 == nid->n_nodes)
+ NEXT_EXPECTING_FALSE (&reader);
+ else
+ NEXT_EXPECTING_TRUE (&reader);
+
+ ++i;
+ }
+
+ retval = TRUE;
+
+ out:
+ return retval;
+}
+
static dbus_bool_t
run_test_nodes_iteration (void *data)
{
if (n_iterations_expected_this_test <= MAX_ITERATIONS_FOR_EXPENSIVE_TESTS)
{
+ /* this set values test uses code from copy and
+ * values_only_write so would ideally be last so you get a
+ * simpler test case for problems with copying or values_only
+ * writing; but it also needs an already-written DataBlock so it
+ * has to go first. Comment it out if it breaks, and see if the
+ * later tests also break - debug them first if so.
+ */
+ if (!run_test_set_values (nid))
+ goto out;
+
if (!run_test_copy (nid))
goto out;
nid.nodes = nodes;
nid.n_nodes = n_nodes;
-#if TEST_OOM_HANDLING
- _dbus_test_oom_handling ("running test node",
- run_test_nodes_iteration,
- &nid);
-#else
- if (!run_test_nodes_iteration (&nid))
- _dbus_assert_not_reached ("no memory");
-#endif
+ if (TEST_OOM_HANDLING &&
+ n_iterations_expected_this_test <= MAX_ITERATIONS_FOR_EXPENSIVE_TESTS)
+ {
+ _dbus_test_oom_handling ("running test node",
+ run_test_nodes_iteration,
+ &nid);
+ }
+ else
+ {
+ if (!run_test_nodes_iteration (&nid))
+ _dbus_assert_not_reached ("no memory");
+ }
data_block_free (&block);
}
return TRUE;
}
+static dbus_bool_t
+int32_set_value (TestTypeNode *node,
+ DBusTypeReader *reader,
+ DBusTypeReader *realign_root,
+ int seed)
+{
+ /* also used for uint32 */
+ dbus_int32_t v;
+
+ v = int32_from_seed (seed);
+
+ return _dbus_type_reader_set_basic (reader,
+ &v,
+ realign_root);
+}
+
#ifdef DBUS_HAVE_INT64
static dbus_int64_t
int64_from_seed (int seed)
#endif
}
+static dbus_bool_t
+int64_set_value (TestTypeNode *node,
+ DBusTypeReader *reader,
+ DBusTypeReader *realign_root,
+ int seed)
+{
+#ifdef DBUS_HAVE_INT64
+ /* also used for uint64 */
+ dbus_int64_t v;
+
+ v = int64_from_seed (seed);
+
+ return _dbus_type_reader_set_basic (reader,
+ &v,
+ realign_root);
+#else
+ return TRUE;
+#endif
+}
+
#define MAX_SAMPLE_STRING_LEN 10
static void
string_from_seed (char *buf,
_dbus_assert (len < MAX_SAMPLE_STRING_LEN);
+ /* vary the length slightly, though we also have multiple string
+ * value types for this, varying it here tests the set_value code
+ */
+ switch (seed % 3)
+ {
+ case 1:
+ len += 2;
+ break;
+ case 2:
+ len -= 2;
+ break;
+ }
+ if (len < 0)
+ len = 0;
+
v = (unsigned char) ('A' + seed);
i = 0;
return TRUE;
}
+static dbus_bool_t
+string_set_value (TestTypeNode *node,
+ DBusTypeReader *reader,
+ DBusTypeReader *realign_root,
+ int seed)
+{
+ char buf[MAX_SAMPLE_STRING_LEN];
+ const char *v_string = buf;
+
+ string_from_seed (buf, node->klass->subclass_detail,
+ seed);
+
+ return _dbus_type_reader_set_basic (reader,
+ &v_string,
+ realign_root);
+}
+
#define BOOL_FROM_SEED(seed) (seed % 2)
static dbus_bool_t
return TRUE;
}
+static dbus_bool_t
+bool_set_value (TestTypeNode *node,
+ DBusTypeReader *reader,
+ DBusTypeReader *realign_root,
+ int seed)
+{
+ unsigned char v;
+
+ v = BOOL_FROM_SEED (seed);
+
+ return _dbus_type_reader_set_basic (reader,
+ &v,
+ realign_root);
+}
+
#define BYTE_FROM_SEED(seed) ((unsigned char) int32_from_seed (seed))
static dbus_bool_t
return TRUE;
}
+
+static dbus_bool_t
+byte_set_value (TestTypeNode *node,
+ DBusTypeReader *reader,
+ DBusTypeReader *realign_root,
+ int seed)
+{
+ unsigned char v;
+
+ v = BYTE_FROM_SEED (seed);
+
+ return _dbus_type_reader_set_basic (reader,
+ &v,
+ realign_root);
+}
+
static double
double_from_seed (int seed)
{
#ifdef DBUS_HAVE_INT64
_dbus_warn ("Expected double %g got %g\n bits = 0x%llx vs.\n bits = 0x%llx)\n",
expected, v,
- *(dbus_uint64_t*)&expected,
- *(dbus_uint64_t*)&v);
+ *(dbus_uint64_t*)(char*)&expected,
+ *(dbus_uint64_t*)(char*)&v);
#endif
_dbus_assert_not_reached ("test failed");
}
return TRUE;
}
+static dbus_bool_t
+double_set_value (TestTypeNode *node,
+ DBusTypeReader *reader,
+ DBusTypeReader *realign_root,
+ int seed)
+{
+ double v;
+
+ v = double_from_seed (seed);
+
+ return _dbus_type_reader_set_basic (reader,
+ &v,
+ realign_root);
+}
#define MAX_SAMPLE_OBJECT_PATH_LEN 10
static void
{
int i;
unsigned char v;
+ int len;
+
+ len = seed % 9;
+ _dbus_assert (len < MAX_SAMPLE_OBJECT_PATH_LEN);
v = (unsigned char) ('A' + seed);
i = 0;
- while (i < 8)
+ while (i + 1 < len)
{
if (v < 'A' || v > 'z')
v = 'A';
return TRUE;
}
+static dbus_bool_t
+object_path_set_value (TestTypeNode *node,
+ DBusTypeReader *reader,
+ DBusTypeReader *realign_root,
+ int seed)
+{
+ char buf[MAX_SAMPLE_OBJECT_PATH_LEN];
+ const char *v_string = buf;
+
+ object_path_from_seed (buf, seed);
+
+ return _dbus_type_reader_set_basic (reader,
+ &v_string,
+ realign_root);
+}
#define MAX_SAMPLE_SIGNATURE_LEN 10
static void
{
int i;
const char *s;
+ /* try to avoid ascending, descending, or alternating length to help find bugs */
const char *sample_signatures[] = {
+ "asax"
"",
- "ai",
+ "asau(xxxx)",
"x",
- "a(ii)",
- "asax"
- "asau(xxxx)"
+ "ai",
+ "a(ii)"
};
s = sample_signatures[seed % _DBUS_N_ELEMENTS(sample_signatures)];
return TRUE;
}
+
+static dbus_bool_t
+signature_set_value (TestTypeNode *node,
+ DBusTypeReader *reader,
+ DBusTypeReader *realign_root,
+ int seed)
+{
+ char buf[MAX_SAMPLE_SIGNATURE_LEN];
+ const char *v_string = buf;
+
+ signature_from_seed (buf, seed);
+
+ return _dbus_type_reader_set_basic (reader,
+ &v_string,
+ realign_root);
+}
+
static dbus_bool_t
struct_write_value (TestTypeNode *node,
DataBlock *block,
}
static dbus_bool_t
-struct_read_value (TestTypeNode *node,
- DBusTypeReader *reader,
- int seed)
+struct_read_or_set_value (TestTypeNode *node,
+ DBusTypeReader *reader,
+ DBusTypeReader *realign_root,
+ int seed)
{
TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
DBusTypeReader sub;
TestTypeNode *child = link->data;
DBusList *next = _dbus_list_get_next_link (&container->children, link);
- if (!node_read_value (child, &sub, seed + i))
- return FALSE;
+ if (realign_root == NULL)
+ {
+ if (!node_read_value (child, &sub, seed + i))
+ return FALSE;
+ }
+ else
+ {
+ if (!node_set_value (child, &sub, realign_root, seed + i))
+ return FALSE;
+ }
if (i == (n_copies - 1) && next == NULL)
NEXT_EXPECTING_FALSE (&sub);
}
static dbus_bool_t
+struct_read_value (TestTypeNode *node,
+ DBusTypeReader *reader,
+ int seed)
+{
+ return struct_read_or_set_value (node, reader, NULL, seed);
+}
+
+static dbus_bool_t
+struct_set_value (TestTypeNode *node,
+ DBusTypeReader *reader,
+ DBusTypeReader *realign_root,
+ int seed)
+{
+ return struct_read_or_set_value (node, reader, realign_root, seed);
+}
+
+static dbus_bool_t
struct_build_signature (TestTypeNode *node,
DBusString *str)
{
}
static dbus_bool_t
-array_read_value (TestTypeNode *node,
- DBusTypeReader *reader,
- int seed)
+array_read_or_set_value (TestTypeNode *node,
+ DBusTypeReader *reader,
+ DBusTypeReader *realign_root,
+ int seed)
{
TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
DBusTypeReader sub;
TestTypeNode *child = link->data;
DBusList *next = _dbus_list_get_next_link (&container->children, link);
- if (!node_read_value (child, &sub, seed + i))
- return FALSE;
+ if (realign_root == NULL)
+ {
+ if (!node_read_value (child, &sub, seed + i))
+ return FALSE;
+ }
+ else
+ {
+ if (!node_set_value (child, &sub, realign_root, seed + i))
+ return FALSE;
+ }
if (i == (n_copies - 1) && next == NULL)
NEXT_EXPECTING_FALSE (&sub);
}
static dbus_bool_t
+array_read_value (TestTypeNode *node,
+ DBusTypeReader *reader,
+ int seed)
+{
+ return array_read_or_set_value (node, reader, NULL, seed);
+}
+
+static dbus_bool_t
+array_set_value (TestTypeNode *node,
+ DBusTypeReader *reader,
+ DBusTypeReader *realign_root,
+ int seed)
+{
+ return array_read_or_set_value (node, reader, realign_root, seed);
+}
+
+static dbus_bool_t
array_build_signature (TestTypeNode *node,
DBusString *str)
{
}
static dbus_bool_t
-variant_read_value (TestTypeNode *node,
- DBusTypeReader *reader,
- int seed)
+variant_read_or_set_value (TestTypeNode *node,
+ DBusTypeReader *reader,
+ DBusTypeReader *realign_root,
+ int seed)
{
TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
DBusTypeReader sub;
_dbus_type_reader_recurse (reader, &sub);
- if (!node_read_value (child, &sub, seed + VARIANT_SEED))
- return FALSE;
+ if (realign_root == NULL)
+ {
+ if (!node_read_value (child, &sub, seed + VARIANT_SEED))
+ return FALSE;
+ }
+ else
+ {
+ if (!node_set_value (child, &sub, realign_root, seed + VARIANT_SEED))
+ return FALSE;
+ }
NEXT_EXPECTING_FALSE (&sub);
return TRUE;
}
+static dbus_bool_t
+variant_read_value (TestTypeNode *node,
+ DBusTypeReader *reader,
+ int seed)
+{
+ return variant_read_or_set_value (node, reader, NULL, seed);
+}
+
+static dbus_bool_t
+variant_set_value (TestTypeNode *node,
+ DBusTypeReader *reader,
+ DBusTypeReader *realign_root,
+ int seed)
+{
+ return variant_read_or_set_value (node, reader, realign_root, seed);
+}
+
static void
container_destroy (TestTypeNode *node)
{