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