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