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