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