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