Merge branch 'dbus-1.10'
[platform/upstream/dbus.git] / dbus / dbus-marshal-recursive-util.c
1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /* dbus-marshal-recursive-util.c  Would be in dbus-marshal-recursive.c, but only used in bus/tests
3  *
4  * Copyright (C) 2004, 2005 Red Hat, Inc.
5  *
6  * Licensed under the Academic Free License version 2.1
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
21  *
22  */
23
24 #include <config.h>
25
26 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
27
28 #include "dbus-marshal-recursive.h"
29 #include "dbus-marshal-basic.h"
30 #include "dbus-signature.h"
31 #include "dbus-internals.h"
32 #include <string.h>
33
34 #if !defined(PRIx64) && defined(DBUS_WIN)
35 #define PRIx64 "I64x"
36 #endif
37
38 static void
39 basic_value_zero (DBusBasicValue *value)
40 {
41   value->u64 = 0;
42 }
43
44 static dbus_bool_t
45 basic_value_equal (int             type,
46                    DBusBasicValue *lhs,
47                    DBusBasicValue *rhs)
48 {
49   if (type == DBUS_TYPE_STRING ||
50       type == DBUS_TYPE_SIGNATURE ||
51       type == DBUS_TYPE_OBJECT_PATH)
52     {
53       return strcmp (lhs->str, rhs->str) == 0;
54     }
55   else
56     {
57       return lhs->u64 == rhs->u64;
58     }
59 }
60
61 static dbus_bool_t
62 equal_values_helper (DBusTypeReader *lhs,
63                      DBusTypeReader *rhs)
64 {
65   int lhs_type;
66   int rhs_type;
67
68   lhs_type = _dbus_type_reader_get_current_type (lhs);
69   rhs_type = _dbus_type_reader_get_current_type (rhs);
70
71   if (lhs_type != rhs_type)
72     return FALSE;
73
74   if (lhs_type == DBUS_TYPE_INVALID)
75     return TRUE;
76
77   if (dbus_type_is_basic (lhs_type))
78     {
79       DBusBasicValue lhs_value;
80       DBusBasicValue rhs_value;
81
82       basic_value_zero (&lhs_value);
83       basic_value_zero (&rhs_value);
84       
85       _dbus_type_reader_read_basic (lhs, &lhs_value);
86       _dbus_type_reader_read_basic (rhs, &rhs_value);
87
88       return basic_value_equal (lhs_type, &lhs_value, &rhs_value);
89     }
90   else
91     {
92       DBusTypeReader lhs_sub;
93       DBusTypeReader rhs_sub;
94
95       _dbus_type_reader_recurse (lhs, &lhs_sub);
96       _dbus_type_reader_recurse (rhs, &rhs_sub);
97
98       return equal_values_helper (&lhs_sub, &rhs_sub);
99     }
100 }
101
102 /**
103  * See whether the two readers point to identical data blocks.
104  *
105  * @param lhs reader 1
106  * @param rhs reader 2
107  * @returns #TRUE if the data blocks have the same values
108  */
109 dbus_bool_t
110 _dbus_type_reader_equal_values (const DBusTypeReader *lhs,
111                                 const DBusTypeReader *rhs)
112 {
113   DBusTypeReader copy_lhs = *lhs;
114   DBusTypeReader copy_rhs = *rhs;
115
116   return equal_values_helper (&copy_lhs, &copy_rhs);
117 }
118
119 /* TESTS */
120
121 #ifndef DOXYGEN_SHOULD_SKIP_THIS
122
123 #include "dbus-test.h"
124 #include "dbus-list.h"
125 #include <stdio.h>
126 #include <stdlib.h>
127
128 /* Whether to do the OOM stuff (only with other expensive tests) */
129 #define TEST_OOM_HANDLING 0
130 /* We do start offset 0 through 9, to get various alignment cases. Still this
131  * obviously makes the test suite run 10x as slow.
132  */
133 #define MAX_INITIAL_OFFSET 9
134
135 /* Largest iteration count to test copying, realignment,
136  * etc. with. i.e. we only test this stuff with some of the smaller
137  * data sets.
138  */
139 #define MAX_ITERATIONS_FOR_EXPENSIVE_TESTS 1000
140
141 typedef struct
142 {
143   int byte_order;
144   int initial_offset;
145   DBusString signature;
146   DBusString body;
147 } DataBlock;
148
149 typedef struct
150 {
151   int saved_sig_len;
152   int saved_body_len;
153 } DataBlockState;
154
155 #define N_FENCE_BYTES 5
156 #define FENCE_BYTES_STR "abcde"
157 #define INITIAL_PADDING_BYTE '\0'
158
159 static dbus_bool_t
160 data_block_init (DataBlock *block,
161                  int        byte_order,
162                  int        initial_offset)
163 {
164   if (!_dbus_string_init (&block->signature))
165     return FALSE;
166
167   if (!_dbus_string_init (&block->body))
168     {
169       _dbus_string_free (&block->signature);
170       return FALSE;
171     }
172
173   if (!_dbus_string_insert_bytes (&block->signature, 0, initial_offset,
174                                   INITIAL_PADDING_BYTE) ||
175       !_dbus_string_insert_bytes (&block->body, 0, initial_offset,
176                                   INITIAL_PADDING_BYTE) ||
177       !_dbus_string_append (&block->signature, FENCE_BYTES_STR) ||
178       !_dbus_string_append (&block->body, FENCE_BYTES_STR))
179     {
180       _dbus_string_free (&block->signature);
181       _dbus_string_free (&block->body);
182       return FALSE;
183     }
184
185   block->byte_order = byte_order;
186   block->initial_offset = initial_offset;
187
188   return TRUE;
189 }
190
191 static void
192 data_block_save (DataBlock      *block,
193                  DataBlockState *state)
194 {
195   state->saved_sig_len = _dbus_string_get_length (&block->signature) - N_FENCE_BYTES;
196   state->saved_body_len = _dbus_string_get_length (&block->body) - N_FENCE_BYTES;
197 }
198
199 static void
200 data_block_restore (DataBlock      *block,
201                     DataBlockState *state)
202 {
203   _dbus_string_delete (&block->signature,
204                        state->saved_sig_len,
205                        _dbus_string_get_length (&block->signature) - state->saved_sig_len - N_FENCE_BYTES);
206   _dbus_string_delete (&block->body,
207                        state->saved_body_len,
208                        _dbus_string_get_length (&block->body) - state->saved_body_len - N_FENCE_BYTES);
209 }
210
211 static void
212 data_block_verify (DataBlock *block)
213 {
214   if (!_dbus_string_ends_with_c_str (&block->signature,
215                                      FENCE_BYTES_STR))
216     {
217       int offset;
218
219       offset = _dbus_string_get_length (&block->signature) - N_FENCE_BYTES - 8;
220       if (offset < 0)
221         offset = 0;
222
223       _dbus_verbose_bytes_of_string (&block->signature,
224                                      offset,
225                                      _dbus_string_get_length (&block->signature) - offset);
226       _dbus_assert_not_reached ("block did not verify: bad bytes at end of signature");
227     }
228   if (!_dbus_string_ends_with_c_str (&block->body,
229                                      FENCE_BYTES_STR))
230     {
231       int offset;
232
233       offset = _dbus_string_get_length (&block->body) - N_FENCE_BYTES - 8;
234       if (offset < 0)
235         offset = 0;
236
237       _dbus_verbose_bytes_of_string (&block->body,
238                                      offset,
239                                      _dbus_string_get_length (&block->body) - offset);
240       _dbus_assert_not_reached ("block did not verify: bad bytes at end of body");
241     }
242
243   _dbus_assert (_dbus_string_validate_nul (&block->signature,
244                                            0, block->initial_offset));
245   _dbus_assert (_dbus_string_validate_nul (&block->body,
246                                            0, block->initial_offset));
247 }
248
249 static void
250 data_block_free (DataBlock *block)
251 {
252   data_block_verify (block);
253
254   _dbus_string_free (&block->signature);
255   _dbus_string_free (&block->body);
256 }
257
258 static void
259 data_block_reset (DataBlock *block)
260 {
261   data_block_verify (block);
262
263   _dbus_string_delete (&block->signature,
264                        block->initial_offset,
265                        _dbus_string_get_length (&block->signature) - N_FENCE_BYTES - block->initial_offset);
266   _dbus_string_delete (&block->body,
267                        block->initial_offset,
268                        _dbus_string_get_length (&block->body) - N_FENCE_BYTES - block->initial_offset);
269
270   data_block_verify (block);
271 }
272
273 static void
274 data_block_init_reader_writer (DataBlock      *block,
275                                DBusTypeReader *reader,
276                                DBusTypeWriter *writer)
277 {
278   if (reader)
279     _dbus_type_reader_init (reader,
280                             block->byte_order,
281                             &block->signature,
282                             block->initial_offset,
283                             &block->body,
284                             block->initial_offset);
285
286   if (writer)
287     _dbus_type_writer_init (writer,
288                             block->byte_order,
289                             &block->signature,
290                             _dbus_string_get_length (&block->signature) - N_FENCE_BYTES,
291                             &block->body,
292                             _dbus_string_get_length (&block->body) - N_FENCE_BYTES);
293 }
294
295 static void
296 real_check_expected_type (DBusTypeReader *reader,
297                           int             expected,
298                           const char     *funcname,
299                           int             line)
300 {
301   int t;
302
303   t = _dbus_type_reader_get_current_type (reader);
304
305   if (t != expected)
306     {
307       _dbus_warn ("Read type %s while expecting %s at %s line %d\n",
308                   _dbus_type_to_string (t),
309                   _dbus_type_to_string (expected),
310                   funcname, line);
311
312       _dbus_assert_not_reached ("read wrong type");
313     }
314 }
315
316 #define check_expected_type(reader, expected) real_check_expected_type (reader, expected, _DBUS_FUNCTION_NAME, __LINE__)
317
318 #define NEXT_EXPECTING_TRUE(reader)  do { if (!_dbus_type_reader_next (reader))         \
319  {                                                                                      \
320     _dbus_warn ("_dbus_type_reader_next() should have returned TRUE at %s %d\n",        \
321                               _DBUS_FUNCTION_NAME, __LINE__);                           \
322     _dbus_assert_not_reached ("test failed");                                           \
323  }                                                                                      \
324 } while (0)
325
326 #define NEXT_EXPECTING_FALSE(reader) do { if (_dbus_type_reader_next (reader))          \
327  {                                                                                      \
328     _dbus_warn ("_dbus_type_reader_next() should have returned FALSE at %s %d\n",       \
329                               _DBUS_FUNCTION_NAME, __LINE__);                           \
330     _dbus_assert_not_reached ("test failed");                                           \
331  }                                                                                      \
332  check_expected_type (reader, DBUS_TYPE_INVALID);                                       \
333 } while (0)
334
335 typedef struct TestTypeNode               TestTypeNode;
336 typedef struct TestTypeNodeClass          TestTypeNodeClass;
337 typedef struct TestTypeNodeContainer      TestTypeNodeContainer;
338 typedef struct TestTypeNodeContainerClass TestTypeNodeContainerClass;
339
340 struct TestTypeNode
341 {
342   const TestTypeNodeClass *klass;
343 };
344
345 struct TestTypeNodeContainer
346 {
347   TestTypeNode base;
348   DBusList    *children;
349 };
350
351 struct TestTypeNodeClass
352 {
353   int typecode;
354
355   int instance_size;
356
357   int subclass_detail; /* a bad hack to avoid a bunch of subclass casting */
358
359   dbus_bool_t   (* construct)     (TestTypeNode   *node);
360   void          (* destroy)       (TestTypeNode   *node);
361
362   dbus_bool_t (* write_value)     (TestTypeNode   *node,
363                                    DataBlock      *block,
364                                    DBusTypeWriter *writer,
365                                    int             seed);
366   dbus_bool_t (* read_value)      (TestTypeNode   *node,
367                                    DBusTypeReader *reader,
368                                    int             seed);
369   dbus_bool_t (* set_value)       (TestTypeNode   *node,
370                                    DBusTypeReader *reader,
371                                    DBusTypeReader *realign_root,
372                                    int             seed);
373   dbus_bool_t (* build_signature) (TestTypeNode   *node,
374                                    DBusString     *str);
375   dbus_bool_t (* write_multi)     (TestTypeNode   *node,
376                                    DataBlock      *block,
377                                    DBusTypeWriter *writer,
378                                    int             seed,
379                                    int             count);
380   dbus_bool_t (* read_multi)      (TestTypeNode   *node,
381                                    DBusTypeReader *reader,
382                                    int             seed,
383                                    int             count);
384 };
385
386 struct TestTypeNodeContainerClass
387 {
388   TestTypeNodeClass base;
389 };
390
391 /* FIXME this could be chilled out substantially by unifying
392  * the basic types into basic_write_value/basic_read_value
393  * and by merging read_value and set_value into one function
394  * taking a flag argument.
395  */
396 static dbus_bool_t int16_write_value       (TestTypeNode   *node,
397                                             DataBlock      *block,
398                                             DBusTypeWriter *writer,
399                                             int             seed);
400 static dbus_bool_t int16_read_value        (TestTypeNode   *node,
401                                             DBusTypeReader *reader,
402                                             int             seed);
403 static dbus_bool_t int16_set_value         (TestTypeNode   *node,
404                                             DBusTypeReader *reader,
405                                             DBusTypeReader *realign_root,
406                                             int             seed);
407 static dbus_bool_t int16_write_multi       (TestTypeNode   *node,
408                                             DataBlock      *block,
409                                             DBusTypeWriter *writer,
410                                             int             seed,
411                                             int             count);
412 static dbus_bool_t int16_read_multi        (TestTypeNode   *node,
413                                             DBusTypeReader *reader,
414                                             int             seed,
415                                             int             count);
416 static dbus_bool_t int32_write_value       (TestTypeNode   *node,
417                                             DataBlock      *block,
418                                             DBusTypeWriter *writer,
419                                             int             seed);
420 static dbus_bool_t int32_read_value        (TestTypeNode   *node,
421                                             DBusTypeReader *reader,
422                                             int             seed);
423 static dbus_bool_t int32_set_value         (TestTypeNode   *node,
424                                             DBusTypeReader *reader,
425                                             DBusTypeReader *realign_root,
426                                             int             seed);
427 static dbus_bool_t int32_write_multi       (TestTypeNode   *node,
428                                             DataBlock      *block,
429                                             DBusTypeWriter *writer,
430                                             int             seed,
431                                             int             count);
432 static dbus_bool_t int32_read_multi        (TestTypeNode   *node,
433                                             DBusTypeReader *reader,
434                                             int             seed,
435                                             int             count);
436 static dbus_bool_t int64_write_value       (TestTypeNode   *node,
437                                             DataBlock      *block,
438                                             DBusTypeWriter *writer,
439                                             int             seed);
440 static dbus_bool_t int64_read_value        (TestTypeNode   *node,
441                                             DBusTypeReader *reader,
442                                             int             seed);
443 static dbus_bool_t int64_set_value         (TestTypeNode   *node,
444                                             DBusTypeReader *reader,
445                                             DBusTypeReader *realign_root,
446                                             int             seed);
447 static dbus_bool_t string_write_value      (TestTypeNode   *node,
448                                             DataBlock      *block,
449                                             DBusTypeWriter *writer,
450                                             int             seed);
451 static dbus_bool_t string_read_value       (TestTypeNode   *node,
452                                             DBusTypeReader *reader,
453                                             int             seed);
454 static dbus_bool_t string_set_value        (TestTypeNode   *node,
455                                             DBusTypeReader *reader,
456                                             DBusTypeReader *realign_root,
457                                             int             seed);
458 static dbus_bool_t bool_write_value        (TestTypeNode   *node,
459                                             DataBlock      *block,
460                                             DBusTypeWriter *writer,
461                                             int             seed);
462 static dbus_bool_t bool_read_value         (TestTypeNode   *node,
463                                             DBusTypeReader *reader,
464                                             int             seed);
465 static dbus_bool_t bool_set_value          (TestTypeNode   *node,
466                                             DBusTypeReader *reader,
467                                             DBusTypeReader *realign_root,
468                                             int             seed);
469 static dbus_bool_t byte_write_value        (TestTypeNode   *node,
470                                             DataBlock      *block,
471                                             DBusTypeWriter *writer,
472                                             int             seed);
473 static dbus_bool_t byte_read_value         (TestTypeNode   *node,
474                                             DBusTypeReader *reader,
475                                             int             seed);
476 static dbus_bool_t byte_set_value          (TestTypeNode   *node,
477                                             DBusTypeReader *reader,
478                                             DBusTypeReader *realign_root,
479                                             int             seed);
480 static dbus_bool_t double_write_value      (TestTypeNode   *node,
481                                             DataBlock      *block,
482                                             DBusTypeWriter *writer,
483                                             int             seed);
484 static dbus_bool_t double_read_value       (TestTypeNode   *node,
485                                             DBusTypeReader *reader,
486                                             int             seed);
487 static dbus_bool_t double_set_value        (TestTypeNode   *node,
488                                             DBusTypeReader *reader,
489                                             DBusTypeReader *realign_root,
490                                             int             seed);
491 static dbus_bool_t object_path_write_value (TestTypeNode   *node,
492                                             DataBlock      *block,
493                                             DBusTypeWriter *writer,
494                                             int             seed);
495 static dbus_bool_t object_path_read_value  (TestTypeNode   *node,
496                                             DBusTypeReader *reader,
497                                             int             seed);
498 static dbus_bool_t object_path_set_value   (TestTypeNode   *node,
499                                             DBusTypeReader *reader,
500                                             DBusTypeReader *realign_root,
501                                             int             seed);
502 static dbus_bool_t signature_write_value   (TestTypeNode   *node,
503                                             DataBlock      *block,
504                                             DBusTypeWriter *writer,
505                                             int             seed);
506 static dbus_bool_t signature_read_value    (TestTypeNode   *node,
507                                             DBusTypeReader *reader,
508                                             int             seed);
509 static dbus_bool_t signature_set_value     (TestTypeNode   *node,
510                                             DBusTypeReader *reader,
511                                             DBusTypeReader *realign_root,
512                                             int             seed);
513 static dbus_bool_t struct_write_value      (TestTypeNode   *node,
514                                             DataBlock      *block,
515                                             DBusTypeWriter *writer,
516                                             int             seed);
517 static dbus_bool_t struct_read_value       (TestTypeNode   *node,
518                                             DBusTypeReader *reader,
519                                             int             seed);
520 static dbus_bool_t struct_set_value        (TestTypeNode   *node,
521                                             DBusTypeReader *reader,
522                                             DBusTypeReader *realign_root,
523                                             int             seed);
524 static dbus_bool_t struct_build_signature  (TestTypeNode   *node,
525                                             DBusString     *str);
526 static dbus_bool_t dict_write_value        (TestTypeNode   *node,
527                                             DataBlock      *block,
528                                             DBusTypeWriter *writer,
529                                             int             seed);
530 static dbus_bool_t dict_read_value         (TestTypeNode   *node,
531                                             DBusTypeReader *reader,
532                                             int             seed);
533 static dbus_bool_t dict_set_value          (TestTypeNode   *node,
534                                             DBusTypeReader *reader,
535                                             DBusTypeReader *realign_root,
536                                             int             seed);
537 static dbus_bool_t dict_build_signature    (TestTypeNode   *node,
538                                             DBusString     *str);
539 static dbus_bool_t array_write_value       (TestTypeNode   *node,
540                                             DataBlock      *block,
541                                             DBusTypeWriter *writer,
542                                             int             seed);
543 static dbus_bool_t array_read_value        (TestTypeNode   *node,
544                                             DBusTypeReader *reader,
545                                             int             seed);
546 static dbus_bool_t array_set_value         (TestTypeNode   *node,
547                                             DBusTypeReader *reader,
548                                             DBusTypeReader *realign_root,
549                                             int             seed);
550 static dbus_bool_t array_build_signature   (TestTypeNode   *node,
551                                             DBusString     *str);
552 static dbus_bool_t variant_write_value     (TestTypeNode   *node,
553                                             DataBlock      *block,
554                                             DBusTypeWriter *writer,
555                                             int             seed);
556 static dbus_bool_t variant_read_value      (TestTypeNode   *node,
557                                             DBusTypeReader *reader,
558                                             int             seed);
559 static dbus_bool_t variant_set_value       (TestTypeNode   *node,
560                                             DBusTypeReader *reader,
561                                             DBusTypeReader *realign_root,
562                                             int             seed);
563 static void        container_destroy       (TestTypeNode   *node);
564
565
566
567 static const TestTypeNodeClass int16_class = {
568   DBUS_TYPE_INT16,
569   sizeof (TestTypeNode),
570   0,
571   NULL,
572   NULL,
573   int16_write_value,
574   int16_read_value,
575   int16_set_value,
576   NULL,
577   int16_write_multi,
578   int16_read_multi
579 };
580
581 static const TestTypeNodeClass uint16_class = {
582   DBUS_TYPE_UINT16,
583   sizeof (TestTypeNode),
584   0,
585   NULL,
586   NULL,
587   int16_write_value, /* recycle from int16 */
588   int16_read_value,  /* recycle from int16 */
589   int16_set_value,   /* recycle from int16 */
590   NULL,
591   int16_write_multi, /* recycle from int16 */
592   int16_read_multi   /* recycle from int16 */
593 };
594
595 static const TestTypeNodeClass int32_class = {
596   DBUS_TYPE_INT32,
597   sizeof (TestTypeNode),
598   0,
599   NULL,
600   NULL,
601   int32_write_value,
602   int32_read_value,
603   int32_set_value,
604   NULL,
605   int32_write_multi,
606   int32_read_multi
607 };
608
609 static const TestTypeNodeClass uint32_class = {
610   DBUS_TYPE_UINT32,
611   sizeof (TestTypeNode),
612   0,
613   NULL,
614   NULL,
615   int32_write_value, /* recycle from int32 */
616   int32_read_value,  /* recycle from int32 */
617   int32_set_value,   /* recycle from int32 */
618   NULL,
619   int32_write_multi, /* recycle from int32 */
620   int32_read_multi   /* recycle from int32 */
621 };
622
623 static const TestTypeNodeClass int64_class = {
624   DBUS_TYPE_INT64,
625   sizeof (TestTypeNode),
626   0,
627   NULL,
628   NULL,
629   int64_write_value,
630   int64_read_value,
631   int64_set_value,
632   NULL,
633   NULL, /* FIXME */
634   NULL  /* FIXME */
635 };
636
637 static const TestTypeNodeClass uint64_class = {
638   DBUS_TYPE_UINT64,
639   sizeof (TestTypeNode),
640   0,
641   NULL,
642   NULL,
643   int64_write_value, /* recycle from int64 */
644   int64_read_value,  /* recycle from int64 */
645   int64_set_value,   /* recycle from int64 */
646   NULL,
647   NULL, /* FIXME */
648   NULL  /* FIXME */
649 };
650
651 static const TestTypeNodeClass string_0_class = {
652   DBUS_TYPE_STRING,
653   sizeof (TestTypeNode),
654   0, /* string length */
655   NULL,
656   NULL,
657   string_write_value,
658   string_read_value,
659   string_set_value,
660   NULL,
661   NULL,
662   NULL
663 };
664
665 static const TestTypeNodeClass string_1_class = {
666   DBUS_TYPE_STRING,
667   sizeof (TestTypeNode),
668   1, /* string length */
669   NULL,
670   NULL,
671   string_write_value,
672   string_read_value,
673   string_set_value,
674   NULL,
675   NULL,
676   NULL
677 };
678
679 /* with nul, a len 3 string should fill 4 bytes and thus is "special" */
680 static const TestTypeNodeClass string_3_class = {
681   DBUS_TYPE_STRING,
682   sizeof (TestTypeNode),
683   3, /* string length */
684   NULL,
685   NULL,
686   string_write_value,
687   string_read_value,
688   string_set_value,
689   NULL,
690   NULL,
691   NULL
692 };
693
694 /* with nul, a len 8 string should fill 9 bytes and thus is "special" (far-fetched I suppose) */
695 static const TestTypeNodeClass string_8_class = {
696   DBUS_TYPE_STRING,
697   sizeof (TestTypeNode),
698   8, /* string length */
699   NULL,
700   NULL,
701   string_write_value,
702   string_read_value,
703   string_set_value,
704   NULL,
705   NULL,
706   NULL
707 };
708
709 static const TestTypeNodeClass bool_class = {
710   DBUS_TYPE_BOOLEAN,
711   sizeof (TestTypeNode),
712   0,
713   NULL,
714   NULL,
715   bool_write_value,
716   bool_read_value,
717   bool_set_value,
718   NULL,
719   NULL, /* FIXME */
720   NULL  /* FIXME */
721 };
722
723 static const TestTypeNodeClass byte_class = {
724   DBUS_TYPE_BYTE,
725   sizeof (TestTypeNode),
726   0,
727   NULL,
728   NULL,
729   byte_write_value,
730   byte_read_value,
731   byte_set_value,
732   NULL,
733   NULL, /* FIXME */
734   NULL  /* FIXME */
735 };
736
737 static const TestTypeNodeClass double_class = {
738   DBUS_TYPE_DOUBLE,
739   sizeof (TestTypeNode),
740   0,
741   NULL,
742   NULL,
743   double_write_value,
744   double_read_value,
745   double_set_value,
746   NULL,
747   NULL, /* FIXME */
748   NULL  /* FIXME */
749 };
750
751 static const TestTypeNodeClass object_path_class = {
752   DBUS_TYPE_OBJECT_PATH,
753   sizeof (TestTypeNode),
754   0,
755   NULL,
756   NULL,
757   object_path_write_value,
758   object_path_read_value,
759   object_path_set_value,
760   NULL,
761   NULL,
762   NULL
763 };
764
765 static const TestTypeNodeClass signature_class = {
766   DBUS_TYPE_SIGNATURE,
767   sizeof (TestTypeNode),
768   0,
769   NULL,
770   NULL,
771   signature_write_value,
772   signature_read_value,
773   signature_set_value,
774   NULL,
775   NULL,
776   NULL
777 };
778
779 static const TestTypeNodeClass struct_1_class = {
780   DBUS_TYPE_STRUCT,
781   sizeof (TestTypeNodeContainer),
782   1, /* number of times children appear as fields */
783   NULL,
784   container_destroy,
785   struct_write_value,
786   struct_read_value,
787   struct_set_value,
788   struct_build_signature,
789   NULL,
790   NULL
791 };
792
793 static const TestTypeNodeClass struct_2_class = {
794   DBUS_TYPE_STRUCT,
795   sizeof (TestTypeNodeContainer),
796   2, /* number of times children appear as fields */
797   NULL,
798   container_destroy,
799   struct_write_value,
800   struct_read_value,
801   struct_set_value,
802   struct_build_signature,
803   NULL,
804   NULL
805 };
806
807 static const TestTypeNodeClass dict_1_class = {
808   DBUS_TYPE_ARRAY, /* this is correct, a dict is an array of dict entry */
809   sizeof (TestTypeNodeContainer),
810   1, /* number of entries */
811   NULL,
812   container_destroy,
813   dict_write_value,
814   dict_read_value,
815   dict_set_value,
816   dict_build_signature,
817   NULL,
818   NULL
819 };
820
821 static dbus_bool_t arrays_write_fixed_in_blocks = FALSE;
822
823 static const TestTypeNodeClass array_0_class = {
824   DBUS_TYPE_ARRAY,
825   sizeof (TestTypeNodeContainer),
826   0, /* number of array elements */
827   NULL,
828   container_destroy,
829   array_write_value,
830   array_read_value,
831   array_set_value,
832   array_build_signature,
833   NULL,
834   NULL
835 };
836
837 static const TestTypeNodeClass array_1_class = {
838   DBUS_TYPE_ARRAY,
839   sizeof (TestTypeNodeContainer),
840   1, /* number of array elements */
841   NULL,
842   container_destroy,
843   array_write_value,
844   array_read_value,
845   array_set_value,
846   array_build_signature,
847   NULL,
848   NULL
849 };
850
851 static const TestTypeNodeClass array_2_class = {
852   DBUS_TYPE_ARRAY,
853   sizeof (TestTypeNodeContainer),
854   2, /* number of array elements */
855   NULL,
856   container_destroy,
857   array_write_value,
858   array_read_value,
859   array_set_value,
860   array_build_signature,
861   NULL,
862   NULL
863 };
864
865 static const TestTypeNodeClass array_9_class = {
866   DBUS_TYPE_ARRAY,
867   sizeof (TestTypeNodeContainer),
868   9, /* number of array elements */
869   NULL,
870   container_destroy,
871   array_write_value,
872   array_read_value,
873   array_set_value,
874   array_build_signature,
875   NULL,
876   NULL
877 };
878
879 static const TestTypeNodeClass variant_class = {
880   DBUS_TYPE_VARIANT,
881   sizeof (TestTypeNodeContainer),
882   0,
883   NULL,
884   container_destroy,
885   variant_write_value,
886   variant_read_value,
887   variant_set_value,
888   NULL,
889   NULL,
890   NULL
891 };
892
893 static const TestTypeNodeClass* const
894 basic_nodes[] = {
895   &int16_class,
896   &uint16_class,
897   &int32_class,
898   &uint32_class,
899   &int64_class,
900   &uint64_class,
901   &bool_class,
902   &byte_class,
903   &double_class,
904   &string_0_class,
905   &string_1_class,
906   &string_3_class,
907   &string_8_class,
908   &object_path_class,
909   &signature_class
910 };
911 #define N_BASICS (_DBUS_N_ELEMENTS (basic_nodes))
912
913 static const TestTypeNodeClass* const
914 container_nodes[] = {
915   &struct_1_class,
916   &array_1_class,
917   &struct_2_class,
918   &array_0_class,
919   &array_2_class,
920   &variant_class,
921   &dict_1_class /* last since we want struct and array before it */
922   /* array_9_class is omitted on purpose, it's too slow;
923    * we only use it in one hardcoded test below
924    */
925 };
926 #define N_CONTAINERS (_DBUS_N_ELEMENTS (container_nodes))
927
928 static TestTypeNode*
929 node_new (const TestTypeNodeClass *klass)
930 {
931   TestTypeNode *node;
932
933   node = dbus_malloc0 (klass->instance_size);
934   if (node == NULL)
935     return NULL;
936
937   node->klass = klass;
938
939   if (klass->construct)
940     {
941       if (!(* klass->construct) (node))
942         {
943           dbus_free (node);
944           return NULL;
945         }
946     }
947
948   return node;
949 }
950
951 static void
952 node_destroy (TestTypeNode *node)
953 {
954   if (node->klass->destroy)
955     (* node->klass->destroy) (node);
956   dbus_free (node);
957 }
958
959 static dbus_bool_t
960 node_write_value (TestTypeNode   *node,
961                   DataBlock      *block,
962                   DBusTypeWriter *writer,
963                   int             seed)
964 {
965   dbus_bool_t retval;
966
967   retval = (* node->klass->write_value) (node, block, writer, seed);
968
969 #if 0
970   /* Handy to see where things break, but too expensive to do all the time */
971   data_block_verify (block);
972 #endif
973
974   return retval;
975 }
976
977 static dbus_bool_t
978 node_read_value (TestTypeNode   *node,
979                  DBusTypeReader *reader,
980                  int             seed)
981 {
982   /* DBusTypeReader restored; */
983
984   if (!(* node->klass->read_value) (node, reader, seed))
985     return FALSE;
986
987   return TRUE;
988 }
989
990 /* Warning: if this one fails due to OOM, it has side effects (can
991  * modify only some of the sub-values). OK in a test suite, but we
992  * never do this in real code.
993  */
994 static dbus_bool_t
995 node_set_value (TestTypeNode   *node,
996                 DBusTypeReader *reader,
997                 DBusTypeReader *realign_root,
998                 int             seed)
999 {
1000   if (!(* node->klass->set_value) (node, reader, realign_root, seed))
1001     return FALSE;
1002
1003   return TRUE;
1004 }
1005
1006 static dbus_bool_t
1007 node_build_signature (TestTypeNode *node,
1008                       DBusString   *str)
1009 {
1010   if (node->klass->build_signature)
1011     return (* node->klass->build_signature) (node, str);
1012   else
1013     return _dbus_string_append_byte (str, node->klass->typecode);
1014 }
1015
1016 static dbus_bool_t
1017 node_append_child (TestTypeNode *node,
1018                    TestTypeNode *child)
1019 {
1020   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
1021
1022   _dbus_assert (node->klass->instance_size >= (int) sizeof (TestTypeNodeContainer));
1023
1024   if (!_dbus_list_append (&container->children, child))
1025     _dbus_assert_not_reached ("no memory"); /* we never check the return value on node_append_child anyhow - it's run from outside the malloc-failure test code */
1026
1027   return TRUE;
1028 }
1029
1030 static dbus_bool_t
1031 node_write_multi (TestTypeNode   *node,
1032                   DataBlock      *block,
1033                   DBusTypeWriter *writer,
1034                   int             seed,
1035                   int             n_copies)
1036 {
1037   dbus_bool_t retval;
1038
1039   _dbus_assert (node->klass->write_multi != NULL);
1040   retval = (* node->klass->write_multi) (node, block, writer, seed, n_copies);
1041
1042 #if 0
1043   /* Handy to see where things break, but too expensive to do all the time */
1044   data_block_verify (block);
1045 #endif
1046
1047   return retval;
1048 }
1049
1050 static dbus_bool_t
1051 node_read_multi (TestTypeNode   *node,
1052                  DBusTypeReader *reader,
1053                  int             seed,
1054                  int             n_copies)
1055 {
1056   _dbus_assert (node->klass->read_multi != NULL);
1057
1058   if (!(* node->klass->read_multi) (node, reader, seed, n_copies))
1059     return FALSE;
1060
1061   return TRUE;
1062 }
1063
1064 static int n_iterations_completed_total = 0;
1065 static int n_iterations_completed_this_test = 0;
1066 static int n_iterations_expected_this_test = 0;
1067
1068 typedef struct
1069 {
1070   const DBusString   *signature;
1071   DataBlock          *block;
1072   int                 type_offset;
1073   TestTypeNode      **nodes;
1074   int                 n_nodes;
1075 } NodeIterationData;
1076
1077 static dbus_bool_t
1078 run_test_copy (NodeIterationData *nid)
1079 {
1080   DataBlock *src;
1081   DataBlock dest;
1082   dbus_bool_t retval;
1083   DBusTypeReader reader;
1084   DBusTypeWriter writer;
1085
1086   _dbus_verbose ("\n");
1087
1088   src = nid->block;
1089
1090   retval = FALSE;
1091
1092   if (!data_block_init (&dest, src->byte_order, src->initial_offset))
1093     return FALSE;
1094
1095   data_block_init_reader_writer (src, &reader, NULL);
1096   data_block_init_reader_writer (&dest, NULL, &writer);
1097
1098   /* DBusTypeWriter assumes it's writing into an existing signature,
1099    * so doesn't add nul on its own. We have to do that.
1100    */
1101   if (!_dbus_string_insert_byte (&dest.signature,
1102                                  dest.initial_offset, '\0'))
1103     goto out;
1104
1105   if (!_dbus_type_writer_write_reader (&writer, &reader))
1106     goto out;
1107
1108   /* Data blocks should now be identical */
1109   if (!_dbus_string_equal (&src->signature, &dest.signature))
1110     {
1111       _dbus_verbose ("SOURCE\n");
1112       _dbus_verbose_bytes_of_string (&src->signature, 0,
1113                                      _dbus_string_get_length (&src->signature));
1114       _dbus_verbose ("DEST\n");
1115       _dbus_verbose_bytes_of_string (&dest.signature, 0,
1116                                      _dbus_string_get_length (&dest.signature));
1117       _dbus_assert_not_reached ("signatures did not match");
1118     }
1119
1120   if (!_dbus_string_equal (&src->body, &dest.body))
1121     {
1122       _dbus_verbose ("SOURCE\n");
1123       _dbus_verbose_bytes_of_string (&src->body, 0,
1124                                      _dbus_string_get_length (&src->body));
1125       _dbus_verbose ("DEST\n");
1126       _dbus_verbose_bytes_of_string (&dest.body, 0,
1127                                      _dbus_string_get_length (&dest.body));
1128       _dbus_assert_not_reached ("bodies did not match");
1129     }
1130
1131   retval = TRUE;
1132
1133  out:
1134
1135   data_block_free (&dest);
1136
1137   return retval;
1138 }
1139
1140 static dbus_bool_t
1141 run_test_values_only_write (NodeIterationData *nid)
1142 {
1143   DBusTypeReader reader;
1144   DBusTypeWriter writer;
1145   int i;
1146   dbus_bool_t retval;
1147   int sig_len;
1148
1149   _dbus_verbose ("\n");
1150
1151   retval = FALSE;
1152
1153   data_block_reset (nid->block);
1154
1155   sig_len = _dbus_string_get_length (nid->signature);
1156
1157   _dbus_type_writer_init_values_only (&writer,
1158                                       nid->block->byte_order,
1159                                       nid->signature, 0,
1160                                       &nid->block->body,
1161                                       _dbus_string_get_length (&nid->block->body) - N_FENCE_BYTES);
1162   _dbus_type_reader_init (&reader,
1163                           nid->block->byte_order,
1164                           nid->signature, 0,
1165                           &nid->block->body,
1166                           nid->block->initial_offset);
1167
1168   i = 0;
1169   while (i < nid->n_nodes)
1170     {
1171       if (!node_write_value (nid->nodes[i], nid->block, &writer, i))
1172         goto out;
1173
1174       ++i;
1175     }
1176
1177   /* if we wrote any typecodes then this would fail */
1178   _dbus_assert (sig_len == _dbus_string_get_length (nid->signature));
1179
1180   /* But be sure we wrote out the values correctly */
1181   i = 0;
1182   while (i < nid->n_nodes)
1183     {
1184       if (!node_read_value (nid->nodes[i], &reader, i))
1185         goto out;
1186
1187       if (i + 1 == nid->n_nodes)
1188         NEXT_EXPECTING_FALSE (&reader);
1189       else
1190         NEXT_EXPECTING_TRUE (&reader);
1191
1192       ++i;
1193     }
1194
1195   retval = TRUE;
1196
1197  out:
1198   data_block_reset (nid->block);
1199   return retval;
1200 }
1201
1202 /* offset the seed for setting, so we set different numbers than
1203  * we originally wrote. Don't offset by a huge number since in
1204  * some cases it's value = possibilities[seed % n_possibilities]
1205  * and we don't want to wrap around. bool_from_seed
1206  * is just seed % 2 even.
1207  */
1208 #define SET_SEED 1
1209 static dbus_bool_t
1210 run_test_set_values (NodeIterationData *nid)
1211 {
1212   DBusTypeReader reader;
1213   DBusTypeReader realign_root;
1214   dbus_bool_t retval;
1215   int i;
1216
1217   _dbus_verbose ("\n");
1218
1219   retval = FALSE;
1220
1221   data_block_init_reader_writer (nid->block,
1222                                  &reader, NULL);
1223
1224   realign_root = reader;
1225
1226   i = 0;
1227   while (i < nid->n_nodes)
1228     {
1229       if (!node_set_value (nid->nodes[i],
1230                            &reader, &realign_root,
1231                            i + SET_SEED))
1232         goto out;
1233
1234       if (i + 1 == nid->n_nodes)
1235         NEXT_EXPECTING_FALSE (&reader);
1236       else
1237         NEXT_EXPECTING_TRUE (&reader);
1238
1239       ++i;
1240     }
1241
1242   /* Check that the new values were set */
1243
1244   reader = realign_root;
1245
1246   i = 0;
1247   while (i < nid->n_nodes)
1248     {
1249       if (!node_read_value (nid->nodes[i], &reader,
1250                             i + SET_SEED))
1251         goto out;
1252
1253       if (i + 1 == nid->n_nodes)
1254         NEXT_EXPECTING_FALSE (&reader);
1255       else
1256         NEXT_EXPECTING_TRUE (&reader);
1257
1258       ++i;
1259     }
1260
1261   retval = TRUE;
1262
1263  out:
1264   return retval;
1265 }
1266
1267 static dbus_bool_t
1268 run_test_delete_values (NodeIterationData *nid)
1269 {
1270   DBusTypeReader reader;
1271   dbus_bool_t retval;
1272   int t;
1273
1274   _dbus_verbose ("\n");
1275
1276   retval = FALSE;
1277
1278   data_block_init_reader_writer (nid->block,
1279                                  &reader, NULL);
1280
1281   while ((t = _dbus_type_reader_get_current_type (&reader)) != DBUS_TYPE_INVALID)
1282     {
1283       /* Right now, deleting only works on array elements.  We delete
1284        * all array elements, and then verify that there aren't any
1285        * left.
1286        */
1287       if (t == DBUS_TYPE_ARRAY)
1288         {
1289           DBusTypeReader array;
1290           int n_elements;
1291           int elem_type;
1292
1293           _dbus_type_reader_recurse (&reader, &array);
1294           n_elements = 0;
1295           while (_dbus_type_reader_get_current_type (&array) != DBUS_TYPE_INVALID)
1296             {
1297               n_elements += 1;
1298               _dbus_type_reader_next (&array);
1299             }
1300
1301           /* reset to start of array */
1302           _dbus_type_reader_recurse (&reader, &array);
1303           _dbus_verbose ("recursing into deletion loop reader.value_pos = %d array.value_pos = %d array.u.start_pos = %d\n",
1304                          reader.value_pos, array.value_pos, array.u.array.start_pos);
1305           while ((elem_type = _dbus_type_reader_get_current_type (&array)) != DBUS_TYPE_INVALID)
1306             {
1307               /* We don't want to always delete from the same part of the array. */
1308               static int cycle = 0;
1309               int elem;
1310
1311               _dbus_assert (n_elements > 0);
1312
1313               elem = cycle;
1314               if (elem == 3 || elem >= n_elements) /* end of array */
1315                 elem = n_elements - 1;
1316
1317               _dbus_verbose ("deleting array element %d of %d type %s cycle %d reader pos %d elem pos %d\n",
1318                              elem, n_elements, _dbus_type_to_string (elem_type),
1319                              cycle, reader.value_pos, array.value_pos);
1320               while (elem > 0)
1321                 {
1322                   if (!_dbus_type_reader_next (&array))
1323                     _dbus_assert_not_reached ("should have had another element\n");
1324                   --elem;
1325                 }
1326
1327               if (!_dbus_type_reader_delete (&array, &reader))
1328                 goto out;
1329
1330               n_elements -= 1;
1331
1332               /* reset */
1333               _dbus_type_reader_recurse (&reader, &array);
1334
1335               if (cycle > 2)
1336                 cycle = 0;
1337               else
1338                 cycle += 1;
1339             }
1340         }
1341       _dbus_type_reader_next (&reader);
1342     }
1343
1344   /* Check that there are no array elements left */
1345   data_block_init_reader_writer (nid->block,
1346                                  &reader, NULL);
1347
1348   while ((t = _dbus_type_reader_get_current_type (&reader)) != DBUS_TYPE_INVALID)
1349     {
1350       _dbus_type_reader_next (&reader);
1351     }
1352
1353   retval = TRUE;
1354
1355  out:
1356   return retval;
1357 }
1358
1359 static dbus_bool_t
1360 run_test_nodes_iteration (void *data)
1361 {
1362   NodeIterationData *nid = data;
1363   DBusTypeReader reader;
1364   DBusTypeWriter writer;
1365   int i;
1366   dbus_bool_t retval;
1367
1368   /* Stuff to do:
1369    * 1. write the value
1370    * 2. strcmp-compare with the signature we built
1371    * 3. read the value
1372    * 4. type-iterate the signature and the value and see if they are the same type-wise
1373    */
1374   retval = FALSE;
1375
1376   data_block_init_reader_writer (nid->block,
1377                                  &reader, &writer);
1378
1379   /* DBusTypeWriter assumes it's writing into an existing signature,
1380    * so doesn't add nul on its own. We have to do that.
1381    */
1382   if (!_dbus_string_insert_byte (&nid->block->signature,
1383                                  nid->type_offset, '\0'))
1384     goto out;
1385
1386   i = 0;
1387   while (i < nid->n_nodes)
1388     {
1389       if (!node_write_value (nid->nodes[i], nid->block, &writer, i))
1390         goto out;
1391
1392       ++i;
1393     }
1394
1395   if (!_dbus_string_equal_substring (nid->signature, 0, _dbus_string_get_length (nid->signature),
1396                                      &nid->block->signature, nid->type_offset))
1397     {
1398       _dbus_warn ("Expected signature '%s' and got '%s' with initial offset %d\n",
1399                   _dbus_string_get_const_data (nid->signature),
1400                   _dbus_string_get_const_data_len (&nid->block->signature, nid->type_offset, 0),
1401                   nid->type_offset);
1402       _dbus_assert_not_reached ("wrong signature");
1403     }
1404
1405   i = 0;
1406   while (i < nid->n_nodes)
1407     {
1408       if (!node_read_value (nid->nodes[i], &reader, i))
1409         goto out;
1410
1411       if (i + 1 == nid->n_nodes)
1412         NEXT_EXPECTING_FALSE (&reader);
1413       else
1414         NEXT_EXPECTING_TRUE (&reader);
1415
1416       ++i;
1417     }
1418
1419   if (n_iterations_expected_this_test <= MAX_ITERATIONS_FOR_EXPENSIVE_TESTS)
1420     {
1421       /* this set values test uses code from copy and
1422        * values_only_write so would ideally be last so you get a
1423        * simpler test case for problems with copying or values_only
1424        * writing; but it also needs an already-written DataBlock so it
1425        * has to go first. Comment it out if it breaks, and see if the
1426        * later tests also break - debug them first if so.
1427        */
1428       if (!run_test_set_values (nid))
1429         goto out;
1430
1431       if (!run_test_delete_values (nid))
1432         goto out;
1433
1434       if (!run_test_copy (nid))
1435         goto out;
1436
1437       if (!run_test_values_only_write (nid))
1438         goto out;
1439     }
1440
1441   /* FIXME type-iterate both signature and value and compare the resulting
1442    * tree to the node tree perhaps
1443    */
1444
1445   retval = TRUE;
1446
1447  out:
1448
1449   data_block_reset (nid->block);
1450
1451   return retval;
1452 }
1453
1454 static void
1455 run_test_nodes_in_one_configuration (TestTypeNode    **nodes,
1456                                      int               n_nodes,
1457                                      const DBusString *signature,
1458                                      int               byte_order,
1459                                      int               initial_offset)
1460 {
1461   DataBlock block;
1462   NodeIterationData nid;
1463
1464   if (!data_block_init (&block, byte_order, initial_offset))
1465     _dbus_assert_not_reached ("no memory");
1466
1467   nid.signature = signature;
1468   nid.block = &block;
1469   nid.type_offset = initial_offset;
1470   nid.nodes = nodes;
1471   nid.n_nodes = n_nodes;
1472
1473   if (TEST_OOM_HANDLING &&
1474       n_iterations_expected_this_test <= MAX_ITERATIONS_FOR_EXPENSIVE_TESTS)
1475     {
1476       _dbus_test_oom_handling ("running test node",
1477                                run_test_nodes_iteration,
1478                                &nid);
1479     }
1480   else
1481     {
1482       if (!run_test_nodes_iteration (&nid))
1483         _dbus_assert_not_reached ("no memory");
1484     }
1485
1486   data_block_free (&block);
1487 }
1488
1489 static void
1490 run_test_nodes (TestTypeNode **nodes,
1491                 int            n_nodes)
1492 {
1493   int i;
1494   DBusString signature;
1495
1496   if (!_dbus_string_init (&signature))
1497     _dbus_assert_not_reached ("no memory");
1498
1499   i = 0;
1500   while (i < n_nodes)
1501     {
1502       if (! node_build_signature (nodes[i], &signature))
1503         _dbus_assert_not_reached ("no memory");
1504
1505       ++i;
1506     }
1507
1508   _dbus_verbose (">>> test nodes with signature '%s'\n",
1509                  _dbus_string_get_const_data (&signature));
1510
1511   i = 0;
1512   while (i <= MAX_INITIAL_OFFSET)
1513     {
1514       run_test_nodes_in_one_configuration (nodes, n_nodes, &signature,
1515                                            DBUS_LITTLE_ENDIAN, i);
1516       run_test_nodes_in_one_configuration (nodes, n_nodes, &signature,
1517                                            DBUS_BIG_ENDIAN, i);
1518
1519       ++i;
1520     }
1521
1522   n_iterations_completed_this_test += 1;
1523   n_iterations_completed_total += 1;
1524
1525   if (n_iterations_completed_this_test == n_iterations_expected_this_test)
1526     {
1527       fprintf (stderr, " 100%% %d this test (%d cumulative)\n",
1528                n_iterations_completed_this_test,
1529                n_iterations_completed_total);
1530     }
1531   /* this happens to turn out well with mod == 1 */
1532   else if ((n_iterations_completed_this_test %
1533             (int)(n_iterations_expected_this_test / 10.0)) == 1)
1534     {
1535       fprintf (stderr, " %d%% ", (int) (n_iterations_completed_this_test / (double) n_iterations_expected_this_test * 100));
1536     }
1537
1538   _dbus_string_free (&signature);
1539 }
1540
1541 #define N_VALUES (N_BASICS * N_CONTAINERS + N_BASICS)
1542
1543 static TestTypeNode*
1544 value_generator (int *ip)
1545 {
1546   int i = *ip;
1547   const TestTypeNodeClass *child_klass;
1548   const TestTypeNodeClass *container_klass;
1549   TestTypeNode *child;
1550   TestTypeNode *node;
1551
1552   _dbus_assert (i <= N_VALUES);
1553
1554   if (i == N_VALUES)
1555     {
1556       return NULL;
1557     }
1558   else if (i < N_BASICS)
1559     {
1560       node = node_new (basic_nodes[i]);
1561     }
1562   else
1563     {
1564       /* imagine an array:
1565        * container 0 of basic 0
1566        * container 0 of basic 1
1567        * container 0 of basic 2
1568        * container 1 of basic 0
1569        * container 1 of basic 1
1570        * container 1 of basic 2
1571        */
1572       i -= N_BASICS;
1573
1574       container_klass = container_nodes[i / N_BASICS];
1575       child_klass = basic_nodes[i % N_BASICS];
1576
1577       node = node_new (container_klass);
1578       child = node_new (child_klass);
1579
1580       node_append_child (node, child);
1581     }
1582
1583   *ip += 1; /* increment the generator */
1584
1585   return node;
1586 }
1587
1588 static void
1589 build_body (TestTypeNode **nodes,
1590             int            n_nodes,
1591             int            byte_order,
1592             DBusString    *signature,
1593             DBusString    *body)
1594 {
1595   int i;
1596   DataBlock block;
1597   DBusTypeReader reader;
1598   DBusTypeWriter writer;
1599
1600   i = 0;
1601   while (i < n_nodes)
1602     {
1603       if (! node_build_signature (nodes[i], signature))
1604         _dbus_assert_not_reached ("no memory");
1605       
1606       ++i;
1607     }
1608
1609   if (!data_block_init (&block, byte_order, 0))
1610     _dbus_assert_not_reached ("no memory");
1611   
1612   data_block_init_reader_writer (&block,
1613                                  &reader, &writer);
1614   
1615   /* DBusTypeWriter assumes it's writing into an existing signature,
1616    * so doesn't add nul on its own. We have to do that.
1617    */
1618   if (!_dbus_string_insert_byte (&block.signature,
1619                                  0, '\0'))
1620     _dbus_assert_not_reached ("no memory");
1621
1622   i = 0;
1623   while (i < n_nodes)
1624     {
1625       if (!node_write_value (nodes[i], &block, &writer, i))
1626         _dbus_assert_not_reached ("no memory");
1627
1628       ++i;
1629     }
1630
1631   if (!_dbus_string_copy_len (&block.body, 0,
1632                               _dbus_string_get_length (&block.body) - N_FENCE_BYTES,
1633                               body, 0))
1634     _dbus_assert_not_reached ("oom");
1635
1636   data_block_free (&block);  
1637 }
1638
1639 dbus_bool_t
1640 dbus_internal_do_not_use_generate_bodies (int           sequence,
1641                                           int           byte_order,
1642                                           DBusString   *signature,
1643                                           DBusString   *body)
1644 {
1645   TestTypeNode *nodes[1];
1646   int i;
1647   int n_nodes;
1648
1649   nodes[0] = value_generator (&sequence);
1650
1651   if (nodes[0] == NULL)
1652     return FALSE;
1653
1654   n_nodes = 1;
1655   
1656   build_body (nodes, n_nodes, byte_order, signature, body);
1657
1658
1659   i = 0;
1660   while (i < n_nodes)
1661     {
1662       node_destroy (nodes[i]);
1663       ++i;
1664     }
1665   
1666   return TRUE;
1667 }
1668
1669 static void
1670 make_and_run_values_inside_container (const TestTypeNodeClass *container_klass,
1671                                       int                      n_nested)
1672 {
1673   TestTypeNode *root;
1674   TestTypeNode *container;
1675   TestTypeNode *child;
1676   int i;
1677
1678   root = node_new (container_klass);
1679   container = root;
1680   for (i = 1; i < n_nested; i++)
1681     {
1682       child = node_new (container_klass);
1683       node_append_child (container, child);
1684       container = child;
1685     }
1686
1687   /* container should now be the most-nested container */
1688
1689   i = 0;
1690   while ((child = value_generator (&i)))
1691     {
1692       node_append_child (container, child);
1693
1694       run_test_nodes (&root, 1);
1695
1696       _dbus_list_clear (&((TestTypeNodeContainer*)container)->children);
1697       node_destroy (child);
1698     }
1699
1700   node_destroy (root);
1701 }
1702
1703 static void
1704 start_next_test (const char *format,
1705                  int         expected)
1706 {
1707   n_iterations_completed_this_test = 0;
1708   n_iterations_expected_this_test = expected;
1709
1710   fprintf (stderr, ">>> >>> ");
1711   fprintf (stderr, format,
1712            n_iterations_expected_this_test);
1713 }
1714
1715 static void
1716 make_and_run_test_nodes (void)
1717 {
1718   int i, j, k, m;
1719
1720   /* We try to do this in order of "complicatedness" so that test
1721    * failures tend to show up in the simplest test case that
1722    * demonstrates the failure.  There are also some tests that run
1723    * more than once for this reason, first while going through simple
1724    * cases, second while going through a broader range of complex
1725    * cases.
1726    */
1727   /* Each basic node. The basic nodes should include:
1728    *
1729    * - each fixed-size type (in such a way that it has different values each time,
1730    *                         so we can tell if we mix two of them up)
1731    * - strings of various lengths
1732    * - object path
1733    * - signature
1734    */
1735   /* Each container node. The container nodes should include:
1736    *
1737    *  struct with 1 and 2 copies of the contained item
1738    *  array with 0, 1, 2 copies of the contained item
1739    *  variant
1740    */
1741   /*  Let a "value" be a basic node, or a container containing a single basic node.
1742    *  Let n_values be the number of such values i.e. (n_container * n_basic + n_basic)
1743    *  When iterating through all values to make combinations, do the basic types
1744    *  first and the containers second.
1745    */
1746   /* Each item is shown with its number of iterations to complete so
1747    * we can keep a handle on this unit test
1748    */
1749
1750   /* FIXME test just an empty body, no types at all */
1751
1752   start_next_test ("Each value by itself %d iterations\n", N_VALUES);
1753   {
1754     TestTypeNode *node;
1755     i = 0;
1756     while ((node = value_generator (&i)))
1757       {
1758         run_test_nodes (&node, 1);
1759
1760         node_destroy (node);
1761       }
1762   }
1763
1764   start_next_test ("Each value by itself with arrays as blocks %d iterations\n", N_VALUES);
1765   arrays_write_fixed_in_blocks = TRUE;
1766   {
1767     TestTypeNode *node;
1768     i = 0;
1769     while ((node = value_generator (&i)))
1770       {
1771         run_test_nodes (&node, 1);
1772
1773         node_destroy (node);
1774       }
1775   }
1776   arrays_write_fixed_in_blocks = FALSE;
1777
1778   start_next_test ("All values in one big toplevel %d iteration\n", 1);
1779   {
1780     TestTypeNode *nodes[N_VALUES];
1781     TestTypeNode *node;
1782
1783     i = 0;
1784     while ((node = value_generator (&i)))
1785       {
1786         nodes[i - 1] = node;
1787       }
1788
1789     run_test_nodes (nodes, N_VALUES);
1790
1791     for (i = 0; i < N_VALUES; i++)
1792       node_destroy (nodes[i]);
1793   }
1794
1795   start_next_test ("Each value,value pair combination as toplevel, in both orders %d iterations\n",
1796                    N_VALUES * N_VALUES);
1797   {
1798     TestTypeNode *nodes[2];
1799
1800     i = 0;
1801     while ((nodes[0] = value_generator (&i)))
1802       {
1803         j = 0;
1804         while ((nodes[1] = value_generator (&j)))
1805           {
1806             run_test_nodes (nodes, 2);
1807
1808             node_destroy (nodes[1]);
1809           }
1810
1811         node_destroy (nodes[0]);
1812       }
1813   }
1814
1815   start_next_test ("Each container containing each value %d iterations\n",
1816                    N_CONTAINERS * N_VALUES);
1817   for (i = 0; i < N_CONTAINERS; i++)
1818     {
1819       const TestTypeNodeClass *container_klass = container_nodes[i];
1820
1821       make_and_run_values_inside_container (container_klass, 1);
1822     }
1823
1824   start_next_test ("Each container containing each value with arrays as blocks %d iterations\n",
1825                    N_CONTAINERS * N_VALUES);
1826   arrays_write_fixed_in_blocks = TRUE;
1827   for (i = 0; i < N_CONTAINERS; i++)
1828     {
1829       const TestTypeNodeClass *container_klass = container_nodes[i];
1830
1831       make_and_run_values_inside_container (container_klass, 1);
1832     }
1833   arrays_write_fixed_in_blocks = FALSE;
1834
1835   start_next_test ("Each container of same container of each value %d iterations\n",
1836                    N_CONTAINERS * N_VALUES);
1837   for (i = 0; i < N_CONTAINERS; i++)
1838     {
1839       const TestTypeNodeClass *container_klass = container_nodes[i];
1840
1841       make_and_run_values_inside_container (container_klass, 2);
1842     }
1843
1844   start_next_test ("Each container of same container of same container of each value %d iterations\n",
1845                    N_CONTAINERS * N_VALUES);
1846   for (i = 0; i < N_CONTAINERS; i++)
1847     {
1848       const TestTypeNodeClass *container_klass = container_nodes[i];
1849
1850       make_and_run_values_inside_container (container_klass, 3);
1851     }
1852
1853   start_next_test ("Each value,value pair inside a struct %d iterations\n",
1854                    N_VALUES * N_VALUES);
1855   {
1856     TestTypeNode *val1, *val2;
1857     TestTypeNode *node;
1858
1859     node = node_new (&struct_1_class);
1860
1861     i = 0;
1862     while ((val1 = value_generator (&i)))
1863       {
1864         j = 0;
1865         while ((val2 = value_generator (&j)))
1866           {
1867             TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
1868
1869             node_append_child (node, val1);
1870             node_append_child (node, val2);
1871
1872             run_test_nodes (&node, 1);
1873
1874             _dbus_list_clear (&container->children);
1875             node_destroy (val2);
1876           }
1877         node_destroy (val1);
1878       }
1879     node_destroy (node);
1880   }
1881
1882   start_next_test ("All values in one big struct %d iteration\n",
1883                    1);
1884   {
1885     TestTypeNode *node;
1886     TestTypeNode *child;
1887
1888     node = node_new (&struct_1_class);
1889
1890     i = 0;
1891     while ((child = value_generator (&i)))
1892       node_append_child (node, child);
1893
1894     run_test_nodes (&node, 1);
1895
1896     node_destroy (node);
1897   }
1898
1899   start_next_test ("Each value in a large array %d iterations\n",
1900                    N_VALUES);
1901   {
1902     TestTypeNode *val;
1903     TestTypeNode *node;
1904
1905     node = node_new (&array_9_class);
1906
1907     i = 0;
1908     while ((val = value_generator (&i)))
1909       {
1910         TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
1911
1912         node_append_child (node, val);
1913
1914         run_test_nodes (&node, 1);
1915
1916         _dbus_list_clear (&container->children);
1917         node_destroy (val);
1918       }
1919
1920     node_destroy (node);
1921   }
1922
1923   if (_dbus_getenv ("DBUS_TEST_SLOW") == NULL ||
1924       atoi (_dbus_getenv ("DBUS_TEST_SLOW")) < 1)
1925     {
1926       fprintf (stderr, "skipping remaining marshal-recursive tests, "
1927           "run with DBUS_TEST_SLOW=1 (or more) to enable\n");
1928       goto out;
1929     }
1930
1931   start_next_test ("Each container of each container of each value %d iterations\n",
1932                    N_CONTAINERS * N_CONTAINERS * N_VALUES);
1933   for (i = 0; i < N_CONTAINERS; i++)
1934     {
1935       const TestTypeNodeClass *outer_container_klass = container_nodes[i];
1936       TestTypeNode *outer_container = node_new (outer_container_klass);
1937
1938       for (j = 0; j < N_CONTAINERS; j++)
1939         {
1940           TestTypeNode *child;
1941           const TestTypeNodeClass *inner_container_klass = container_nodes[j];
1942           TestTypeNode *inner_container = node_new (inner_container_klass);
1943
1944           node_append_child (outer_container, inner_container);
1945
1946           m = 0;
1947           while ((child = value_generator (&m)))
1948             {
1949               node_append_child (inner_container, child);
1950
1951               run_test_nodes (&outer_container, 1);
1952
1953               _dbus_list_clear (&((TestTypeNodeContainer*)inner_container)->children);
1954               node_destroy (child);
1955             }
1956           _dbus_list_clear (&((TestTypeNodeContainer*)outer_container)->children);
1957           node_destroy (inner_container);
1958         }
1959       node_destroy (outer_container);
1960     }
1961
1962   start_next_test ("Each container of each container of each container of each value %d iterations\n",
1963                    N_CONTAINERS * N_CONTAINERS * N_CONTAINERS * N_VALUES);
1964   for (i = 0; i < N_CONTAINERS; i++)
1965     {
1966       const TestTypeNodeClass *outer_container_klass = container_nodes[i];
1967       TestTypeNode *outer_container = node_new (outer_container_klass);
1968
1969       for (j = 0; j < N_CONTAINERS; j++)
1970         {
1971           const TestTypeNodeClass *inner_container_klass = container_nodes[j];
1972           TestTypeNode *inner_container = node_new (inner_container_klass);
1973
1974           node_append_child (outer_container, inner_container);
1975
1976           for (k = 0; k < N_CONTAINERS; k++)
1977             {
1978               TestTypeNode *child;
1979               const TestTypeNodeClass *center_container_klass = container_nodes[k];
1980               TestTypeNode *center_container = node_new (center_container_klass);
1981
1982               node_append_child (inner_container, center_container);
1983
1984               m = 0;
1985               while ((child = value_generator (&m)))
1986                 {
1987                   node_append_child (center_container, child);
1988
1989                   run_test_nodes (&outer_container, 1);
1990
1991                   _dbus_list_clear (&((TestTypeNodeContainer*)center_container)->children);
1992                   node_destroy (child);
1993                 }
1994               _dbus_list_clear (&((TestTypeNodeContainer*)inner_container)->children);
1995               node_destroy (center_container);
1996             }
1997           _dbus_list_clear (&((TestTypeNodeContainer*)outer_container)->children);
1998           node_destroy (inner_container);
1999         }
2000       node_destroy (outer_container);
2001     }
2002
2003   /* This one takes a really long time (10 minutes on a Core2), so only enable
2004    * it if you're really sure */
2005   if (atoi (_dbus_getenv ("DBUS_TEST_SLOW")) < 2)
2006     {
2007       fprintf (stderr, "skipping really slow marshal-recursive test, "
2008           "run with DBUS_TEST_SLOW=2 (or more) to enable\n");
2009       goto out;
2010     }
2011
2012   start_next_test ("Each value,value,value triplet combination as toplevel, in all orders %d iterations\n",
2013                    N_VALUES * N_VALUES * N_VALUES);
2014   {
2015     TestTypeNode *nodes[3];
2016
2017     i = 0;
2018     while ((nodes[0] = value_generator (&i)))
2019       {
2020         j = 0;
2021         while ((nodes[1] = value_generator (&j)))
2022           {
2023             k = 0;
2024             while ((nodes[2] = value_generator (&k)))
2025               {
2026                 run_test_nodes (nodes, 3);
2027
2028                 node_destroy (nodes[2]);
2029               }
2030             node_destroy (nodes[1]);
2031           }
2032         node_destroy (nodes[0]);
2033       }
2034   }
2035
2036 out:
2037   fprintf (stderr, "%d total iterations of recursive marshaling tests\n",
2038            n_iterations_completed_total);
2039   fprintf (stderr, "each iteration ran at initial offsets 0 through %d in both big and little endian\n",
2040            MAX_INITIAL_OFFSET);
2041   fprintf (stderr, "out of memory handling %s tested\n",
2042            TEST_OOM_HANDLING ? "was" : "was not");
2043 }
2044
2045 dbus_bool_t
2046 _dbus_marshal_recursive_test (void)
2047 {
2048   make_and_run_test_nodes ();
2049
2050   return TRUE;
2051 }
2052
2053 /*
2054  *
2055  *
2056  *         Implementations of each type node class
2057  *
2058  *
2059  *
2060  */
2061 #define MAX_MULTI_COUNT 5
2062
2063 #define SAMPLE_INT16           1234
2064 #define SAMPLE_INT16_ALTERNATE 6785
2065 static dbus_int16_t
2066 int16_from_seed (int seed)
2067 {
2068   /* Generate an integer value that's predictable from seed.  We could
2069    * just use seed itself, but that would only ever touch one byte of
2070    * the int so would miss some kinds of bug.
2071    */
2072   dbus_int16_t v;
2073
2074   v = 42; /* just to quiet compiler afaik */
2075   switch (seed % 5)
2076     {
2077     case 0:
2078       v = SAMPLE_INT16;
2079       break;
2080     case 1:
2081       v = SAMPLE_INT16_ALTERNATE;
2082       break;
2083     case 2:
2084       v = -1;
2085       break;
2086     case 3:
2087       v = _DBUS_INT16_MAX;
2088       break;
2089     case 4:
2090       v = 1;
2091       break;
2092     }
2093
2094   if (seed > 1)
2095     v *= seed; /* wraps around eventually, which is fine */
2096
2097   return v;
2098 }
2099
2100 static dbus_bool_t
2101 int16_write_value (TestTypeNode   *node,
2102                    DataBlock      *block,
2103                    DBusTypeWriter *writer,
2104                    int             seed)
2105 {
2106   /* also used for uint16 */
2107   dbus_int16_t v;
2108
2109   v = int16_from_seed (seed);
2110
2111   return _dbus_type_writer_write_basic (writer,
2112                                         node->klass->typecode,
2113                                         &v);
2114 }
2115
2116 static dbus_bool_t
2117 int16_read_value (TestTypeNode   *node,
2118                   DBusTypeReader *reader,
2119                   int             seed)
2120 {
2121   /* also used for uint16 */
2122   dbus_int16_t v;
2123
2124   check_expected_type (reader, node->klass->typecode);
2125
2126   _dbus_type_reader_read_basic (reader,
2127                                 (dbus_int16_t*) &v);
2128
2129   _dbus_assert (v == int16_from_seed (seed));
2130
2131   return TRUE;
2132 }
2133
2134 static dbus_bool_t
2135 int16_set_value (TestTypeNode   *node,
2136                  DBusTypeReader *reader,
2137                  DBusTypeReader *realign_root,
2138                  int             seed)
2139 {
2140   /* also used for uint16 */
2141   dbus_int16_t v;
2142
2143   v = int16_from_seed (seed);
2144
2145   return _dbus_type_reader_set_basic (reader,
2146                                       &v,
2147                                       realign_root);
2148 }
2149
2150 static dbus_bool_t
2151 int16_write_multi (TestTypeNode   *node,
2152                    DataBlock      *block,
2153                    DBusTypeWriter *writer,
2154                    int             seed,
2155                    int             count)
2156 {
2157   /* also used for uint16 */
2158   dbus_int16_t values[MAX_MULTI_COUNT];
2159   dbus_int16_t *v_ARRAY_INT16 = values;
2160   int i;
2161
2162   for (i = 0; i < count; ++i)
2163     values[i] = int16_from_seed (seed + i);
2164
2165   return _dbus_type_writer_write_fixed_multi (writer,
2166                                               node->klass->typecode,
2167                                               &v_ARRAY_INT16, count);
2168 }
2169
2170 static dbus_bool_t
2171 int16_read_multi (TestTypeNode   *node,
2172                   DBusTypeReader *reader,
2173                   int             seed,
2174                   int             count)
2175 {
2176   /* also used for uint16 */
2177   dbus_int16_t *values;
2178   int n_elements;
2179   int i;
2180
2181   check_expected_type (reader, node->klass->typecode);
2182
2183   _dbus_type_reader_read_fixed_multi (reader,
2184                                       &values,
2185                                       &n_elements);
2186
2187   if (n_elements != count)
2188     _dbus_warn ("got %d elements expected %d\n", n_elements, count);
2189   _dbus_assert (n_elements == count);
2190
2191   for (i = 0; i < count; i++)
2192     _dbus_assert (((dbus_int16_t)_dbus_unpack_uint16 (reader->byte_order,
2193                                                       (const unsigned char*)values + (i * 2))) ==
2194                   int16_from_seed (seed + i));
2195
2196   return TRUE;
2197 }
2198
2199
2200 #define SAMPLE_INT32           12345678
2201 #define SAMPLE_INT32_ALTERNATE 53781429
2202 static dbus_int32_t
2203 int32_from_seed (int seed)
2204 {
2205   /* Generate an integer value that's predictable from seed.  We could
2206    * just use seed itself, but that would only ever touch one byte of
2207    * the int so would miss some kinds of bug.
2208    */
2209   dbus_int32_t v;
2210
2211   v = 42; /* just to quiet compiler afaik */
2212   switch (seed % 5)
2213     {
2214     case 0:
2215       v = SAMPLE_INT32;
2216       break;
2217     case 1:
2218       v = SAMPLE_INT32_ALTERNATE;
2219       break;
2220     case 2:
2221       v = -1;
2222       break;
2223     case 3:
2224       v = _DBUS_INT_MAX;
2225       break;
2226     case 4:
2227       v = 1;
2228       break;
2229     }
2230
2231   if (seed > 1)
2232     v *= seed; /* wraps around eventually, which is fine */
2233
2234   return v;
2235 }
2236
2237 static dbus_bool_t
2238 int32_write_value (TestTypeNode   *node,
2239                    DataBlock      *block,
2240                    DBusTypeWriter *writer,
2241                    int             seed)
2242 {
2243   /* also used for uint32 */
2244   dbus_int32_t v;
2245
2246   v = int32_from_seed (seed);
2247
2248   return _dbus_type_writer_write_basic (writer,
2249                                         node->klass->typecode,
2250                                         &v);
2251 }
2252
2253 static dbus_bool_t
2254 int32_read_value (TestTypeNode   *node,
2255                   DBusTypeReader *reader,
2256                   int             seed)
2257 {
2258   /* also used for uint32 */
2259   dbus_int32_t v;
2260
2261   check_expected_type (reader, node->klass->typecode);
2262
2263   _dbus_type_reader_read_basic (reader,
2264                                 (dbus_int32_t*) &v);
2265
2266   _dbus_assert (v == int32_from_seed (seed));
2267
2268   return TRUE;
2269 }
2270
2271 static dbus_bool_t
2272 int32_set_value (TestTypeNode   *node,
2273                  DBusTypeReader *reader,
2274                  DBusTypeReader *realign_root,
2275                  int             seed)
2276 {
2277   /* also used for uint32 */
2278   dbus_int32_t v;
2279
2280   v = int32_from_seed (seed);
2281
2282   return _dbus_type_reader_set_basic (reader,
2283                                       &v,
2284                                       realign_root);
2285 }
2286
2287 static dbus_bool_t
2288 int32_write_multi (TestTypeNode   *node,
2289                    DataBlock      *block,
2290                    DBusTypeWriter *writer,
2291                    int             seed,
2292                    int             count)
2293 {
2294   /* also used for uint32 */
2295   dbus_int32_t values[MAX_MULTI_COUNT];
2296   dbus_int32_t *v_ARRAY_INT32 = values;
2297   int i;
2298
2299   for (i = 0; i < count; ++i)
2300     values[i] = int32_from_seed (seed + i);
2301
2302   return _dbus_type_writer_write_fixed_multi (writer,
2303                                               node->klass->typecode,
2304                                               &v_ARRAY_INT32, count);
2305 }
2306
2307 static dbus_bool_t
2308 int32_read_multi (TestTypeNode   *node,
2309                   DBusTypeReader *reader,
2310                   int             seed,
2311                   int             count)
2312 {
2313   /* also used for uint32 */
2314   dbus_int32_t *values;
2315   int n_elements;
2316   int i;
2317
2318   check_expected_type (reader, node->klass->typecode);
2319
2320   _dbus_type_reader_read_fixed_multi (reader,
2321                                       &values,
2322                                       &n_elements);
2323
2324   if (n_elements != count)
2325     _dbus_warn ("got %d elements expected %d\n", n_elements, count);
2326   _dbus_assert (n_elements == count);
2327
2328   for (i = 0; i < count; i++)
2329     _dbus_assert (((int)_dbus_unpack_uint32 (reader->byte_order,
2330                                              (const unsigned char*)values + (i * 4))) ==
2331                   int32_from_seed (seed + i));
2332
2333   return TRUE;
2334 }
2335
2336 static dbus_int64_t
2337 int64_from_seed (int seed)
2338 {
2339   dbus_int32_t v32;
2340   dbus_int64_t v;
2341
2342   v32 = int32_from_seed (seed);
2343
2344   v = - (dbus_int32_t) ~ v32;
2345   v |= (((dbus_int64_t)v32) << 32);
2346
2347   return v;
2348 }
2349
2350 static dbus_bool_t
2351 int64_write_value (TestTypeNode   *node,
2352                    DataBlock      *block,
2353                    DBusTypeWriter *writer,
2354                    int             seed)
2355 {
2356   /* also used for uint64 */
2357   dbus_int64_t v;
2358
2359   v = int64_from_seed (seed);
2360
2361   return _dbus_type_writer_write_basic (writer,
2362                                         node->klass->typecode,
2363                                         &v);
2364 }
2365
2366 static dbus_bool_t
2367 int64_read_value (TestTypeNode   *node,
2368                   DBusTypeReader *reader,
2369                   int             seed)
2370 {
2371   /* also used for uint64 */
2372   dbus_int64_t v;
2373
2374   check_expected_type (reader, node->klass->typecode);
2375
2376   _dbus_type_reader_read_basic (reader,
2377                                 (dbus_int64_t*) &v);
2378
2379   _dbus_assert (v == int64_from_seed (seed));
2380
2381   return TRUE;
2382 }
2383
2384 static dbus_bool_t
2385 int64_set_value (TestTypeNode   *node,
2386                  DBusTypeReader *reader,
2387                  DBusTypeReader *realign_root,
2388                  int             seed)
2389 {
2390   /* also used for uint64 */
2391   dbus_int64_t v;
2392
2393   v = int64_from_seed (seed);
2394
2395   return _dbus_type_reader_set_basic (reader,
2396                                       &v,
2397                                       realign_root);
2398 }
2399
2400 #define MAX_SAMPLE_STRING_LEN 10
2401 static void
2402 string_from_seed (char *buf,
2403                   int   len,
2404                   int   seed)
2405 {
2406   int i;
2407   unsigned char v;
2408
2409   _dbus_assert (len < MAX_SAMPLE_STRING_LEN);
2410
2411   /* vary the length slightly, though we also have multiple string
2412    * value types for this, varying it here tests the set_value code
2413    */
2414   switch (seed % 3)
2415     {
2416     case 1:
2417       len += 2;
2418       break;
2419     case 2:
2420       len -= 2;
2421       break;
2422     }
2423   if (len < 0)
2424     len = 0;
2425
2426   v = (unsigned char) ('A' + seed);
2427
2428   i = 0;
2429   while (i < len)
2430     {
2431       if (v < 'A' || v > 'z')
2432         v = 'A';
2433
2434       buf[i] = v;
2435
2436       v += 1;
2437       ++i;
2438     }
2439
2440   buf[i] = '\0';
2441 }
2442
2443 static dbus_bool_t
2444 string_write_value (TestTypeNode   *node,
2445                     DataBlock      *block,
2446                     DBusTypeWriter *writer,
2447                     int             seed)
2448 {
2449   char buf[MAX_SAMPLE_STRING_LEN + 1]="";
2450   const char *v_string = buf;
2451
2452
2453   string_from_seed (buf, node->klass->subclass_detail,
2454                     seed);
2455
2456   return _dbus_type_writer_write_basic (writer,
2457                                         node->klass->typecode,
2458                                         &v_string);
2459 }
2460
2461 static dbus_bool_t
2462 string_read_value (TestTypeNode   *node,
2463                    DBusTypeReader *reader,
2464                    int             seed)
2465 {
2466   const char *v;
2467   char buf[MAX_SAMPLE_STRING_LEN + 1];
2468   v = buf;
2469
2470   check_expected_type (reader, node->klass->typecode);
2471
2472   _dbus_type_reader_read_basic (reader,
2473                                 (const char **) &v);
2474
2475   string_from_seed (buf, node->klass->subclass_detail,
2476                     seed);
2477
2478   if (strcmp (buf, v) != 0)
2479     {
2480       _dbus_warn ("read string '%s' expected '%s'\n",
2481                   v, buf);
2482       _dbus_assert_not_reached ("test failed");
2483     }
2484
2485   return TRUE;
2486 }
2487
2488 static dbus_bool_t
2489 string_set_value (TestTypeNode   *node,
2490                   DBusTypeReader *reader,
2491                   DBusTypeReader *realign_root,
2492                   int             seed)
2493 {
2494   char buf[MAX_SAMPLE_STRING_LEN + 1];
2495   const char *v_string = buf;
2496
2497   string_from_seed (buf, node->klass->subclass_detail,
2498                     seed);
2499
2500 #if RECURSIVE_MARSHAL_WRITE_TRACE
2501  {
2502    const char *old;
2503    _dbus_type_reader_read_basic (reader, &old);
2504    _dbus_verbose ("SETTING new string '%s' len %d in place of '%s' len %d\n",
2505                   v_string, strlen (v_string), old, strlen (old));
2506  }
2507 #endif
2508
2509   return _dbus_type_reader_set_basic (reader,
2510                                       &v_string,
2511                                       realign_root);
2512 }
2513
2514 #define BOOL_FROM_SEED(seed) ((dbus_bool_t)((seed) % 2))
2515
2516 static dbus_bool_t
2517 bool_write_value (TestTypeNode   *node,
2518                   DataBlock      *block,
2519                   DBusTypeWriter *writer,
2520                   int             seed)
2521 {
2522   dbus_bool_t v;
2523
2524   v = BOOL_FROM_SEED (seed);
2525
2526   return _dbus_type_writer_write_basic (writer,
2527                                         node->klass->typecode,
2528                                         &v);
2529 }
2530
2531 static dbus_bool_t
2532 bool_read_value (TestTypeNode   *node,
2533                  DBusTypeReader *reader,
2534                  int             seed)
2535 {
2536   dbus_bool_t v;
2537
2538   check_expected_type (reader, node->klass->typecode);
2539
2540   _dbus_type_reader_read_basic (reader,
2541                                 (unsigned char*) &v);
2542
2543   _dbus_assert (v == BOOL_FROM_SEED (seed));
2544
2545   return TRUE;
2546 }
2547
2548 static dbus_bool_t
2549 bool_set_value (TestTypeNode   *node,
2550                 DBusTypeReader *reader,
2551                 DBusTypeReader *realign_root,
2552                 int             seed)
2553 {
2554   dbus_bool_t v;
2555
2556   v = BOOL_FROM_SEED (seed);
2557
2558   return _dbus_type_reader_set_basic (reader,
2559                                       &v,
2560                                       realign_root);
2561 }
2562
2563 #define BYTE_FROM_SEED(seed) ((unsigned char) int32_from_seed (seed))
2564
2565 static dbus_bool_t
2566 byte_write_value (TestTypeNode   *node,
2567                   DataBlock      *block,
2568                   DBusTypeWriter *writer,
2569                   int             seed)
2570 {
2571   unsigned char v;
2572
2573   v = BYTE_FROM_SEED (seed);
2574
2575   return _dbus_type_writer_write_basic (writer,
2576                                         node->klass->typecode,
2577                                         &v);
2578 }
2579
2580 static dbus_bool_t
2581 byte_read_value (TestTypeNode   *node,
2582                  DBusTypeReader *reader,
2583                  int             seed)
2584 {
2585   unsigned char v;
2586
2587   check_expected_type (reader, node->klass->typecode);
2588
2589   _dbus_type_reader_read_basic (reader,
2590                                 (unsigned char*) &v);
2591
2592   _dbus_assert (v == BYTE_FROM_SEED (seed));
2593
2594   return TRUE;
2595 }
2596
2597
2598 static dbus_bool_t
2599 byte_set_value (TestTypeNode   *node,
2600                 DBusTypeReader *reader,
2601                 DBusTypeReader *realign_root,
2602                 int             seed)
2603 {
2604   unsigned char v;
2605
2606   v = BYTE_FROM_SEED (seed);
2607
2608   return _dbus_type_reader_set_basic (reader,
2609                                       &v,
2610                                       realign_root);
2611 }
2612
2613 static double
2614 double_from_seed (int seed)
2615 {
2616   return SAMPLE_INT32 * (double) seed + 0.3;
2617 }
2618
2619 static dbus_bool_t
2620 double_write_value (TestTypeNode   *node,
2621                     DataBlock      *block,
2622                     DBusTypeWriter *writer,
2623                     int             seed)
2624 {
2625   double v;
2626
2627   v = double_from_seed (seed);
2628
2629   return _dbus_type_writer_write_basic (writer,
2630                                         node->klass->typecode,
2631                                         &v);
2632 }
2633
2634 static dbus_bool_t
2635 double_read_value (TestTypeNode   *node,
2636                    DBusTypeReader *reader,
2637                    int             seed)
2638 {
2639   double v;
2640   double expected;
2641
2642   check_expected_type (reader, node->klass->typecode);
2643
2644   _dbus_type_reader_read_basic (reader,
2645                                 (double*) &v);
2646
2647   expected = double_from_seed (seed);
2648
2649   if (!_DBUS_DOUBLES_BITWISE_EQUAL (v, expected))
2650     {
2651       _dbus_warn ("Expected double %g got %g\n bits = 0x%" PRIx64 " vs.\n bits = 0x%" PRIx64 ")\n",
2652                   expected, v,
2653                   *(dbus_uint64_t*)(char*)&expected,
2654                   *(dbus_uint64_t*)(char*)&v);
2655       _dbus_assert_not_reached ("test failed");
2656     }
2657
2658   return TRUE;
2659 }
2660
2661 static dbus_bool_t
2662 double_set_value (TestTypeNode   *node,
2663                 DBusTypeReader *reader,
2664                 DBusTypeReader *realign_root,
2665                 int             seed)
2666 {
2667   double v;
2668
2669   v = double_from_seed (seed);
2670
2671   return _dbus_type_reader_set_basic (reader,
2672                                       &v,
2673                                       realign_root);
2674 }
2675
2676 #define MAX_SAMPLE_OBJECT_PATH_LEN 10
2677 static void
2678 object_path_from_seed (char *buf,
2679                        int   seed)
2680 {
2681   int i;
2682   unsigned char v;
2683   int len;
2684
2685   len = seed % 9;
2686   _dbus_assert (len < MAX_SAMPLE_OBJECT_PATH_LEN);
2687
2688   v = (unsigned char) ('A' + seed);
2689
2690   if (len < 2)
2691     {
2692       buf[0] = '/';
2693       i = 1;
2694     }
2695   else
2696     {
2697       i = 0;
2698       while (i + 1 < len)
2699         {
2700           if (v < 'A' || v > 'z')
2701             v = 'A';
2702
2703           buf[i] = '/';
2704           ++i;
2705           buf[i] = v;
2706           ++i;
2707           
2708           v += 1;
2709         }
2710     }
2711
2712   buf[i] = '\0';
2713 }
2714
2715 static dbus_bool_t
2716 object_path_write_value (TestTypeNode   *node,
2717                          DataBlock      *block,
2718                          DBusTypeWriter *writer,
2719                          int             seed)
2720 {
2721   char buf[MAX_SAMPLE_OBJECT_PATH_LEN + 1];
2722   const char *v_string = buf;
2723
2724   object_path_from_seed (buf, seed);
2725
2726   return _dbus_type_writer_write_basic (writer,
2727                                         node->klass->typecode,
2728                                         &v_string);
2729 }
2730
2731 static dbus_bool_t
2732 object_path_read_value (TestTypeNode   *node,
2733                         DBusTypeReader *reader,
2734                         int             seed)
2735 {
2736   const char *v;
2737   char buf[MAX_SAMPLE_OBJECT_PATH_LEN + 1];
2738
2739   check_expected_type (reader, node->klass->typecode);
2740
2741   _dbus_type_reader_read_basic (reader,
2742                                 (const char **) &v);
2743
2744   object_path_from_seed (buf, seed);
2745
2746   if (strcmp (buf, v) != 0)
2747     {
2748       _dbus_warn ("read object path '%s' expected '%s'\n",
2749                   v, buf);
2750       _dbus_assert_not_reached ("test failed");
2751     }
2752
2753   return TRUE;
2754 }
2755
2756 static dbus_bool_t
2757 object_path_set_value (TestTypeNode   *node,
2758                        DBusTypeReader *reader,
2759                        DBusTypeReader *realign_root,
2760                        int             seed)
2761 {
2762   char buf[MAX_SAMPLE_OBJECT_PATH_LEN + 1];
2763   const char *v_string = buf;
2764
2765   object_path_from_seed (buf, seed);
2766
2767   return _dbus_type_reader_set_basic (reader,
2768                                       &v_string,
2769                                       realign_root);
2770 }
2771
2772 #define MAX_SAMPLE_SIGNATURE_LEN 10
2773 static void
2774 signature_from_seed (char *buf,
2775                      int   seed)
2776 {
2777   /* try to avoid ascending, descending, or alternating length to help find bugs */
2778   const char *sample_signatures[] = {
2779     "asax",
2780     "",
2781     "asau(xxxx)",
2782     "x",
2783     "ai",
2784     "a(ii)"
2785   };
2786
2787   strcpy (buf, sample_signatures[seed % _DBUS_N_ELEMENTS(sample_signatures)]);
2788 }
2789
2790 static dbus_bool_t
2791 signature_write_value (TestTypeNode   *node,
2792                        DataBlock      *block,
2793                        DBusTypeWriter *writer,
2794                        int             seed)
2795 {
2796   char buf[MAX_SAMPLE_SIGNATURE_LEN + 1];
2797   const char *v_string = buf;
2798
2799   signature_from_seed (buf, seed);
2800
2801   return _dbus_type_writer_write_basic (writer,
2802                                         node->klass->typecode,
2803                                         &v_string);
2804 }
2805
2806 static dbus_bool_t
2807 signature_read_value (TestTypeNode   *node,
2808                       DBusTypeReader *reader,
2809                       int             seed)
2810 {
2811   const char *v;
2812   char buf[MAX_SAMPLE_SIGNATURE_LEN + 1];
2813
2814   check_expected_type (reader, node->klass->typecode);
2815
2816   _dbus_type_reader_read_basic (reader,
2817                                 (const char **) &v);
2818
2819   signature_from_seed (buf, seed);
2820
2821   if (strcmp (buf, v) != 0)
2822     {
2823       _dbus_warn ("read signature value '%s' expected '%s'\n",
2824                   v, buf);
2825       _dbus_assert_not_reached ("test failed");
2826     }
2827
2828   return TRUE;
2829 }
2830
2831
2832 static dbus_bool_t
2833 signature_set_value (TestTypeNode   *node,
2834                      DBusTypeReader *reader,
2835                      DBusTypeReader *realign_root,
2836                      int             seed)
2837 {
2838   char buf[MAX_SAMPLE_SIGNATURE_LEN + 1];
2839   const char *v_string = buf;
2840
2841   signature_from_seed (buf, seed);
2842
2843   return _dbus_type_reader_set_basic (reader,
2844                                       &v_string,
2845                                       realign_root);
2846 }
2847
2848 static dbus_bool_t
2849 struct_write_value (TestTypeNode   *node,
2850                     DataBlock      *block,
2851                     DBusTypeWriter *writer,
2852                     int             seed)
2853 {
2854   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
2855   DataBlockState saved;
2856   DBusTypeWriter sub;
2857   int i;
2858   int n_copies;
2859
2860   n_copies = node->klass->subclass_detail;
2861
2862   _dbus_assert (container->children != NULL);
2863
2864   data_block_save (block, &saved);
2865
2866   if (!_dbus_type_writer_recurse (writer, DBUS_TYPE_STRUCT,
2867                                   NULL, 0,
2868                                   &sub))
2869     return FALSE;
2870
2871   i = 0;
2872   while (i < n_copies)
2873     {
2874       DBusList *link;
2875
2876       link = _dbus_list_get_first_link (&container->children);
2877       while (link != NULL)
2878         {
2879           TestTypeNode *child = link->data;
2880           DBusList *next = _dbus_list_get_next_link (&container->children, link);
2881
2882           if (!node_write_value (child, block, &sub, seed + i))
2883             {
2884               data_block_restore (block, &saved);
2885               return FALSE;
2886             }
2887
2888           link = next;
2889         }
2890
2891       ++i;
2892     }
2893
2894   if (!_dbus_type_writer_unrecurse (writer, &sub))
2895     {
2896       data_block_restore (block, &saved);
2897       return FALSE;
2898     }
2899
2900   return TRUE;
2901 }
2902
2903 static dbus_bool_t
2904 struct_read_or_set_value (TestTypeNode   *node,
2905                           DBusTypeReader *reader,
2906                           DBusTypeReader *realign_root,
2907                           int             seed)
2908 {
2909   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
2910   DBusTypeReader sub;
2911   int i;
2912   int n_copies;
2913
2914   n_copies = node->klass->subclass_detail;
2915
2916   check_expected_type (reader, DBUS_TYPE_STRUCT);
2917
2918   _dbus_type_reader_recurse (reader, &sub);
2919
2920   i = 0;
2921   while (i < n_copies)
2922     {
2923       DBusList *link;
2924
2925       link = _dbus_list_get_first_link (&container->children);
2926       while (link != NULL)
2927         {
2928           TestTypeNode *child = link->data;
2929           DBusList *next = _dbus_list_get_next_link (&container->children, link);
2930
2931           if (realign_root == NULL)
2932             {
2933               if (!node_read_value (child, &sub, seed + i))
2934                 return FALSE;
2935             }
2936           else
2937             {
2938               if (!node_set_value (child, &sub, realign_root, seed + i))
2939                 return FALSE;
2940             }
2941
2942           if (i == (n_copies - 1) && next == NULL)
2943             NEXT_EXPECTING_FALSE (&sub);
2944           else
2945             NEXT_EXPECTING_TRUE (&sub);
2946
2947           link = next;
2948         }
2949
2950       ++i;
2951     }
2952
2953   return TRUE;
2954 }
2955
2956 static dbus_bool_t
2957 struct_read_value (TestTypeNode   *node,
2958                    DBusTypeReader *reader,
2959                    int             seed)
2960 {
2961   return struct_read_or_set_value (node, reader, NULL, seed);
2962 }
2963
2964 static dbus_bool_t
2965 struct_set_value (TestTypeNode   *node,
2966                   DBusTypeReader *reader,
2967                   DBusTypeReader *realign_root,
2968                   int             seed)
2969 {
2970   return struct_read_or_set_value (node, reader, realign_root, seed);
2971 }
2972
2973 static dbus_bool_t
2974 struct_build_signature (TestTypeNode   *node,
2975                         DBusString     *str)
2976 {
2977   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
2978   int i;
2979   int orig_len;
2980   int n_copies;
2981
2982   n_copies = node->klass->subclass_detail;
2983
2984   orig_len = _dbus_string_get_length (str);
2985
2986   if (!_dbus_string_append_byte (str, DBUS_STRUCT_BEGIN_CHAR))
2987     goto oom;
2988
2989   i = 0;
2990   while (i < n_copies)
2991     {
2992       DBusList *link;
2993
2994       link = _dbus_list_get_first_link (&container->children);
2995       while (link != NULL)
2996         {
2997           TestTypeNode *child = link->data;
2998           DBusList *next = _dbus_list_get_next_link (&container->children, link);
2999
3000           if (!node_build_signature (child, str))
3001             goto oom;
3002
3003           link = next;
3004         }
3005
3006       ++i;
3007     }
3008
3009   if (!_dbus_string_append_byte (str, DBUS_STRUCT_END_CHAR))
3010     goto oom;
3011
3012   return TRUE;
3013
3014  oom:
3015   _dbus_string_set_length (str, orig_len);
3016   return FALSE;
3017 }
3018
3019 static dbus_bool_t
3020 array_write_value (TestTypeNode   *node,
3021                    DataBlock      *block,
3022                    DBusTypeWriter *writer,
3023                    int             seed)
3024 {
3025   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3026   DataBlockState saved;
3027   DBusTypeWriter sub;
3028   DBusString element_signature;
3029   int i;
3030   int n_copies;
3031   int element_type;
3032   TestTypeNode *child;
3033
3034   n_copies = node->klass->subclass_detail;
3035
3036   _dbus_assert (container->children != NULL);
3037
3038   data_block_save (block, &saved);
3039
3040   if (!_dbus_string_init (&element_signature))
3041     return FALSE;
3042
3043   child = _dbus_list_get_first (&container->children);
3044
3045   if (!node_build_signature (child,
3046                              &element_signature))
3047     goto oom;
3048
3049   element_type = _dbus_first_type_in_signature (&element_signature, 0);
3050
3051   if (!_dbus_type_writer_recurse (writer, DBUS_TYPE_ARRAY,
3052                                   &element_signature, 0,
3053                                   &sub))
3054     goto oom;
3055
3056   if (arrays_write_fixed_in_blocks &&
3057       dbus_type_is_fixed (element_type) &&
3058       child->klass->write_multi)
3059     {
3060       if (!node_write_multi (child, block, &sub, seed, n_copies))
3061         goto oom;
3062     }
3063   else
3064     {
3065       i = 0;
3066       while (i < n_copies)
3067         {
3068           DBusList *link;
3069
3070           link = _dbus_list_get_first_link (&container->children);
3071           while (link != NULL)
3072             {
3073               TestTypeNode *child = link->data;
3074               DBusList *next = _dbus_list_get_next_link (&container->children, link);
3075
3076               if (!node_write_value (child, block, &sub, seed + i))
3077                 goto oom;
3078
3079               link = next;
3080             }
3081
3082           ++i;
3083         }
3084     }
3085
3086   if (!_dbus_type_writer_unrecurse (writer, &sub))
3087     goto oom;
3088
3089   _dbus_string_free (&element_signature);
3090   return TRUE;
3091
3092  oom:
3093   data_block_restore (block, &saved);
3094   _dbus_string_free (&element_signature);
3095   return FALSE;
3096 }
3097
3098 static dbus_bool_t
3099 array_read_or_set_value (TestTypeNode   *node,
3100                          DBusTypeReader *reader,
3101                          DBusTypeReader *realign_root,
3102                          int             seed)
3103 {
3104   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3105   DBusTypeReader sub;
3106   int i;
3107   int n_copies;
3108   TestTypeNode *child;
3109
3110   n_copies = node->klass->subclass_detail;
3111
3112   check_expected_type (reader, DBUS_TYPE_ARRAY);
3113
3114   child = _dbus_list_get_first (&container->children);
3115
3116   if (n_copies > 0)
3117     {
3118       _dbus_type_reader_recurse (reader, &sub);
3119
3120       if (realign_root == NULL && arrays_write_fixed_in_blocks &&
3121           dbus_type_is_fixed (_dbus_type_reader_get_element_type (reader)) &&
3122           child->klass->read_multi)
3123         {
3124           if (!node_read_multi (child, &sub, seed, n_copies))
3125             return FALSE;
3126         }
3127       else
3128         {
3129           i = 0;
3130           while (i < n_copies)
3131             {
3132               DBusList *link;
3133
3134               link = _dbus_list_get_first_link (&container->children);
3135               while (link != NULL)
3136                 {
3137                   TestTypeNode *child = link->data;
3138                   DBusList *next = _dbus_list_get_next_link (&container->children, link);
3139
3140                   _dbus_assert (child->klass->typecode ==
3141                                 _dbus_type_reader_get_element_type (reader));
3142
3143                   if (realign_root == NULL)
3144                     {
3145                       if (!node_read_value (child, &sub, seed + i))
3146                         return FALSE;
3147                     }
3148                   else
3149                     {
3150                       if (!node_set_value (child, &sub, realign_root, seed + i))
3151                         return FALSE;
3152                     }
3153
3154                   if (i == (n_copies - 1) && next == NULL)
3155                     NEXT_EXPECTING_FALSE (&sub);
3156                   else
3157                     NEXT_EXPECTING_TRUE (&sub);
3158
3159                   link = next;
3160                 }
3161
3162               ++i;
3163             }
3164         }
3165     }
3166
3167   return TRUE;
3168 }
3169
3170 static dbus_bool_t
3171 array_read_value (TestTypeNode   *node,
3172                   DBusTypeReader *reader,
3173                   int             seed)
3174 {
3175   return array_read_or_set_value (node, reader, NULL, seed);
3176 }
3177
3178 static dbus_bool_t
3179 array_set_value (TestTypeNode   *node,
3180                  DBusTypeReader *reader,
3181                  DBusTypeReader *realign_root,
3182                  int             seed)
3183 {
3184   return array_read_or_set_value (node, reader, realign_root, seed);
3185 }
3186
3187 static dbus_bool_t
3188 array_build_signature (TestTypeNode   *node,
3189                        DBusString     *str)
3190 {
3191   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3192   int orig_len;
3193
3194   orig_len = _dbus_string_get_length (str);
3195
3196   if (!_dbus_string_append_byte (str, DBUS_TYPE_ARRAY))
3197     goto oom;
3198
3199   if (!node_build_signature (_dbus_list_get_first (&container->children),
3200                              str))
3201     goto oom;
3202
3203   return TRUE;
3204
3205  oom:
3206   _dbus_string_set_length (str, orig_len);
3207   return FALSE;
3208 }
3209
3210  /* 10 is random just to add another seed that we use in the suite */
3211 #define VARIANT_SEED 10
3212
3213 static dbus_bool_t
3214 variant_write_value (TestTypeNode   *node,
3215                      DataBlock      *block,
3216                      DBusTypeWriter *writer,
3217                      int             seed)
3218 {
3219   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3220   DataBlockState saved;
3221   DBusTypeWriter sub;
3222   DBusString content_signature;
3223   TestTypeNode *child;
3224
3225   _dbus_assert (container->children != NULL);
3226   _dbus_assert (_dbus_list_length_is_one (&container->children));
3227
3228   child = _dbus_list_get_first (&container->children);
3229
3230   data_block_save (block, &saved);
3231
3232   if (!_dbus_string_init (&content_signature))
3233     return FALSE;
3234
3235   if (!node_build_signature (child,
3236                              &content_signature))
3237     goto oom;
3238
3239   if (!_dbus_type_writer_recurse (writer, DBUS_TYPE_VARIANT,
3240                                   &content_signature, 0,
3241                                   &sub))
3242     goto oom;
3243
3244   if (!node_write_value (child, block, &sub, seed + VARIANT_SEED))
3245     goto oom;
3246
3247   if (!_dbus_type_writer_unrecurse (writer, &sub))
3248     goto oom;
3249
3250   _dbus_string_free (&content_signature);
3251   return TRUE;
3252
3253  oom:
3254   data_block_restore (block, &saved);
3255   _dbus_string_free (&content_signature);
3256   return FALSE;
3257 }
3258
3259 static dbus_bool_t
3260 variant_read_or_set_value (TestTypeNode   *node,
3261                            DBusTypeReader *reader,
3262                            DBusTypeReader *realign_root,
3263                            int             seed)
3264 {
3265   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3266   DBusTypeReader sub;
3267   TestTypeNode *child;
3268
3269   _dbus_assert (container->children != NULL);
3270   _dbus_assert (_dbus_list_length_is_one (&container->children));
3271
3272   child = _dbus_list_get_first (&container->children);
3273
3274   check_expected_type (reader, DBUS_TYPE_VARIANT);
3275
3276   _dbus_type_reader_recurse (reader, &sub);
3277
3278   if (realign_root == NULL)
3279     {
3280       if (!node_read_value (child, &sub, seed + VARIANT_SEED))
3281         return FALSE;
3282     }
3283   else
3284     {
3285       if (!node_set_value (child, &sub, realign_root, seed + VARIANT_SEED))
3286         return FALSE;
3287     }
3288
3289   NEXT_EXPECTING_FALSE (&sub);
3290
3291   return TRUE;
3292 }
3293
3294 static dbus_bool_t
3295 variant_read_value (TestTypeNode   *node,
3296                     DBusTypeReader *reader,
3297                     int             seed)
3298 {
3299   return variant_read_or_set_value (node, reader, NULL, seed);
3300 }
3301
3302 static dbus_bool_t
3303 variant_set_value (TestTypeNode   *node,
3304                    DBusTypeReader *reader,
3305                    DBusTypeReader *realign_root,
3306                    int             seed)
3307 {
3308   return variant_read_or_set_value (node, reader, realign_root, seed);
3309 }
3310
3311 static dbus_bool_t
3312 dict_write_value (TestTypeNode   *node,
3313                   DataBlock      *block,
3314                   DBusTypeWriter *writer,
3315                   int             seed)
3316 {
3317   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3318   DataBlockState saved;
3319   DBusTypeWriter sub;
3320   DBusString entry_value_signature;
3321   DBusString dict_entry_signature;
3322   int i;
3323   int n_entries;
3324   TestTypeNode *child;
3325
3326   n_entries = node->klass->subclass_detail;
3327
3328   _dbus_assert (container->children != NULL);
3329
3330   data_block_save (block, &saved);
3331
3332   if (!_dbus_string_init (&entry_value_signature))
3333     return FALSE;
3334
3335   if (!_dbus_string_init (&dict_entry_signature))
3336     {
3337       _dbus_string_free (&entry_value_signature);
3338       return FALSE;
3339     }
3340   
3341   child = _dbus_list_get_first (&container->children);
3342
3343   if (!node_build_signature (child,
3344                              &entry_value_signature))
3345     goto oom;
3346
3347   if (!_dbus_string_append (&dict_entry_signature,
3348                             DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
3349                             DBUS_TYPE_INT32_AS_STRING))
3350     goto oom;
3351
3352   if (!_dbus_string_copy (&entry_value_signature, 0,
3353                           &dict_entry_signature,
3354                           _dbus_string_get_length (&dict_entry_signature)))
3355     goto oom;
3356
3357   if (!_dbus_string_append_byte (&dict_entry_signature,
3358                                  DBUS_DICT_ENTRY_END_CHAR))
3359     goto oom;
3360
3361   if (!_dbus_type_writer_recurse (writer, DBUS_TYPE_ARRAY,
3362                                   &dict_entry_signature, 0,
3363                                   &sub))
3364     goto oom;
3365
3366   i = 0;
3367   while (i < n_entries)
3368     {
3369       DBusTypeWriter entry_sub;
3370       dbus_int32_t key;
3371
3372       if (!_dbus_type_writer_recurse (&sub, DBUS_TYPE_DICT_ENTRY,
3373                                       NULL, 0,
3374                                       &entry_sub))
3375         goto oom;
3376
3377       key = int32_from_seed (seed + i);
3378
3379       if (!_dbus_type_writer_write_basic (&entry_sub,
3380                                           DBUS_TYPE_INT32,
3381                                           &key))
3382         goto oom;
3383       
3384       if (!node_write_value (child, block, &entry_sub, seed + i))
3385         goto oom;
3386
3387       if (!_dbus_type_writer_unrecurse (&sub, &entry_sub))
3388         goto oom;
3389       
3390       ++i;
3391     }
3392
3393   if (!_dbus_type_writer_unrecurse (writer, &sub))
3394     goto oom;
3395   
3396   _dbus_string_free (&entry_value_signature);
3397   _dbus_string_free (&dict_entry_signature);
3398   return TRUE;
3399
3400  oom:
3401   data_block_restore (block, &saved);
3402   _dbus_string_free (&entry_value_signature);
3403   _dbus_string_free (&dict_entry_signature);
3404   return FALSE;
3405 }
3406
3407 static dbus_bool_t
3408 dict_read_or_set_value (TestTypeNode   *node,
3409                         DBusTypeReader *reader,
3410                         DBusTypeReader *realign_root,
3411                         int             seed)
3412 {
3413   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3414   DBusTypeReader sub;
3415   int i;
3416   int n_entries;
3417   TestTypeNode *child;
3418
3419   n_entries = node->klass->subclass_detail;
3420
3421   check_expected_type (reader, DBUS_TYPE_ARRAY);
3422
3423   child = _dbus_list_get_first (&container->children);
3424
3425   if (n_entries > 0)
3426     {
3427       _dbus_type_reader_recurse (reader, &sub);
3428
3429       check_expected_type (&sub, DBUS_TYPE_DICT_ENTRY);
3430       
3431       i = 0;
3432       while (i < n_entries)
3433         {
3434           DBusTypeReader entry_sub;
3435
3436           check_expected_type (&sub, DBUS_TYPE_DICT_ENTRY);
3437           
3438           _dbus_type_reader_recurse (&sub, &entry_sub);
3439           
3440           if (realign_root == NULL)
3441             {
3442               dbus_int32_t v;
3443               
3444               check_expected_type (&entry_sub, DBUS_TYPE_INT32);
3445
3446               _dbus_type_reader_read_basic (&entry_sub,
3447                                             (dbus_int32_t*) &v);
3448
3449               _dbus_assert (v == int32_from_seed (seed + i));
3450
3451               NEXT_EXPECTING_TRUE (&entry_sub);
3452               
3453               if (!node_read_value (child, &entry_sub, seed + i))
3454                 return FALSE;
3455
3456               NEXT_EXPECTING_FALSE (&entry_sub);
3457             }
3458           else
3459             {
3460               dbus_int32_t v;
3461               
3462               v = int32_from_seed (seed + i);
3463               
3464               if (!_dbus_type_reader_set_basic (&entry_sub,
3465                                                 &v,
3466                                                 realign_root))
3467                 return FALSE;
3468
3469               NEXT_EXPECTING_TRUE (&entry_sub);
3470               
3471               if (!node_set_value (child, &entry_sub, realign_root, seed + i))
3472                 return FALSE;
3473
3474               NEXT_EXPECTING_FALSE (&entry_sub);
3475             }
3476           
3477           if (i == (n_entries - 1))
3478             NEXT_EXPECTING_FALSE (&sub);
3479           else
3480             NEXT_EXPECTING_TRUE (&sub);
3481
3482           ++i;
3483         }
3484     }
3485
3486   return TRUE;
3487 }
3488
3489 static dbus_bool_t
3490 dict_read_value (TestTypeNode   *node,
3491                  DBusTypeReader *reader,
3492                  int             seed)
3493 {
3494   return dict_read_or_set_value (node, reader, NULL, seed);
3495 }
3496
3497 static dbus_bool_t
3498 dict_set_value (TestTypeNode   *node,
3499                 DBusTypeReader *reader,
3500                 DBusTypeReader *realign_root,
3501                 int             seed)
3502 {
3503   return dict_read_or_set_value (node, reader, realign_root, seed);
3504 }
3505
3506 static dbus_bool_t
3507 dict_build_signature (TestTypeNode   *node,
3508                       DBusString     *str)
3509 {
3510   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3511   int orig_len;
3512
3513   orig_len = _dbus_string_get_length (str);
3514
3515   if (!_dbus_string_append_byte (str, DBUS_TYPE_ARRAY))
3516     goto oom;
3517
3518   if (!_dbus_string_append (str, DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING DBUS_TYPE_INT32_AS_STRING))
3519     goto oom;
3520   
3521   if (!node_build_signature (_dbus_list_get_first (&container->children),
3522                              str))
3523     goto oom;
3524
3525   if (!_dbus_string_append_byte (str, DBUS_DICT_ENTRY_END_CHAR))
3526     goto oom;
3527
3528   return TRUE;
3529
3530  oom:
3531   _dbus_string_set_length (str, orig_len);
3532   return FALSE;
3533 }
3534
3535 static void
3536 container_destroy (TestTypeNode *node)
3537 {
3538   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3539   DBusList *link;
3540
3541   link = _dbus_list_get_first_link (&container->children);
3542   while (link != NULL)
3543     {
3544       TestTypeNode *child = link->data;
3545       DBusList *next = _dbus_list_get_next_link (&container->children, link);
3546
3547       node_destroy (child);
3548
3549       _dbus_list_free_link (link);
3550
3551       link = next;
3552     }
3553 }
3554
3555 #endif /* !DOXYGEN_SHOULD_SKIP_THIS */
3556
3557 #endif /* DBUS_ENABLE_EMBEDDED_TESTS */