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