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