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