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