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->eight.first32 = 0;
42  value->eight.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->eight.first32 == rhs->eight.first32 &&
63        lhs->eight.second32 == rhs->eight.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  if (_dbus_getenv ("DBUS_TEST_SLOW") == NULL ||
1928      atoi (_dbus_getenv ("DBUS_TEST_SLOW")) < 1)
1929    {
1930      fprintf (stderr, "skipping remaining marshal-recursive tests, "
1931          "run with DBUS_TEST_SLOW=1 (or more) to enable\n");
1932      goto out;
1933    }
1934
1935  start_next_test ("Each container of each container of each value %d iterations\n",
1936                   N_CONTAINERS * N_CONTAINERS * N_VALUES);
1937  for (i = 0; i < N_CONTAINERS; i++)
1938    {
1939      const TestTypeNodeClass *outer_container_klass = container_nodes[i];
1940      TestTypeNode *outer_container = node_new (outer_container_klass);
1941
1942      for (j = 0; j < N_CONTAINERS; j++)
1943        {
1944          TestTypeNode *child;
1945          const TestTypeNodeClass *inner_container_klass = container_nodes[j];
1946          TestTypeNode *inner_container = node_new (inner_container_klass);
1947
1948          node_append_child (outer_container, inner_container);
1949
1950          m = 0;
1951          while ((child = value_generator (&m)))
1952            {
1953              node_append_child (inner_container, child);
1954
1955              run_test_nodes (&outer_container, 1);
1956
1957              _dbus_list_clear (&((TestTypeNodeContainer*)inner_container)->children);
1958              node_destroy (child);
1959            }
1960          _dbus_list_clear (&((TestTypeNodeContainer*)outer_container)->children);
1961          node_destroy (inner_container);
1962        }
1963      node_destroy (outer_container);
1964    }
1965
1966  start_next_test ("Each container of each container of each container of each value %d iterations\n",
1967                   N_CONTAINERS * N_CONTAINERS * N_CONTAINERS * N_VALUES);
1968  for (i = 0; i < N_CONTAINERS; i++)
1969    {
1970      const TestTypeNodeClass *outer_container_klass = container_nodes[i];
1971      TestTypeNode *outer_container = node_new (outer_container_klass);
1972
1973      for (j = 0; j < N_CONTAINERS; j++)
1974        {
1975          const TestTypeNodeClass *inner_container_klass = container_nodes[j];
1976          TestTypeNode *inner_container = node_new (inner_container_klass);
1977
1978          node_append_child (outer_container, inner_container);
1979
1980          for (k = 0; k < N_CONTAINERS; k++)
1981            {
1982              TestTypeNode *child;
1983              const TestTypeNodeClass *center_container_klass = container_nodes[k];
1984              TestTypeNode *center_container = node_new (center_container_klass);
1985
1986              node_append_child (inner_container, center_container);
1987
1988              m = 0;
1989              while ((child = value_generator (&m)))
1990                {
1991                  node_append_child (center_container, child);
1992
1993                  run_test_nodes (&outer_container, 1);
1994
1995                  _dbus_list_clear (&((TestTypeNodeContainer*)center_container)->children);
1996                  node_destroy (child);
1997                }
1998              _dbus_list_clear (&((TestTypeNodeContainer*)inner_container)->children);
1999              node_destroy (center_container);
2000            }
2001          _dbus_list_clear (&((TestTypeNodeContainer*)outer_container)->children);
2002          node_destroy (inner_container);
2003        }
2004      node_destroy (outer_container);
2005    }
2006
2007  /* This one takes a really long time (10 minutes on a Core2), so only enable
2008   * it if you're really sure */
2009  if (atoi (_dbus_getenv ("DBUS_TEST_SLOW")) < 2)
2010    {
2011      fprintf (stderr, "skipping really slow marshal-recursive test, "
2012          "run with DBUS_TEST_SLOW=2 (or more) to enable\n");
2013      goto out;
2014    }
2015
2016  start_next_test ("Each value,value,value triplet combination as toplevel, in all orders %d iterations\n",
2017                   N_VALUES * N_VALUES * N_VALUES);
2018  {
2019    TestTypeNode *nodes[3];
2020
2021    i = 0;
2022    while ((nodes[0] = value_generator (&i)))
2023      {
2024        j = 0;
2025        while ((nodes[1] = value_generator (&j)))
2026          {
2027            k = 0;
2028            while ((nodes[2] = value_generator (&k)))
2029              {
2030                run_test_nodes (nodes, 3);
2031
2032                node_destroy (nodes[2]);
2033              }
2034            node_destroy (nodes[1]);
2035          }
2036        node_destroy (nodes[0]);
2037      }
2038  }
2039
2040out:
2041  fprintf (stderr, "%d total iterations of recursive marshaling tests\n",
2042           n_iterations_completed_total);
2043  fprintf (stderr, "each iteration ran at initial offsets 0 through %d in both big and little endian\n",
2044           MAX_INITIAL_OFFSET);
2045  fprintf (stderr, "out of memory handling %s tested\n",
2046           TEST_OOM_HANDLING ? "was" : "was not");
2047}
2048
2049dbus_bool_t
2050_dbus_marshal_recursive_test (void)
2051{
2052  make_and_run_test_nodes ();
2053
2054  return TRUE;
2055}
2056
2057/*
2058 *
2059 *
2060 *         Implementations of each type node class
2061 *
2062 *
2063 *
2064 */
2065#define MAX_MULTI_COUNT 5
2066
2067#define SAMPLE_INT16           1234
2068#define SAMPLE_INT16_ALTERNATE 6785
2069static dbus_int16_t
2070int16_from_seed (int seed)
2071{
2072  /* Generate an integer value that's predictable from seed.  We could
2073   * just use seed itself, but that would only ever touch one byte of
2074   * the int so would miss some kinds of bug.
2075   */
2076  dbus_int16_t v;
2077
2078  v = 42; /* just to quiet compiler afaik */
2079  switch (seed % 5)
2080    {
2081    case 0:
2082      v = SAMPLE_INT16;
2083      break;
2084    case 1:
2085      v = SAMPLE_INT16_ALTERNATE;
2086      break;
2087    case 2:
2088      v = -1;
2089      break;
2090    case 3:
2091      v = _DBUS_INT16_MAX;
2092      break;
2093    case 4:
2094      v = 1;
2095      break;
2096    }
2097
2098  if (seed > 1)
2099    v *= seed; /* wraps around eventually, which is fine */
2100
2101  return v;
2102}
2103
2104static dbus_bool_t
2105int16_write_value (TestTypeNode   *node,
2106                   DataBlock      *block,
2107                   DBusTypeWriter *writer,
2108                   int             seed)
2109{
2110  /* also used for uint16 */
2111  dbus_int16_t v;
2112
2113  v = int16_from_seed (seed);
2114
2115  return _dbus_type_writer_write_basic (writer,
2116                                        node->klass->typecode,
2117                                        &v);
2118}
2119
2120static dbus_bool_t
2121int16_read_value (TestTypeNode   *node,
2122                  DBusTypeReader *reader,
2123                  int             seed)
2124{
2125  /* also used for uint16 */
2126  dbus_int16_t v;
2127
2128  check_expected_type (reader, node->klass->typecode);
2129
2130  _dbus_type_reader_read_basic (reader,
2131                                (dbus_int16_t*) &v);
2132
2133  _dbus_assert (v == int16_from_seed (seed));
2134
2135  return TRUE;
2136}
2137
2138static dbus_bool_t
2139int16_set_value (TestTypeNode   *node,
2140                 DBusTypeReader *reader,
2141                 DBusTypeReader *realign_root,
2142                 int             seed)
2143{
2144  /* also used for uint16 */
2145  dbus_int16_t v;
2146
2147  v = int16_from_seed (seed);
2148
2149  return _dbus_type_reader_set_basic (reader,
2150                                      &v,
2151                                      realign_root);
2152}
2153
2154static dbus_bool_t
2155int16_write_multi (TestTypeNode   *node,
2156                   DataBlock      *block,
2157                   DBusTypeWriter *writer,
2158                   int             seed,
2159                   int             count)
2160{
2161  /* also used for uint16 */
2162  dbus_int16_t values[MAX_MULTI_COUNT];
2163  dbus_int16_t *v_ARRAY_INT16 = values;
2164  int i;
2165
2166  for (i = 0; i < count; ++i)
2167    values[i] = int16_from_seed (seed + i);
2168
2169  return _dbus_type_writer_write_fixed_multi (writer,
2170                                              node->klass->typecode,
2171                                              &v_ARRAY_INT16, count);
2172}
2173
2174static dbus_bool_t
2175int16_read_multi (TestTypeNode   *node,
2176                  DBusTypeReader *reader,
2177                  int             seed,
2178                  int             count)
2179{
2180  /* also used for uint16 */
2181  dbus_int16_t *values;
2182  int n_elements;
2183  int i;
2184
2185  check_expected_type (reader, node->klass->typecode);
2186
2187  _dbus_type_reader_read_fixed_multi (reader,
2188                                      &values,
2189                                      &n_elements);
2190
2191  if (n_elements != count)
2192    _dbus_warn ("got %d elements expected %d\n", n_elements, count);
2193  _dbus_assert (n_elements == count);
2194
2195  for (i = 0; i < count; i++)
2196    _dbus_assert (((dbus_int16_t)_dbus_unpack_uint16 (reader->byte_order,
2197                                                      (const unsigned char*)values + (i * 2))) ==
2198                  int16_from_seed (seed + i));
2199
2200  return TRUE;
2201}
2202
2203
2204#define SAMPLE_INT32           12345678
2205#define SAMPLE_INT32_ALTERNATE 53781429
2206static dbus_int32_t
2207int32_from_seed (int seed)
2208{
2209  /* Generate an integer value that's predictable from seed.  We could
2210   * just use seed itself, but that would only ever touch one byte of
2211   * the int so would miss some kinds of bug.
2212   */
2213  dbus_int32_t v;
2214
2215  v = 42; /* just to quiet compiler afaik */
2216  switch (seed % 5)
2217    {
2218    case 0:
2219      v = SAMPLE_INT32;
2220      break;
2221    case 1:
2222      v = SAMPLE_INT32_ALTERNATE;
2223      break;
2224    case 2:
2225      v = -1;
2226      break;
2227    case 3:
2228      v = _DBUS_INT_MAX;
2229      break;
2230    case 4:
2231      v = 1;
2232      break;
2233    }
2234
2235  if (seed > 1)
2236    v *= seed; /* wraps around eventually, which is fine */
2237
2238  return v;
2239}
2240
2241static dbus_bool_t
2242int32_write_value (TestTypeNode   *node,
2243                   DataBlock      *block,
2244                   DBusTypeWriter *writer,
2245                   int             seed)
2246{
2247  /* also used for uint32 */
2248  dbus_int32_t v;
2249
2250  v = int32_from_seed (seed);
2251
2252  return _dbus_type_writer_write_basic (writer,
2253                                        node->klass->typecode,
2254                                        &v);
2255}
2256
2257static dbus_bool_t
2258int32_read_value (TestTypeNode   *node,
2259                  DBusTypeReader *reader,
2260                  int             seed)
2261{
2262  /* also used for uint32 */
2263  dbus_int32_t v;
2264
2265  check_expected_type (reader, node->klass->typecode);
2266
2267  _dbus_type_reader_read_basic (reader,
2268                                (dbus_int32_t*) &v);
2269
2270  _dbus_assert (v == int32_from_seed (seed));
2271
2272  return TRUE;
2273}
2274
2275static dbus_bool_t
2276int32_set_value (TestTypeNode   *node,
2277                 DBusTypeReader *reader,
2278                 DBusTypeReader *realign_root,
2279                 int             seed)
2280{
2281  /* also used for uint32 */
2282  dbus_int32_t v;
2283
2284  v = int32_from_seed (seed);
2285
2286  return _dbus_type_reader_set_basic (reader,
2287                                      &v,
2288                                      realign_root);
2289}
2290
2291static dbus_bool_t
2292int32_write_multi (TestTypeNode   *node,
2293                   DataBlock      *block,
2294                   DBusTypeWriter *writer,
2295                   int             seed,
2296                   int             count)
2297{
2298  /* also used for uint32 */
2299  dbus_int32_t values[MAX_MULTI_COUNT];
2300  dbus_int32_t *v_ARRAY_INT32 = values;
2301  int i;
2302
2303  for (i = 0; i < count; ++i)
2304    values[i] = int32_from_seed (seed + i);
2305
2306  return _dbus_type_writer_write_fixed_multi (writer,
2307                                              node->klass->typecode,
2308                                              &v_ARRAY_INT32, count);
2309}
2310
2311static dbus_bool_t
2312int32_read_multi (TestTypeNode   *node,
2313                  DBusTypeReader *reader,
2314                  int             seed,
2315                  int             count)
2316{
2317  /* also used for uint32 */
2318  dbus_int32_t *values;
2319  int n_elements;
2320  int i;
2321
2322  check_expected_type (reader, node->klass->typecode);
2323
2324  _dbus_type_reader_read_fixed_multi (reader,
2325                                      &values,
2326                                      &n_elements);
2327
2328  if (n_elements != count)
2329    _dbus_warn ("got %d elements expected %d\n", n_elements, count);
2330  _dbus_assert (n_elements == count);
2331
2332  for (i = 0; i < count; i++)
2333    _dbus_assert (((int)_dbus_unpack_uint32 (reader->byte_order,
2334                                             (const unsigned char*)values + (i * 4))) ==
2335                  int32_from_seed (seed + i));
2336
2337  return TRUE;
2338}
2339
2340#ifdef DBUS_HAVE_INT64
2341static dbus_int64_t
2342int64_from_seed (int seed)
2343{
2344  dbus_int32_t v32;
2345  dbus_int64_t v;
2346
2347  v32 = int32_from_seed (seed);
2348
2349  v = - (dbus_int32_t) ~ v32;
2350  v |= (((dbus_int64_t)v32) << 32);
2351
2352  return v;
2353}
2354#endif
2355
2356static dbus_bool_t
2357int64_write_value (TestTypeNode   *node,
2358                   DataBlock      *block,
2359                   DBusTypeWriter *writer,
2360                   int             seed)
2361{
2362#ifdef DBUS_HAVE_INT64
2363  /* also used for uint64 */
2364  dbus_int64_t v;
2365
2366  v = int64_from_seed (seed);
2367
2368  return _dbus_type_writer_write_basic (writer,
2369                                        node->klass->typecode,
2370                                        &v);
2371#else
2372  return TRUE;
2373#endif
2374}
2375
2376static dbus_bool_t
2377int64_read_value (TestTypeNode   *node,
2378                  DBusTypeReader *reader,
2379                  int             seed)
2380{
2381#ifdef DBUS_HAVE_INT64
2382  /* also used for uint64 */
2383  dbus_int64_t v;
2384
2385  check_expected_type (reader, node->klass->typecode);
2386
2387  _dbus_type_reader_read_basic (reader,
2388                                (dbus_int64_t*) &v);
2389
2390  _dbus_assert (v == int64_from_seed (seed));
2391
2392  return TRUE;
2393#else
2394  return TRUE;
2395#endif
2396}
2397
2398static dbus_bool_t
2399int64_set_value (TestTypeNode   *node,
2400                 DBusTypeReader *reader,
2401                 DBusTypeReader *realign_root,
2402                 int             seed)
2403{
2404#ifdef DBUS_HAVE_INT64
2405  /* also used for uint64 */
2406  dbus_int64_t v;
2407
2408  v = int64_from_seed (seed);
2409
2410  return _dbus_type_reader_set_basic (reader,
2411                                      &v,
2412                                      realign_root);
2413#else
2414  return TRUE;
2415#endif
2416}
2417
2418#define MAX_SAMPLE_STRING_LEN 10
2419static void
2420string_from_seed (char *buf,
2421                  int   len,
2422                  int   seed)
2423{
2424  int i;
2425  unsigned char v;
2426
2427  _dbus_assert (len < MAX_SAMPLE_STRING_LEN);
2428
2429  /* vary the length slightly, though we also have multiple string
2430   * value types for this, varying it here tests the set_value code
2431   */
2432  switch (seed % 3)
2433    {
2434    case 1:
2435      len += 2;
2436      break;
2437    case 2:
2438      len -= 2;
2439      break;
2440    }
2441  if (len < 0)
2442    len = 0;
2443
2444  v = (unsigned char) ('A' + seed);
2445
2446  i = 0;
2447  while (i < len)
2448    {
2449      if (v < 'A' || v > 'z')
2450        v = 'A';
2451
2452      buf[i] = v;
2453
2454      v += 1;
2455      ++i;
2456    }
2457
2458  buf[i] = '\0';
2459}
2460
2461static dbus_bool_t
2462string_write_value (TestTypeNode   *node,
2463                    DataBlock      *block,
2464                    DBusTypeWriter *writer,
2465                    int             seed)
2466{
2467  char buf[MAX_SAMPLE_STRING_LEN + 1]="";
2468  const char *v_string = buf;
2469
2470
2471  string_from_seed (buf, node->klass->subclass_detail,
2472                    seed);
2473
2474  return _dbus_type_writer_write_basic (writer,
2475                                        node->klass->typecode,
2476                                        &v_string);
2477}
2478
2479static dbus_bool_t
2480string_read_value (TestTypeNode   *node,
2481                   DBusTypeReader *reader,
2482                   int             seed)
2483{
2484  const char *v;
2485  char buf[MAX_SAMPLE_STRING_LEN + 1];
2486  v = buf;
2487
2488  check_expected_type (reader, node->klass->typecode);
2489
2490  _dbus_type_reader_read_basic (reader,
2491                                (const char **) &v);
2492
2493  string_from_seed (buf, node->klass->subclass_detail,
2494                    seed);
2495
2496  if (strcmp (buf, v) != 0)
2497    {
2498      _dbus_warn ("read string '%s' expected '%s'\n",
2499                  v, buf);
2500      _dbus_assert_not_reached ("test failed");
2501    }
2502
2503  return TRUE;
2504}
2505
2506static dbus_bool_t
2507string_set_value (TestTypeNode   *node,
2508                  DBusTypeReader *reader,
2509                  DBusTypeReader *realign_root,
2510                  int             seed)
2511{
2512  char buf[MAX_SAMPLE_STRING_LEN + 1];
2513  const char *v_string = buf;
2514
2515  string_from_seed (buf, node->klass->subclass_detail,
2516                    seed);
2517
2518#if RECURSIVE_MARSHAL_WRITE_TRACE
2519 {
2520   const char *old;
2521   _dbus_type_reader_read_basic (reader, &old);
2522   _dbus_verbose ("SETTING new string '%s' len %d in place of '%s' len %d\n",
2523                  v_string, strlen (v_string), old, strlen (old));
2524 }
2525#endif
2526
2527  return _dbus_type_reader_set_basic (reader,
2528                                      &v_string,
2529                                      realign_root);
2530}
2531
2532#define BOOL_FROM_SEED(seed) ((dbus_bool_t)((seed) % 2))
2533
2534static dbus_bool_t
2535bool_write_value (TestTypeNode   *node,
2536                  DataBlock      *block,
2537                  DBusTypeWriter *writer,
2538                  int             seed)
2539{
2540  dbus_bool_t v;
2541
2542  v = BOOL_FROM_SEED (seed);
2543
2544  return _dbus_type_writer_write_basic (writer,
2545                                        node->klass->typecode,
2546                                        &v);
2547}
2548
2549static dbus_bool_t
2550bool_read_value (TestTypeNode   *node,
2551                 DBusTypeReader *reader,
2552                 int             seed)
2553{
2554  dbus_bool_t v;
2555
2556  check_expected_type (reader, node->klass->typecode);
2557
2558  _dbus_type_reader_read_basic (reader,
2559                                (unsigned char*) &v);
2560
2561  _dbus_assert (v == BOOL_FROM_SEED (seed));
2562
2563  return TRUE;
2564}
2565
2566static dbus_bool_t
2567bool_set_value (TestTypeNode   *node,
2568                DBusTypeReader *reader,
2569                DBusTypeReader *realign_root,
2570                int             seed)
2571{
2572  dbus_bool_t v;
2573
2574  v = BOOL_FROM_SEED (seed);
2575
2576  return _dbus_type_reader_set_basic (reader,
2577                                      &v,
2578                                      realign_root);
2579}
2580
2581#define BYTE_FROM_SEED(seed) ((unsigned char) int32_from_seed (seed))
2582
2583static dbus_bool_t
2584byte_write_value (TestTypeNode   *node,
2585                  DataBlock      *block,
2586                  DBusTypeWriter *writer,
2587                  int             seed)
2588{
2589  unsigned char v;
2590
2591  v = BYTE_FROM_SEED (seed);
2592
2593  return _dbus_type_writer_write_basic (writer,
2594                                        node->klass->typecode,
2595                                        &v);
2596}
2597
2598static dbus_bool_t
2599byte_read_value (TestTypeNode   *node,
2600                 DBusTypeReader *reader,
2601                 int             seed)
2602{
2603  unsigned char v;
2604
2605  check_expected_type (reader, node->klass->typecode);
2606
2607  _dbus_type_reader_read_basic (reader,
2608                                (unsigned char*) &v);
2609
2610  _dbus_assert (v == BYTE_FROM_SEED (seed));
2611
2612  return TRUE;
2613}
2614
2615
2616static dbus_bool_t
2617byte_set_value (TestTypeNode   *node,
2618                DBusTypeReader *reader,
2619                DBusTypeReader *realign_root,
2620                int             seed)
2621{
2622  unsigned char v;
2623
2624  v = BYTE_FROM_SEED (seed);
2625
2626  return _dbus_type_reader_set_basic (reader,
2627                                      &v,
2628                                      realign_root);
2629}
2630
2631static double
2632double_from_seed (int seed)
2633{
2634  return SAMPLE_INT32 * (double) seed + 0.3;
2635}
2636
2637static dbus_bool_t
2638double_write_value (TestTypeNode   *node,
2639                    DataBlock      *block,
2640                    DBusTypeWriter *writer,
2641                    int             seed)
2642{
2643  double v;
2644
2645  v = double_from_seed (seed);
2646
2647  return _dbus_type_writer_write_basic (writer,
2648                                        node->klass->typecode,
2649                                        &v);
2650}
2651
2652static dbus_bool_t
2653double_read_value (TestTypeNode   *node,
2654                   DBusTypeReader *reader,
2655                   int             seed)
2656{
2657  double v;
2658  double expected;
2659
2660  check_expected_type (reader, node->klass->typecode);
2661
2662  _dbus_type_reader_read_basic (reader,
2663                                (double*) &v);
2664
2665  expected = double_from_seed (seed);
2666
2667  if (!_DBUS_DOUBLES_BITWISE_EQUAL (v, expected))
2668    {
2669#ifdef DBUS_INT64_PRINTF_MODIFIER
2670      _dbus_warn ("Expected double %g got %g\n bits = 0x%" DBUS_INT64_PRINTF_MODIFIER "x vs.\n bits = 0x%" DBUS_INT64_PRINTF_MODIFIER "x)\n",
2671                  expected, v,
2672                  *(dbus_uint64_t*)(char*)&expected,
2673                  *(dbus_uint64_t*)(char*)&v);
2674#endif
2675      _dbus_assert_not_reached ("test failed");
2676    }
2677
2678  return TRUE;
2679}
2680
2681static dbus_bool_t
2682double_set_value (TestTypeNode   *node,
2683                DBusTypeReader *reader,
2684                DBusTypeReader *realign_root,
2685                int             seed)
2686{
2687  double v;
2688
2689  v = double_from_seed (seed);
2690
2691  return _dbus_type_reader_set_basic (reader,
2692                                      &v,
2693                                      realign_root);
2694}
2695
2696#define MAX_SAMPLE_OBJECT_PATH_LEN 10
2697static void
2698object_path_from_seed (char *buf,
2699                       int   seed)
2700{
2701  int i;
2702  unsigned char v;
2703  int len;
2704
2705  len = seed % 9;
2706  _dbus_assert (len < MAX_SAMPLE_OBJECT_PATH_LEN);
2707
2708  v = (unsigned char) ('A' + seed);
2709
2710  if (len < 2)
2711    {
2712      buf[0] = '/';
2713      i = 1;
2714    }
2715  else
2716    {
2717      i = 0;
2718      while (i + 1 < len)
2719        {
2720          if (v < 'A' || v > 'z')
2721            v = 'A';
2722
2723          buf[i] = '/';
2724          ++i;
2725          buf[i] = v;
2726          ++i;
2727
2728          v += 1;
2729        }
2730    }
2731
2732  buf[i] = '\0';
2733}
2734
2735static dbus_bool_t
2736object_path_write_value (TestTypeNode   *node,
2737                         DataBlock      *block,
2738                         DBusTypeWriter *writer,
2739                         int             seed)
2740{
2741  char buf[MAX_SAMPLE_OBJECT_PATH_LEN + 1];
2742  const char *v_string = buf;
2743
2744  object_path_from_seed (buf, seed);
2745
2746  return _dbus_type_writer_write_basic (writer,
2747                                        node->klass->typecode,
2748                                        &v_string);
2749}
2750
2751static dbus_bool_t
2752object_path_read_value (TestTypeNode   *node,
2753                        DBusTypeReader *reader,
2754                        int             seed)
2755{
2756  const char *v;
2757  char buf[MAX_SAMPLE_OBJECT_PATH_LEN + 1];
2758
2759  check_expected_type (reader, node->klass->typecode);
2760
2761  _dbus_type_reader_read_basic (reader,
2762                                (const char **) &v);
2763
2764  object_path_from_seed (buf, seed);
2765
2766  if (strcmp (buf, v) != 0)
2767    {
2768      _dbus_warn ("read object path '%s' expected '%s'\n",
2769                  v, buf);
2770      _dbus_assert_not_reached ("test failed");
2771    }
2772
2773  return TRUE;
2774}
2775
2776static dbus_bool_t
2777object_path_set_value (TestTypeNode   *node,
2778                       DBusTypeReader *reader,
2779                       DBusTypeReader *realign_root,
2780                       int             seed)
2781{
2782  char buf[MAX_SAMPLE_OBJECT_PATH_LEN + 1];
2783  const char *v_string = buf;
2784
2785  object_path_from_seed (buf, seed);
2786
2787  return _dbus_type_reader_set_basic (reader,
2788                                      &v_string,
2789                                      realign_root);
2790}
2791
2792#define MAX_SAMPLE_SIGNATURE_LEN 10
2793static void
2794signature_from_seed (char *buf,
2795                     int   seed)
2796{
2797  /* try to avoid ascending, descending, or alternating length to help find bugs */
2798  const char *sample_signatures[] = {
2799    "asax"
2800    "",
2801    "asau(xxxx)",
2802    "x",
2803    "ai",
2804    "a(ii)"
2805  };
2806
2807  strcpy (buf, sample_signatures[seed % _DBUS_N_ELEMENTS(sample_signatures)]);
2808}
2809
2810static dbus_bool_t
2811signature_write_value (TestTypeNode   *node,
2812                       DataBlock      *block,
2813                       DBusTypeWriter *writer,
2814                       int             seed)
2815{
2816  char buf[MAX_SAMPLE_SIGNATURE_LEN + 1];
2817  const char *v_string = buf;
2818
2819  signature_from_seed (buf, seed);
2820
2821  return _dbus_type_writer_write_basic (writer,
2822                                        node->klass->typecode,
2823                                        &v_string);
2824}
2825
2826static dbus_bool_t
2827signature_read_value (TestTypeNode   *node,
2828                      DBusTypeReader *reader,
2829                      int             seed)
2830{
2831  const char *v;
2832  char buf[MAX_SAMPLE_SIGNATURE_LEN + 1];
2833
2834  check_expected_type (reader, node->klass->typecode);
2835
2836  _dbus_type_reader_read_basic (reader,
2837                                (const char **) &v);
2838
2839  signature_from_seed (buf, seed);
2840
2841  if (strcmp (buf, v) != 0)
2842    {
2843      _dbus_warn ("read signature value '%s' expected '%s'\n",
2844                  v, buf);
2845      _dbus_assert_not_reached ("test failed");
2846    }
2847
2848  return TRUE;
2849}
2850
2851
2852static dbus_bool_t
2853signature_set_value (TestTypeNode   *node,
2854                     DBusTypeReader *reader,
2855                     DBusTypeReader *realign_root,
2856                     int             seed)
2857{
2858  char buf[MAX_SAMPLE_SIGNATURE_LEN + 1];
2859  const char *v_string = buf;
2860
2861  signature_from_seed (buf, seed);
2862
2863  return _dbus_type_reader_set_basic (reader,
2864                                      &v_string,
2865                                      realign_root);
2866}
2867
2868static dbus_bool_t
2869struct_write_value (TestTypeNode   *node,
2870                    DataBlock      *block,
2871                    DBusTypeWriter *writer,
2872                    int             seed)
2873{
2874  TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
2875  DataBlockState saved;
2876  DBusTypeWriter sub;
2877  int i;
2878  int n_copies;
2879
2880  n_copies = node->klass->subclass_detail;
2881
2882  _dbus_assert (container->children != NULL);
2883
2884  data_block_save (block, &saved);
2885
2886  if (!_dbus_type_writer_recurse (writer, DBUS_TYPE_STRUCT,
2887                                  NULL, 0,
2888                                  &sub))
2889    return FALSE;
2890
2891  i = 0;
2892  while (i < n_copies)
2893    {
2894      DBusList *link;
2895
2896      link = _dbus_list_get_first_link (&container->children);
2897      while (link != NULL)
2898        {
2899          TestTypeNode *child = link->data;
2900          DBusList *next = _dbus_list_get_next_link (&container->children, link);
2901
2902          if (!node_write_value (child, block, &sub, seed + i))
2903            {
2904              data_block_restore (block, &saved);
2905              return FALSE;
2906            }
2907
2908          link = next;
2909        }
2910
2911      ++i;
2912    }
2913
2914  if (!_dbus_type_writer_unrecurse (writer, &sub))
2915    {
2916      data_block_restore (block, &saved);
2917      return FALSE;
2918    }
2919
2920  return TRUE;
2921}
2922
2923static dbus_bool_t
2924struct_read_or_set_value (TestTypeNode   *node,
2925                          DBusTypeReader *reader,
2926                          DBusTypeReader *realign_root,
2927                          int             seed)
2928{
2929  TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
2930  DBusTypeReader sub;
2931  int i;
2932  int n_copies;
2933
2934  n_copies = node->klass->subclass_detail;
2935
2936  check_expected_type (reader, DBUS_TYPE_STRUCT);
2937
2938  _dbus_type_reader_recurse (reader, &sub);
2939
2940  i = 0;
2941  while (i < n_copies)
2942    {
2943      DBusList *link;
2944
2945      link = _dbus_list_get_first_link (&container->children);
2946      while (link != NULL)
2947        {
2948          TestTypeNode *child = link->data;
2949          DBusList *next = _dbus_list_get_next_link (&container->children, link);
2950
2951          if (realign_root == NULL)
2952            {
2953              if (!node_read_value (child, &sub, seed + i))
2954                return FALSE;
2955            }
2956          else
2957            {
2958              if (!node_set_value (child, &sub, realign_root, seed + i))
2959                return FALSE;
2960            }
2961
2962          if (i == (n_copies - 1) && next == NULL)
2963            NEXT_EXPECTING_FALSE (&sub);
2964          else
2965            NEXT_EXPECTING_TRUE (&sub);
2966
2967          link = next;
2968        }
2969
2970      ++i;
2971    }
2972
2973  return TRUE;
2974}
2975
2976static dbus_bool_t
2977struct_read_value (TestTypeNode   *node,
2978                   DBusTypeReader *reader,
2979                   int             seed)
2980{
2981  return struct_read_or_set_value (node, reader, NULL, seed);
2982}
2983
2984static dbus_bool_t
2985struct_set_value (TestTypeNode   *node,
2986                  DBusTypeReader *reader,
2987                  DBusTypeReader *realign_root,
2988                  int             seed)
2989{
2990  return struct_read_or_set_value (node, reader, realign_root, seed);
2991}
2992
2993static dbus_bool_t
2994struct_build_signature (TestTypeNode   *node,
2995                        DBusString     *str)
2996{
2997  TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
2998  int i;
2999  int orig_len;
3000  int n_copies;
3001
3002  n_copies = node->klass->subclass_detail;
3003
3004  orig_len = _dbus_string_get_length (str);
3005
3006  if (!_dbus_string_append_byte (str, DBUS_STRUCT_BEGIN_CHAR))
3007    goto oom;
3008
3009  i = 0;
3010  while (i < n_copies)
3011    {
3012      DBusList *link;
3013
3014      link = _dbus_list_get_first_link (&container->children);
3015      while (link != NULL)
3016        {
3017          TestTypeNode *child = link->data;
3018          DBusList *next = _dbus_list_get_next_link (&container->children, link);
3019
3020          if (!node_build_signature (child, str))
3021            goto oom;
3022
3023          link = next;
3024        }
3025
3026      ++i;
3027    }
3028
3029  if (!_dbus_string_append_byte (str, DBUS_STRUCT_END_CHAR))
3030    goto oom;
3031
3032  return TRUE;
3033
3034 oom:
3035  _dbus_string_set_length (str, orig_len);
3036  return FALSE;
3037}
3038
3039static dbus_bool_t
3040array_write_value (TestTypeNode   *node,
3041                   DataBlock      *block,
3042                   DBusTypeWriter *writer,
3043                   int             seed)
3044{
3045  TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3046  DataBlockState saved;
3047  DBusTypeWriter sub;
3048  DBusString element_signature;
3049  int i;
3050  int n_copies;
3051  int element_type;
3052  TestTypeNode *child;
3053
3054  n_copies = node->klass->subclass_detail;
3055
3056  _dbus_assert (container->children != NULL);
3057
3058  data_block_save (block, &saved);
3059
3060  if (!_dbus_string_init (&element_signature))
3061    return FALSE;
3062
3063  child = _dbus_list_get_first (&container->children);
3064
3065  if (!node_build_signature (child,
3066                             &element_signature))
3067    goto oom;
3068
3069  element_type = _dbus_first_type_in_signature (&element_signature, 0);
3070
3071  if (!_dbus_type_writer_recurse (writer, DBUS_TYPE_ARRAY,
3072                                  &element_signature, 0,
3073                                  &sub))
3074    goto oom;
3075
3076  if (arrays_write_fixed_in_blocks &&
3077      dbus_type_is_fixed (element_type) &&
3078      child->klass->write_multi)
3079    {
3080      if (!node_write_multi (child, block, &sub, seed, n_copies))
3081        goto oom;
3082    }
3083  else
3084    {
3085      i = 0;
3086      while (i < n_copies)
3087        {
3088          DBusList *link;
3089
3090          link = _dbus_list_get_first_link (&container->children);
3091          while (link != NULL)
3092            {
3093              TestTypeNode *child = link->data;
3094              DBusList *next = _dbus_list_get_next_link (&container->children, link);
3095
3096              if (!node_write_value (child, block, &sub, seed + i))
3097                goto oom;
3098
3099              link = next;
3100            }
3101
3102          ++i;
3103        }
3104    }
3105
3106  if (!_dbus_type_writer_unrecurse (writer, &sub))
3107    goto oom;
3108
3109  _dbus_string_free (&element_signature);
3110  return TRUE;
3111
3112 oom:
3113  data_block_restore (block, &saved);
3114  _dbus_string_free (&element_signature);
3115  return FALSE;
3116}
3117
3118static dbus_bool_t
3119array_read_or_set_value (TestTypeNode   *node,
3120                         DBusTypeReader *reader,
3121                         DBusTypeReader *realign_root,
3122                         int             seed)
3123{
3124  TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3125  DBusTypeReader sub;
3126  int i;
3127  int n_copies;
3128  TestTypeNode *child;
3129
3130  n_copies = node->klass->subclass_detail;
3131
3132  check_expected_type (reader, DBUS_TYPE_ARRAY);
3133
3134  child = _dbus_list_get_first (&container->children);
3135
3136  if (n_copies > 0)
3137    {
3138      _dbus_type_reader_recurse (reader, &sub);
3139
3140      if (realign_root == NULL && arrays_write_fixed_in_blocks &&
3141          dbus_type_is_fixed (_dbus_type_reader_get_element_type (reader)) &&
3142          child->klass->read_multi)
3143        {
3144          if (!node_read_multi (child, &sub, seed, n_copies))
3145            return FALSE;
3146        }
3147      else
3148        {
3149          i = 0;
3150          while (i < n_copies)
3151            {
3152              DBusList *link;
3153
3154              link = _dbus_list_get_first_link (&container->children);
3155              while (link != NULL)
3156                {
3157                  TestTypeNode *child = link->data;
3158                  DBusList *next = _dbus_list_get_next_link (&container->children, link);
3159
3160                  _dbus_assert (child->klass->typecode ==
3161                                _dbus_type_reader_get_element_type (reader));
3162
3163                  if (realign_root == NULL)
3164                    {
3165                      if (!node_read_value (child, &sub, seed + i))
3166                        return FALSE;
3167                    }
3168                  else
3169                    {
3170                      if (!node_set_value (child, &sub, realign_root, seed + i))
3171                        return FALSE;
3172                    }
3173
3174                  if (i == (n_copies - 1) && next == NULL)
3175                    NEXT_EXPECTING_FALSE (&sub);
3176                  else
3177                    NEXT_EXPECTING_TRUE (&sub);
3178
3179                  link = next;
3180                }
3181
3182              ++i;
3183            }
3184        }
3185    }
3186
3187  return TRUE;
3188}
3189
3190static dbus_bool_t
3191array_read_value (TestTypeNode   *node,
3192                  DBusTypeReader *reader,
3193                  int             seed)
3194{
3195  return array_read_or_set_value (node, reader, NULL, seed);
3196}
3197
3198static dbus_bool_t
3199array_set_value (TestTypeNode   *node,
3200                 DBusTypeReader *reader,
3201                 DBusTypeReader *realign_root,
3202                 int             seed)
3203{
3204  return array_read_or_set_value (node, reader, realign_root, seed);
3205}
3206
3207static dbus_bool_t
3208array_build_signature (TestTypeNode   *node,
3209                       DBusString     *str)
3210{
3211  TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3212  int orig_len;
3213
3214  orig_len = _dbus_string_get_length (str);
3215
3216  if (!_dbus_string_append_byte (str, DBUS_TYPE_ARRAY))
3217    goto oom;
3218
3219  if (!node_build_signature (_dbus_list_get_first (&container->children),
3220                             str))
3221    goto oom;
3222
3223  return TRUE;
3224
3225 oom:
3226  _dbus_string_set_length (str, orig_len);
3227  return FALSE;
3228}
3229
3230 /* 10 is random just to add another seed that we use in the suite */
3231#define VARIANT_SEED 10
3232
3233static dbus_bool_t
3234variant_write_value (TestTypeNode   *node,
3235                     DataBlock      *block,
3236                     DBusTypeWriter *writer,
3237                     int             seed)
3238{
3239  TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3240  DataBlockState saved;
3241  DBusTypeWriter sub;
3242  DBusString content_signature;
3243  TestTypeNode *child;
3244
3245  _dbus_assert (container->children != NULL);
3246  _dbus_assert (_dbus_list_length_is_one (&container->children));
3247
3248  child = _dbus_list_get_first (&container->children);
3249
3250  data_block_save (block, &saved);
3251
3252  if (!_dbus_string_init (&content_signature))
3253    return FALSE;
3254
3255  if (!node_build_signature (child,
3256                             &content_signature))
3257    goto oom;
3258
3259  if (!_dbus_type_writer_recurse (writer, DBUS_TYPE_VARIANT,
3260                                  &content_signature, 0,
3261                                  &sub))
3262    goto oom;
3263
3264  if (!node_write_value (child, block, &sub, seed + VARIANT_SEED))
3265    goto oom;
3266
3267  if (!_dbus_type_writer_unrecurse (writer, &sub))
3268    goto oom;
3269
3270  _dbus_string_free (&content_signature);
3271  return TRUE;
3272
3273 oom:
3274  data_block_restore (block, &saved);
3275  _dbus_string_free (&content_signature);
3276  return FALSE;
3277}
3278
3279static dbus_bool_t
3280variant_read_or_set_value (TestTypeNode   *node,
3281                           DBusTypeReader *reader,
3282                           DBusTypeReader *realign_root,
3283                           int             seed)
3284{
3285  TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3286  DBusTypeReader sub;
3287  TestTypeNode *child;
3288
3289  _dbus_assert (container->children != NULL);
3290  _dbus_assert (_dbus_list_length_is_one (&container->children));
3291
3292  child = _dbus_list_get_first (&container->children);
3293
3294  check_expected_type (reader, DBUS_TYPE_VARIANT);
3295
3296  _dbus_type_reader_recurse (reader, &sub);
3297
3298  if (realign_root == NULL)
3299    {
3300      if (!node_read_value (child, &sub, seed + VARIANT_SEED))
3301        return FALSE;
3302    }
3303  else
3304    {
3305      if (!node_set_value (child, &sub, realign_root, seed + VARIANT_SEED))
3306        return FALSE;
3307    }
3308
3309  NEXT_EXPECTING_FALSE (&sub);
3310
3311  return TRUE;
3312}
3313
3314static dbus_bool_t
3315variant_read_value (TestTypeNode   *node,
3316                    DBusTypeReader *reader,
3317                    int             seed)
3318{
3319  return variant_read_or_set_value (node, reader, NULL, seed);
3320}
3321
3322static dbus_bool_t
3323variant_set_value (TestTypeNode   *node,
3324                   DBusTypeReader *reader,
3325                   DBusTypeReader *realign_root,
3326                   int             seed)
3327{
3328  return variant_read_or_set_value (node, reader, realign_root, seed);
3329}
3330
3331static dbus_bool_t
3332dict_write_value (TestTypeNode   *node,
3333                  DataBlock      *block,
3334                  DBusTypeWriter *writer,
3335                  int             seed)
3336{
3337  TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3338  DataBlockState saved;
3339  DBusTypeWriter sub;
3340  DBusString entry_value_signature;
3341  DBusString dict_entry_signature;
3342  int i;
3343  int n_entries;
3344  TestTypeNode *child;
3345
3346  n_entries = node->klass->subclass_detail;
3347
3348  _dbus_assert (container->children != NULL);
3349
3350  data_block_save (block, &saved);
3351
3352  if (!_dbus_string_init (&entry_value_signature))
3353    return FALSE;
3354
3355  if (!_dbus_string_init (&dict_entry_signature))
3356    {
3357      _dbus_string_free (&entry_value_signature);
3358      return FALSE;
3359    }
3360
3361  child = _dbus_list_get_first (&container->children);
3362
3363  if (!node_build_signature (child,
3364                             &entry_value_signature))
3365    goto oom;
3366
3367  if (!_dbus_string_append (&dict_entry_signature,
3368                            DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
3369                            DBUS_TYPE_INT32_AS_STRING))
3370    goto oom;
3371
3372  if (!_dbus_string_copy (&entry_value_signature, 0,
3373                          &dict_entry_signature,
3374                          _dbus_string_get_length (&dict_entry_signature)))
3375    goto oom;
3376
3377  if (!_dbus_string_append_byte (&dict_entry_signature,
3378                                 DBUS_DICT_ENTRY_END_CHAR))
3379    goto oom;
3380
3381  if (!_dbus_type_writer_recurse (writer, DBUS_TYPE_ARRAY,
3382                                  &dict_entry_signature, 0,
3383                                  &sub))
3384    goto oom;
3385
3386  i = 0;
3387  while (i < n_entries)
3388    {
3389      DBusTypeWriter entry_sub;
3390      dbus_int32_t key;
3391
3392      if (!_dbus_type_writer_recurse (&sub, DBUS_TYPE_DICT_ENTRY,
3393                                      NULL, 0,
3394                                      &entry_sub))
3395        goto oom;
3396
3397      key = int32_from_seed (seed + i);
3398
3399      if (!_dbus_type_writer_write_basic (&entry_sub,
3400                                          DBUS_TYPE_INT32,
3401                                          &key))
3402        goto oom;
3403
3404      if (!node_write_value (child, block, &entry_sub, seed + i))
3405        goto oom;
3406
3407      if (!_dbus_type_writer_unrecurse (&sub, &entry_sub))
3408        goto oom;
3409
3410      ++i;
3411    }
3412
3413  if (!_dbus_type_writer_unrecurse (writer, &sub))
3414    goto oom;
3415
3416  _dbus_string_free (&entry_value_signature);
3417  _dbus_string_free (&dict_entry_signature);
3418  return TRUE;
3419
3420 oom:
3421  data_block_restore (block, &saved);
3422  _dbus_string_free (&entry_value_signature);
3423  _dbus_string_free (&dict_entry_signature);
3424  return FALSE;
3425}
3426
3427static dbus_bool_t
3428dict_read_or_set_value (TestTypeNode   *node,
3429                        DBusTypeReader *reader,
3430                        DBusTypeReader *realign_root,
3431                        int             seed)
3432{
3433  TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3434  DBusTypeReader sub;
3435  int i;
3436  int n_entries;
3437  TestTypeNode *child;
3438
3439  n_entries = node->klass->subclass_detail;
3440
3441  check_expected_type (reader, DBUS_TYPE_ARRAY);
3442
3443  child = _dbus_list_get_first (&container->children);
3444
3445  if (n_entries > 0)
3446    {
3447      _dbus_type_reader_recurse (reader, &sub);
3448
3449      check_expected_type (&sub, DBUS_TYPE_DICT_ENTRY);
3450
3451      i = 0;
3452      while (i < n_entries)
3453        {
3454          DBusTypeReader entry_sub;
3455
3456          check_expected_type (&sub, DBUS_TYPE_DICT_ENTRY);
3457
3458          _dbus_type_reader_recurse (&sub, &entry_sub);
3459
3460          if (realign_root == NULL)
3461            {
3462              dbus_int32_t v;
3463
3464              check_expected_type (&entry_sub, DBUS_TYPE_INT32);
3465
3466              _dbus_type_reader_read_basic (&entry_sub,
3467                                            (dbus_int32_t*) &v);
3468
3469              _dbus_assert (v == int32_from_seed (seed + i));
3470
3471              NEXT_EXPECTING_TRUE (&entry_sub);
3472
3473              if (!node_read_value (child, &entry_sub, seed + i))
3474                return FALSE;
3475
3476              NEXT_EXPECTING_FALSE (&entry_sub);
3477            }
3478          else
3479            {
3480              dbus_int32_t v;
3481
3482              v = int32_from_seed (seed + i);
3483
3484              if (!_dbus_type_reader_set_basic (&entry_sub,
3485                                                &v,
3486                                                realign_root))
3487                return FALSE;
3488
3489              NEXT_EXPECTING_TRUE (&entry_sub);
3490
3491              if (!node_set_value (child, &entry_sub, realign_root, seed + i))
3492                return FALSE;
3493
3494              NEXT_EXPECTING_FALSE (&entry_sub);
3495            }
3496
3497          if (i == (n_entries - 1))
3498            NEXT_EXPECTING_FALSE (&sub);
3499          else
3500            NEXT_EXPECTING_TRUE (&sub);
3501
3502          ++i;
3503        }
3504    }
3505
3506  return TRUE;
3507}
3508
3509static dbus_bool_t
3510dict_read_value (TestTypeNode   *node,
3511                 DBusTypeReader *reader,
3512                 int             seed)
3513{
3514  return dict_read_or_set_value (node, reader, NULL, seed);
3515}
3516
3517static dbus_bool_t
3518dict_set_value (TestTypeNode   *node,
3519                DBusTypeReader *reader,
3520                DBusTypeReader *realign_root,
3521                int             seed)
3522{
3523  return dict_read_or_set_value (node, reader, realign_root, seed);
3524}
3525
3526static dbus_bool_t
3527dict_build_signature (TestTypeNode   *node,
3528                      DBusString     *str)
3529{
3530  TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3531  int orig_len;
3532
3533  orig_len = _dbus_string_get_length (str);
3534
3535  if (!_dbus_string_append_byte (str, DBUS_TYPE_ARRAY))
3536    goto oom;
3537
3538  if (!_dbus_string_append (str, DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING DBUS_TYPE_INT32_AS_STRING))
3539    goto oom;
3540
3541  if (!node_build_signature (_dbus_list_get_first (&container->children),
3542                             str))
3543    goto oom;
3544
3545  if (!_dbus_string_append_byte (str, DBUS_DICT_ENTRY_END_CHAR))
3546    goto oom;
3547
3548  return TRUE;
3549
3550 oom:
3551  _dbus_string_set_length (str, orig_len);
3552  return FALSE;
3553}
3554
3555static void
3556container_destroy (TestTypeNode *node)
3557{
3558  TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3559  DBusList *link;
3560
3561  link = _dbus_list_get_first_link (&container->children);
3562  while (link != NULL)
3563    {
3564      TestTypeNode *child = link->data;
3565      DBusList *next = _dbus_list_get_next_link (&container->children, link);
3566
3567      node_destroy (child);
3568
3569      _dbus_list_free_link (link);
3570
3571      link = next;
3572    }
3573}
3574
3575#endif /* !DOXYGEN_SHOULD_SKIP_THIS */
3576
3577#endif /* DBUS_BUILD_TESTS */
3578