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