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