* tools/Makefile.am: Patch by Colin Walters that fixes distcheck
[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 FALSE;
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];
2462   const char *v_string = buf;
2463
2464   string_from_seed (buf, node->klass->subclass_detail,
2465                     seed);
2466
2467   return _dbus_type_writer_write_basic (writer,
2468                                         node->klass->typecode,
2469                                         &v_string);
2470 }
2471
2472 static dbus_bool_t
2473 string_read_value (TestTypeNode   *node,
2474                    DBusTypeReader *reader,
2475                    int             seed)
2476 {
2477   const char *v;
2478   char buf[MAX_SAMPLE_STRING_LEN];
2479
2480   check_expected_type (reader, node->klass->typecode);
2481
2482   _dbus_type_reader_read_basic (reader,
2483                                 (const char **) &v);
2484
2485   string_from_seed (buf, node->klass->subclass_detail,
2486                     seed);
2487
2488   if (strcmp (buf, v) != 0)
2489     {
2490       _dbus_warn ("read string '%s' expected '%s'\n",
2491                   v, buf);
2492       _dbus_assert_not_reached ("test failed");
2493     }
2494
2495   return TRUE;
2496 }
2497
2498 static dbus_bool_t
2499 string_set_value (TestTypeNode   *node,
2500                   DBusTypeReader *reader,
2501                   DBusTypeReader *realign_root,
2502                   int             seed)
2503 {
2504   char buf[MAX_SAMPLE_STRING_LEN];
2505   const char *v_string = buf;
2506
2507   string_from_seed (buf, node->klass->subclass_detail,
2508                     seed);
2509
2510 #if RECURSIVE_MARSHAL_WRITE_TRACE
2511  {
2512    const char *old;
2513    _dbus_type_reader_read_basic (reader, &old);
2514    _dbus_verbose ("SETTING new string '%s' len %d in place of '%s' len %d\n",
2515                   v_string, strlen (v_string), old, strlen (old));
2516  }
2517 #endif
2518
2519   return _dbus_type_reader_set_basic (reader,
2520                                       &v_string,
2521                                       realign_root);
2522 }
2523
2524 #define BOOL_FROM_SEED(seed) ((dbus_bool_t)((seed) % 2))
2525
2526 static dbus_bool_t
2527 bool_write_value (TestTypeNode   *node,
2528                   DataBlock      *block,
2529                   DBusTypeWriter *writer,
2530                   int             seed)
2531 {
2532   dbus_bool_t v;
2533
2534   v = BOOL_FROM_SEED (seed);
2535
2536   return _dbus_type_writer_write_basic (writer,
2537                                         node->klass->typecode,
2538                                         &v);
2539 }
2540
2541 static dbus_bool_t
2542 bool_read_value (TestTypeNode   *node,
2543                  DBusTypeReader *reader,
2544                  int             seed)
2545 {
2546   dbus_bool_t v;
2547
2548   check_expected_type (reader, node->klass->typecode);
2549
2550   _dbus_type_reader_read_basic (reader,
2551                                 (unsigned char*) &v);
2552
2553   _dbus_assert (v == BOOL_FROM_SEED (seed));
2554
2555   return TRUE;
2556 }
2557
2558 static dbus_bool_t
2559 bool_set_value (TestTypeNode   *node,
2560                 DBusTypeReader *reader,
2561                 DBusTypeReader *realign_root,
2562                 int             seed)
2563 {
2564   dbus_bool_t v;
2565
2566   v = BOOL_FROM_SEED (seed);
2567
2568   return _dbus_type_reader_set_basic (reader,
2569                                       &v,
2570                                       realign_root);
2571 }
2572
2573 #define BYTE_FROM_SEED(seed) ((unsigned char) int32_from_seed (seed))
2574
2575 static dbus_bool_t
2576 byte_write_value (TestTypeNode   *node,
2577                   DataBlock      *block,
2578                   DBusTypeWriter *writer,
2579                   int             seed)
2580 {
2581   unsigned char v;
2582
2583   v = BYTE_FROM_SEED (seed);
2584
2585   return _dbus_type_writer_write_basic (writer,
2586                                         node->klass->typecode,
2587                                         &v);
2588 }
2589
2590 static dbus_bool_t
2591 byte_read_value (TestTypeNode   *node,
2592                  DBusTypeReader *reader,
2593                  int             seed)
2594 {
2595   unsigned char v;
2596
2597   check_expected_type (reader, node->klass->typecode);
2598
2599   _dbus_type_reader_read_basic (reader,
2600                                 (unsigned char*) &v);
2601
2602   _dbus_assert (v == BYTE_FROM_SEED (seed));
2603
2604   return TRUE;
2605 }
2606
2607
2608 static dbus_bool_t
2609 byte_set_value (TestTypeNode   *node,
2610                 DBusTypeReader *reader,
2611                 DBusTypeReader *realign_root,
2612                 int             seed)
2613 {
2614   unsigned char v;
2615
2616   v = BYTE_FROM_SEED (seed);
2617
2618   return _dbus_type_reader_set_basic (reader,
2619                                       &v,
2620                                       realign_root);
2621 }
2622
2623 static double
2624 double_from_seed (int seed)
2625 {
2626   return SAMPLE_INT32 * (double) seed + 0.3;
2627 }
2628
2629 static dbus_bool_t
2630 double_write_value (TestTypeNode   *node,
2631                     DataBlock      *block,
2632                     DBusTypeWriter *writer,
2633                     int             seed)
2634 {
2635   double v;
2636
2637   v = double_from_seed (seed);
2638
2639   return _dbus_type_writer_write_basic (writer,
2640                                         node->klass->typecode,
2641                                         &v);
2642 }
2643
2644 static dbus_bool_t
2645 double_read_value (TestTypeNode   *node,
2646                    DBusTypeReader *reader,
2647                    int             seed)
2648 {
2649   double v;
2650   double expected;
2651
2652   check_expected_type (reader, node->klass->typecode);
2653
2654   _dbus_type_reader_read_basic (reader,
2655                                 (double*) &v);
2656
2657   expected = double_from_seed (seed);
2658
2659   if (!_DBUS_DOUBLES_BITWISE_EQUAL (v, expected))
2660     {
2661 #ifdef DBUS_HAVE_INT64
2662       _dbus_warn ("Expected double %g got %g\n bits = 0x%llx vs.\n bits = 0x%llx)\n",
2663                   expected, v,
2664                   *(dbus_uint64_t*)(char*)&expected,
2665                   *(dbus_uint64_t*)(char*)&v);
2666 #endif
2667       _dbus_assert_not_reached ("test failed");
2668     }
2669
2670   return TRUE;
2671 }
2672
2673 static dbus_bool_t
2674 double_set_value (TestTypeNode   *node,
2675                 DBusTypeReader *reader,
2676                 DBusTypeReader *realign_root,
2677                 int             seed)
2678 {
2679   double v;
2680
2681   v = double_from_seed (seed);
2682
2683   return _dbus_type_reader_set_basic (reader,
2684                                       &v,
2685                                       realign_root);
2686 }
2687
2688 #define MAX_SAMPLE_OBJECT_PATH_LEN 10
2689 static void
2690 object_path_from_seed (char *buf,
2691                        int   seed)
2692 {
2693   int i;
2694   unsigned char v;
2695   int len;
2696
2697   len = seed % 9;
2698   _dbus_assert (len < MAX_SAMPLE_OBJECT_PATH_LEN);
2699
2700   v = (unsigned char) ('A' + seed);
2701
2702   if (len < 2)
2703     {
2704       buf[0] = '/';
2705       i = 1;
2706     }
2707   else
2708     {
2709       i = 0;
2710       while (i + 1 < len)
2711         {
2712           if (v < 'A' || v > 'z')
2713             v = 'A';
2714
2715           buf[i] = '/';
2716           ++i;
2717           buf[i] = v;
2718           ++i;
2719           
2720           v += 1;
2721         }
2722     }
2723
2724   buf[i] = '\0';
2725 }
2726
2727 static dbus_bool_t
2728 object_path_write_value (TestTypeNode   *node,
2729                          DataBlock      *block,
2730                          DBusTypeWriter *writer,
2731                          int             seed)
2732 {
2733   char buf[MAX_SAMPLE_OBJECT_PATH_LEN];
2734   const char *v_string = buf;
2735
2736   object_path_from_seed (buf, seed);
2737
2738   return _dbus_type_writer_write_basic (writer,
2739                                         node->klass->typecode,
2740                                         &v_string);
2741 }
2742
2743 static dbus_bool_t
2744 object_path_read_value (TestTypeNode   *node,
2745                         DBusTypeReader *reader,
2746                         int             seed)
2747 {
2748   const char *v;
2749   char buf[MAX_SAMPLE_OBJECT_PATH_LEN];
2750
2751   check_expected_type (reader, node->klass->typecode);
2752
2753   _dbus_type_reader_read_basic (reader,
2754                                 (const char **) &v);
2755
2756   object_path_from_seed (buf, seed);
2757
2758   if (strcmp (buf, v) != 0)
2759     {
2760       _dbus_warn ("read object path '%s' expected '%s'\n",
2761                   v, buf);
2762       _dbus_assert_not_reached ("test failed");
2763     }
2764
2765   return TRUE;
2766 }
2767
2768 static dbus_bool_t
2769 object_path_set_value (TestTypeNode   *node,
2770                        DBusTypeReader *reader,
2771                        DBusTypeReader *realign_root,
2772                        int             seed)
2773 {
2774   char buf[MAX_SAMPLE_OBJECT_PATH_LEN];
2775   const char *v_string = buf;
2776
2777   object_path_from_seed (buf, seed);
2778
2779   return _dbus_type_reader_set_basic (reader,
2780                                       &v_string,
2781                                       realign_root);
2782 }
2783
2784 #define MAX_SAMPLE_SIGNATURE_LEN 10
2785 static void
2786 signature_from_seed (char *buf,
2787                      int   seed)
2788 {
2789   int i;
2790   const char *s;
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   s = sample_signatures[seed % _DBUS_N_ELEMENTS(sample_signatures)];
2802
2803   for (i = 0; s[i]; i++)
2804     {
2805       buf[i] = s[i];
2806     }
2807   buf[i] = '\0';
2808 }
2809
2810 static dbus_bool_t
2811 signature_write_value (TestTypeNode   *node,
2812                        DataBlock      *block,
2813                        DBusTypeWriter *writer,
2814                        int             seed)
2815 {
2816   char buf[MAX_SAMPLE_SIGNATURE_LEN];
2817   const char *v_string = buf;
2818
2819   signature_from_seed (buf, seed);
2820
2821   return _dbus_type_writer_write_basic (writer,
2822                                         node->klass->typecode,
2823                                         &v_string);
2824 }
2825
2826 static dbus_bool_t
2827 signature_read_value (TestTypeNode   *node,
2828                       DBusTypeReader *reader,
2829                       int             seed)
2830 {
2831   const char *v;
2832   char buf[MAX_SAMPLE_SIGNATURE_LEN];
2833
2834   check_expected_type (reader, node->klass->typecode);
2835
2836   _dbus_type_reader_read_basic (reader,
2837                                 (const char **) &v);
2838
2839   signature_from_seed (buf, seed);
2840
2841   if (strcmp (buf, v) != 0)
2842     {
2843       _dbus_warn ("read signature value '%s' expected '%s'\n",
2844                   v, buf);
2845       _dbus_assert_not_reached ("test failed");
2846     }
2847
2848   return TRUE;
2849 }
2850
2851
2852 static dbus_bool_t
2853 signature_set_value (TestTypeNode   *node,
2854                      DBusTypeReader *reader,
2855                      DBusTypeReader *realign_root,
2856                      int             seed)
2857 {
2858   char buf[MAX_SAMPLE_SIGNATURE_LEN];
2859   const char *v_string = buf;
2860
2861   signature_from_seed (buf, seed);
2862
2863   return _dbus_type_reader_set_basic (reader,
2864                                       &v_string,
2865                                       realign_root);
2866 }
2867
2868 static dbus_bool_t
2869 struct_write_value (TestTypeNode   *node,
2870                     DataBlock      *block,
2871                     DBusTypeWriter *writer,
2872                     int             seed)
2873 {
2874   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
2875   DataBlockState saved;
2876   DBusTypeWriter sub;
2877   int i;
2878   int n_copies;
2879
2880   n_copies = node->klass->subclass_detail;
2881
2882   _dbus_assert (container->children != NULL);
2883
2884   data_block_save (block, &saved);
2885
2886   if (!_dbus_type_writer_recurse (writer, DBUS_TYPE_STRUCT,
2887                                   NULL, 0,
2888                                   &sub))
2889     return FALSE;
2890
2891   i = 0;
2892   while (i < n_copies)
2893     {
2894       DBusList *link;
2895
2896       link = _dbus_list_get_first_link (&container->children);
2897       while (link != NULL)
2898         {
2899           TestTypeNode *child = link->data;
2900           DBusList *next = _dbus_list_get_next_link (&container->children, link);
2901
2902           if (!node_write_value (child, block, &sub, seed + i))
2903             {
2904               data_block_restore (block, &saved);
2905               return FALSE;
2906             }
2907
2908           link = next;
2909         }
2910
2911       ++i;
2912     }
2913
2914   if (!_dbus_type_writer_unrecurse (writer, &sub))
2915     {
2916       data_block_restore (block, &saved);
2917       return FALSE;
2918     }
2919
2920   return TRUE;
2921 }
2922
2923 static dbus_bool_t
2924 struct_read_or_set_value (TestTypeNode   *node,
2925                           DBusTypeReader *reader,
2926                           DBusTypeReader *realign_root,
2927                           int             seed)
2928 {
2929   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
2930   DBusTypeReader sub;
2931   int i;
2932   int n_copies;
2933
2934   n_copies = node->klass->subclass_detail;
2935
2936   check_expected_type (reader, DBUS_TYPE_STRUCT);
2937
2938   _dbus_type_reader_recurse (reader, &sub);
2939
2940   i = 0;
2941   while (i < n_copies)
2942     {
2943       DBusList *link;
2944
2945       link = _dbus_list_get_first_link (&container->children);
2946       while (link != NULL)
2947         {
2948           TestTypeNode *child = link->data;
2949           DBusList *next = _dbus_list_get_next_link (&container->children, link);
2950
2951           if (realign_root == NULL)
2952             {
2953               if (!node_read_value (child, &sub, seed + i))
2954                 return FALSE;
2955             }
2956           else
2957             {
2958               if (!node_set_value (child, &sub, realign_root, seed + i))
2959                 return FALSE;
2960             }
2961
2962           if (i == (n_copies - 1) && next == NULL)
2963             NEXT_EXPECTING_FALSE (&sub);
2964           else
2965             NEXT_EXPECTING_TRUE (&sub);
2966
2967           link = next;
2968         }
2969
2970       ++i;
2971     }
2972
2973   return TRUE;
2974 }
2975
2976 static dbus_bool_t
2977 struct_read_value (TestTypeNode   *node,
2978                    DBusTypeReader *reader,
2979                    int             seed)
2980 {
2981   return struct_read_or_set_value (node, reader, NULL, seed);
2982 }
2983
2984 static dbus_bool_t
2985 struct_set_value (TestTypeNode   *node,
2986                   DBusTypeReader *reader,
2987                   DBusTypeReader *realign_root,
2988                   int             seed)
2989 {
2990   return struct_read_or_set_value (node, reader, realign_root, seed);
2991 }
2992
2993 static dbus_bool_t
2994 struct_build_signature (TestTypeNode   *node,
2995                         DBusString     *str)
2996 {
2997   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
2998   int i;
2999   int orig_len;
3000   int n_copies;
3001
3002   n_copies = node->klass->subclass_detail;
3003
3004   orig_len = _dbus_string_get_length (str);
3005
3006   if (!_dbus_string_append_byte (str, DBUS_STRUCT_BEGIN_CHAR))
3007     goto oom;
3008
3009   i = 0;
3010   while (i < n_copies)
3011     {
3012       DBusList *link;
3013
3014       link = _dbus_list_get_first_link (&container->children);
3015       while (link != NULL)
3016         {
3017           TestTypeNode *child = link->data;
3018           DBusList *next = _dbus_list_get_next_link (&container->children, link);
3019
3020           if (!node_build_signature (child, str))
3021             goto oom;
3022
3023           link = next;
3024         }
3025
3026       ++i;
3027     }
3028
3029   if (!_dbus_string_append_byte (str, DBUS_STRUCT_END_CHAR))
3030     goto oom;
3031
3032   return TRUE;
3033
3034  oom:
3035   _dbus_string_set_length (str, orig_len);
3036   return FALSE;
3037 }
3038
3039 static dbus_bool_t
3040 array_write_value (TestTypeNode   *node,
3041                    DataBlock      *block,
3042                    DBusTypeWriter *writer,
3043                    int             seed)
3044 {
3045   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3046   DataBlockState saved;
3047   DBusTypeWriter sub;
3048   DBusString element_signature;
3049   int i;
3050   int n_copies;
3051   int element_type;
3052   TestTypeNode *child;
3053
3054   n_copies = node->klass->subclass_detail;
3055
3056   _dbus_assert (container->children != NULL);
3057
3058   data_block_save (block, &saved);
3059
3060   if (!_dbus_string_init (&element_signature))
3061     return FALSE;
3062
3063   child = _dbus_list_get_first (&container->children);
3064
3065   if (!node_build_signature (child,
3066                              &element_signature))
3067     goto oom;
3068
3069   element_type = _dbus_first_type_in_signature (&element_signature, 0);
3070
3071   if (!_dbus_type_writer_recurse (writer, DBUS_TYPE_ARRAY,
3072                                   &element_signature, 0,
3073                                   &sub))
3074     goto oom;
3075
3076   if (arrays_write_fixed_in_blocks &&
3077       dbus_type_is_fixed (element_type) &&
3078       child->klass->write_multi)
3079     {
3080       if (!node_write_multi (child, block, &sub, seed, n_copies))
3081         goto oom;
3082     }
3083   else
3084     {
3085       i = 0;
3086       while (i < n_copies)
3087         {
3088           DBusList *link;
3089
3090           link = _dbus_list_get_first_link (&container->children);
3091           while (link != NULL)
3092             {
3093               TestTypeNode *child = link->data;
3094               DBusList *next = _dbus_list_get_next_link (&container->children, link);
3095
3096               if (!node_write_value (child, block, &sub, seed + i))
3097                 goto oom;
3098
3099               link = next;
3100             }
3101
3102           ++i;
3103         }
3104     }
3105
3106   if (!_dbus_type_writer_unrecurse (writer, &sub))
3107     goto oom;
3108
3109   _dbus_string_free (&element_signature);
3110   return TRUE;
3111
3112  oom:
3113   data_block_restore (block, &saved);
3114   _dbus_string_free (&element_signature);
3115   return FALSE;
3116 }
3117
3118 static dbus_bool_t
3119 array_read_or_set_value (TestTypeNode   *node,
3120                          DBusTypeReader *reader,
3121                          DBusTypeReader *realign_root,
3122                          int             seed)
3123 {
3124   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3125   DBusTypeReader sub;
3126   int i;
3127   int n_copies;
3128   TestTypeNode *child;
3129
3130   n_copies = node->klass->subclass_detail;
3131
3132   check_expected_type (reader, DBUS_TYPE_ARRAY);
3133
3134   child = _dbus_list_get_first (&container->children);
3135
3136   if (n_copies > 0)
3137     {
3138       _dbus_type_reader_recurse (reader, &sub);
3139
3140       if (realign_root == NULL && arrays_write_fixed_in_blocks &&
3141           dbus_type_is_fixed (_dbus_type_reader_get_element_type (reader)) &&
3142           child->klass->read_multi)
3143         {
3144           if (!node_read_multi (child, &sub, seed, n_copies))
3145             return FALSE;
3146         }
3147       else
3148         {
3149           i = 0;
3150           while (i < n_copies)
3151             {
3152               DBusList *link;
3153
3154               link = _dbus_list_get_first_link (&container->children);
3155               while (link != NULL)
3156                 {
3157                   TestTypeNode *child = link->data;
3158                   DBusList *next = _dbus_list_get_next_link (&container->children, link);
3159
3160                   _dbus_assert (child->klass->typecode ==
3161                                 _dbus_type_reader_get_element_type (reader));
3162
3163                   if (realign_root == NULL)
3164                     {
3165                       if (!node_read_value (child, &sub, seed + i))
3166                         return FALSE;
3167                     }
3168                   else
3169                     {
3170                       if (!node_set_value (child, &sub, realign_root, seed + i))
3171                         return FALSE;
3172                     }
3173
3174                   if (i == (n_copies - 1) && next == NULL)
3175                     NEXT_EXPECTING_FALSE (&sub);
3176                   else
3177                     NEXT_EXPECTING_TRUE (&sub);
3178
3179                   link = next;
3180                 }
3181
3182               ++i;
3183             }
3184         }
3185     }
3186
3187   return TRUE;
3188 }
3189
3190 static dbus_bool_t
3191 array_read_value (TestTypeNode   *node,
3192                   DBusTypeReader *reader,
3193                   int             seed)
3194 {
3195   return array_read_or_set_value (node, reader, NULL, seed);
3196 }
3197
3198 static dbus_bool_t
3199 array_set_value (TestTypeNode   *node,
3200                  DBusTypeReader *reader,
3201                  DBusTypeReader *realign_root,
3202                  int             seed)
3203 {
3204   return array_read_or_set_value (node, reader, realign_root, seed);
3205 }
3206
3207 static dbus_bool_t
3208 array_build_signature (TestTypeNode   *node,
3209                        DBusString     *str)
3210 {
3211   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3212   int orig_len;
3213
3214   orig_len = _dbus_string_get_length (str);
3215
3216   if (!_dbus_string_append_byte (str, DBUS_TYPE_ARRAY))
3217     goto oom;
3218
3219   if (!node_build_signature (_dbus_list_get_first (&container->children),
3220                              str))
3221     goto oom;
3222
3223   return TRUE;
3224
3225  oom:
3226   _dbus_string_set_length (str, orig_len);
3227   return FALSE;
3228 }
3229
3230  /* 10 is random just to add another seed that we use in the suite */
3231 #define VARIANT_SEED 10
3232
3233 static dbus_bool_t
3234 variant_write_value (TestTypeNode   *node,
3235                      DataBlock      *block,
3236                      DBusTypeWriter *writer,
3237                      int             seed)
3238 {
3239   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3240   DataBlockState saved;
3241   DBusTypeWriter sub;
3242   DBusString content_signature;
3243   TestTypeNode *child;
3244
3245   _dbus_assert (container->children != NULL);
3246   _dbus_assert (_dbus_list_length_is_one (&container->children));
3247
3248   child = _dbus_list_get_first (&container->children);
3249
3250   data_block_save (block, &saved);
3251
3252   if (!_dbus_string_init (&content_signature))
3253     return FALSE;
3254
3255   if (!node_build_signature (child,
3256                              &content_signature))
3257     goto oom;
3258
3259   if (!_dbus_type_writer_recurse (writer, DBUS_TYPE_VARIANT,
3260                                   &content_signature, 0,
3261                                   &sub))
3262     goto oom;
3263
3264   if (!node_write_value (child, block, &sub, seed + VARIANT_SEED))
3265     goto oom;
3266
3267   if (!_dbus_type_writer_unrecurse (writer, &sub))
3268     goto oom;
3269
3270   _dbus_string_free (&content_signature);
3271   return TRUE;
3272
3273  oom:
3274   data_block_restore (block, &saved);
3275   _dbus_string_free (&content_signature);
3276   return FALSE;
3277 }
3278
3279 static dbus_bool_t
3280 variant_read_or_set_value (TestTypeNode   *node,
3281                            DBusTypeReader *reader,
3282                            DBusTypeReader *realign_root,
3283                            int             seed)
3284 {
3285   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3286   DBusTypeReader sub;
3287   TestTypeNode *child;
3288
3289   _dbus_assert (container->children != NULL);
3290   _dbus_assert (_dbus_list_length_is_one (&container->children));
3291
3292   child = _dbus_list_get_first (&container->children);
3293
3294   check_expected_type (reader, DBUS_TYPE_VARIANT);
3295
3296   _dbus_type_reader_recurse (reader, &sub);
3297
3298   if (realign_root == NULL)
3299     {
3300       if (!node_read_value (child, &sub, seed + VARIANT_SEED))
3301         return FALSE;
3302     }
3303   else
3304     {
3305       if (!node_set_value (child, &sub, realign_root, seed + VARIANT_SEED))
3306         return FALSE;
3307     }
3308
3309   NEXT_EXPECTING_FALSE (&sub);
3310
3311   return TRUE;
3312 }
3313
3314 static dbus_bool_t
3315 variant_read_value (TestTypeNode   *node,
3316                     DBusTypeReader *reader,
3317                     int             seed)
3318 {
3319   return variant_read_or_set_value (node, reader, NULL, seed);
3320 }
3321
3322 static dbus_bool_t
3323 variant_set_value (TestTypeNode   *node,
3324                    DBusTypeReader *reader,
3325                    DBusTypeReader *realign_root,
3326                    int             seed)
3327 {
3328   return variant_read_or_set_value (node, reader, realign_root, seed);
3329 }
3330
3331 static dbus_bool_t
3332 dict_write_value (TestTypeNode   *node,
3333                   DataBlock      *block,
3334                   DBusTypeWriter *writer,
3335                   int             seed)
3336 {
3337   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3338   DataBlockState saved;
3339   DBusTypeWriter sub;
3340   DBusString entry_value_signature;
3341   DBusString dict_entry_signature;
3342   int i;
3343   int n_entries;
3344   int entry_value_type;
3345   TestTypeNode *child;
3346
3347   n_entries = node->klass->subclass_detail;
3348
3349   _dbus_assert (container->children != NULL);
3350
3351   data_block_save (block, &saved);
3352
3353   if (!_dbus_string_init (&entry_value_signature))
3354     return FALSE;
3355
3356   if (!_dbus_string_init (&dict_entry_signature))
3357     {
3358       _dbus_string_free (&entry_value_signature);
3359       return FALSE;
3360     }
3361   
3362   child = _dbus_list_get_first (&container->children);
3363
3364   if (!node_build_signature (child,
3365                              &entry_value_signature))
3366     goto oom;
3367
3368   if (!_dbus_string_append (&dict_entry_signature,
3369                             DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
3370                             DBUS_TYPE_INT32_AS_STRING))
3371     goto oom;
3372
3373   if (!_dbus_string_copy (&entry_value_signature, 0,
3374                           &dict_entry_signature,
3375                           _dbus_string_get_length (&dict_entry_signature)))
3376     goto oom;
3377
3378   if (!_dbus_string_append_byte (&dict_entry_signature,
3379                                  DBUS_DICT_ENTRY_END_CHAR))
3380     goto oom;
3381   
3382   entry_value_type = _dbus_first_type_in_signature (&entry_value_signature, 0);
3383   
3384   if (!_dbus_type_writer_recurse (writer, DBUS_TYPE_ARRAY,
3385                                   &dict_entry_signature, 0,
3386                                   &sub))
3387     goto oom;
3388
3389   i = 0;
3390   while (i < n_entries)
3391     {
3392       DBusTypeWriter entry_sub;
3393       dbus_int32_t key;
3394
3395       if (!_dbus_type_writer_recurse (&sub, DBUS_TYPE_DICT_ENTRY,
3396                                       NULL, 0,
3397                                       &entry_sub))
3398         goto oom;
3399
3400       key = int32_from_seed (seed + i);
3401
3402       if (!_dbus_type_writer_write_basic (&entry_sub,
3403                                           DBUS_TYPE_INT32,
3404                                           &key))
3405         goto oom;
3406       
3407       if (!node_write_value (child, block, &entry_sub, seed + i))
3408         goto oom;
3409
3410       if (!_dbus_type_writer_unrecurse (&sub, &entry_sub))
3411         goto oom;
3412       
3413       ++i;
3414     }
3415
3416   if (!_dbus_type_writer_unrecurse (writer, &sub))
3417     goto oom;
3418   
3419   _dbus_string_free (&entry_value_signature);
3420   _dbus_string_free (&dict_entry_signature);
3421   return TRUE;
3422
3423  oom:
3424   data_block_restore (block, &saved);
3425   _dbus_string_free (&entry_value_signature);
3426   _dbus_string_free (&dict_entry_signature);
3427   return FALSE;
3428 }
3429
3430 static dbus_bool_t
3431 dict_read_or_set_value (TestTypeNode   *node,
3432                         DBusTypeReader *reader,
3433                         DBusTypeReader *realign_root,
3434                         int             seed)
3435 {
3436   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3437   DBusTypeReader sub;
3438   int i;
3439   int n_entries;
3440   TestTypeNode *child;
3441
3442   n_entries = node->klass->subclass_detail;
3443
3444   check_expected_type (reader, DBUS_TYPE_ARRAY);
3445
3446   child = _dbus_list_get_first (&container->children);
3447
3448   if (n_entries > 0)
3449     {
3450       _dbus_type_reader_recurse (reader, &sub);
3451
3452       check_expected_type (&sub, DBUS_TYPE_DICT_ENTRY);
3453       
3454       i = 0;
3455       while (i < n_entries)
3456         {
3457           DBusTypeReader entry_sub;
3458
3459           check_expected_type (&sub, DBUS_TYPE_DICT_ENTRY);
3460           
3461           _dbus_type_reader_recurse (&sub, &entry_sub);
3462           
3463           if (realign_root == NULL)
3464             {
3465               dbus_int32_t v;
3466               
3467               check_expected_type (&entry_sub, DBUS_TYPE_INT32);
3468
3469               _dbus_type_reader_read_basic (&entry_sub,
3470                                             (dbus_int32_t*) &v);
3471
3472               _dbus_assert (v == int32_from_seed (seed + i));
3473
3474               NEXT_EXPECTING_TRUE (&entry_sub);
3475               
3476               if (!node_read_value (child, &entry_sub, seed + i))
3477                 return FALSE;
3478
3479               NEXT_EXPECTING_FALSE (&entry_sub);
3480             }
3481           else
3482             {
3483               dbus_int32_t v;
3484               
3485               v = int32_from_seed (seed + i);
3486               
3487               if (!_dbus_type_reader_set_basic (&entry_sub,
3488                                                 &v,
3489                                                 realign_root))
3490                 return FALSE;
3491
3492               NEXT_EXPECTING_TRUE (&entry_sub);
3493               
3494               if (!node_set_value (child, &entry_sub, realign_root, seed + i))
3495                 return FALSE;
3496
3497               NEXT_EXPECTING_FALSE (&entry_sub);
3498             }
3499           
3500           if (i == (n_entries - 1))
3501             NEXT_EXPECTING_FALSE (&sub);
3502           else
3503             NEXT_EXPECTING_TRUE (&sub);
3504
3505           ++i;
3506         }
3507     }
3508
3509   return TRUE;
3510 }
3511
3512 static dbus_bool_t
3513 dict_read_value (TestTypeNode   *node,
3514                  DBusTypeReader *reader,
3515                  int             seed)
3516 {
3517   return dict_read_or_set_value (node, reader, NULL, seed);
3518 }
3519
3520 static dbus_bool_t
3521 dict_set_value (TestTypeNode   *node,
3522                 DBusTypeReader *reader,
3523                 DBusTypeReader *realign_root,
3524                 int             seed)
3525 {
3526   return dict_read_or_set_value (node, reader, realign_root, seed);
3527 }
3528
3529 static dbus_bool_t
3530 dict_build_signature (TestTypeNode   *node,
3531                       DBusString     *str)
3532 {
3533   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3534   int orig_len;
3535
3536   orig_len = _dbus_string_get_length (str);
3537
3538   if (!_dbus_string_append_byte (str, DBUS_TYPE_ARRAY))
3539     goto oom;
3540
3541   if (!_dbus_string_append (str, DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING DBUS_TYPE_INT32_AS_STRING))
3542     goto oom;
3543   
3544   if (!node_build_signature (_dbus_list_get_first (&container->children),
3545                              str))
3546     goto oom;
3547
3548   if (!_dbus_string_append_byte (str, DBUS_DICT_ENTRY_END_CHAR))
3549     goto oom;
3550
3551   return TRUE;
3552
3553  oom:
3554   _dbus_string_set_length (str, orig_len);
3555   return FALSE;
3556 }
3557
3558 static void
3559 container_destroy (TestTypeNode *node)
3560 {
3561   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3562   DBusList *link;
3563
3564   link = _dbus_list_get_first_link (&container->children);
3565   while (link != NULL)
3566     {
3567       TestTypeNode *child = link->data;
3568       DBusList *next = _dbus_list_get_next_link (&container->children, link);
3569
3570       node_destroy (child);
3571
3572       _dbus_list_free_link (link);
3573
3574       link = next;
3575     }
3576 }
3577
3578 #endif /* DBUS_BUILD_TESTS */