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